天天看點

用python自制微信機器人,定時發送天氣預報

wxpy基于itchat,使用了 Web 微信的通訊協定,通過大量接口優化提升了子產品的易用性,并進行豐富的功能擴充。實作了微信登入、收發消息、搜尋好友、資料統計、微信公衆号、微信好友、微信群基本資訊擷取等功能。

關注公衆号「Python專欄」,背景回複:**zsxq05**,擷取本文全套代碼!

0 引言

前段時間找到了一個免費的天氣預報API,費了好段時間把這個API解析并組裝成自己想用的格式了,就想着如何實作每天發送天氣資訊給自己。最近無意中發現了wxpy庫,用它來做再合适不過了。以下是wxpy庫的簡介:

wxpy基于itchat,使用了 Web 微信的通訊協定,通過大量接口優化提升了子產品的易用性,并進行豐富的功能擴充。實作了微信登入、收發消息、搜尋好友、資料統計、微信公衆号、微信好友、微信群基本資訊擷取等功能。

廢話不多說,代碼寫起來。

1 環境

作業系統:Windows / Linux

Python版本:3.7.2

2 代碼實作

我們要實作用Python來發微信,發送的内容是每天最新的天氣資訊。很明顯我們需要完成兩部分的準備,先來看看擷取天氣資訊這部分内容。

2.0 準備工作

本文我們用到的第三方庫有requests、wxpyy,若環境還沒有,按如下方式進行安裝即可。

pip install wxpy
pip install requests
           

2.1 擷取天氣資訊

這裡我使用的API的請求連結如下:

http://t.weather.sojson.com/api/weather/city/city_code

請求方式是GET方法,使用時注意更換為自己城市對應的city_code,除此之外不用帶任何參數。

請求是restfull風格,city_code為9位數字,如下示例:

{
  "_id": 58,
  "id": 59,
  "pid": 3,
  "city_code": "101230201",
  "city_name": "廈門"
}
           

大家可以從_city.json檔案中擷取各個城市對應的編号。該檔案我已經放在Github本文章對應的目錄下了,大家可自行查詢使用。

# weather API的URL,此處的城市編号,參看_city.json
url = \'http://t.weather.sojson.com/api/weather/city/101010200\'
header = {
    \'User-Agent\': \'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36\'
}

# 請求Weather API并拿到伺服器傳回的資料
rep = requests.get(url, headers = header)
rep.encoding = "utf-8"
result = \'\'
weather = rep.tex
           

這個API接口的傳回值内容很多,以下僅展示傳回的部分資訊。實際使用中僅用到三塊内容,首先是城市資訊。

"cityInfo": {
    "city": "海澱區", //請求城市
    "cityId": "101010200", //城市ID
    "parent": "北京市", //上級,一般是省份
    "updateTime": "09:02" //天氣更新時間
}
           

其次是,該城市目前天氣的空氣相關指數。

"data": {
    "shidu": "32%", //濕度
    "pm25": 35.0, //pm2.5
    "pm10": 97.0, //pm10
    "quality": "良", //空氣品質
    "wendu": "7", //溫度
    "ganmao": "極少數敏感人群應減少戶外活動", //感冒提醒(指數)
}
           

第三部分,該城市目前天氣的溫度風力等另外一些指數。

"forecast": [ //今天+未來14天
    {
        "date": "16", //日期
        "sunrise": "06: 28",
        "high": "高溫 20.0℃",
        "low": "低溫 2.0℃",
        "sunset": "18: 21",
        "aqi": 48.0, 
        "ymd": "2019-03-16", //年月日
        "week": "星期六",
        "fx": "西北風", //風向
        "fl": "3-4級", //風力
        "type": "晴",
        "notice": "願你擁有比陽光明媚的心情"
    }
]
           

注:這個API接口傳回值完整的示例,請見Github中本文章目錄下的weather.json檔案。

拿到傳回值之後,需要解析,并轉換組裝成我們想要的格式。

# 解析伺服器傳回的資料,具體可參考weather.json檔案
index_cityInfo = weather.find("cityInfo")
index_cityId = weather.find("cityId")
index_shidu = weather.find("shidu")
index_pm25 = weather.find("pm25")
index_pm10 = weather.find("pm10")
index_quality = weather.find("quality")
index_wendu = weather.find("wendu")
index_ganmao = weather.find("ganmao")
index_forecast = weather.find("forecast")
index_ymd = weather.find("ymd", index_forecast)
index_week = weather.find("week", index_forecast)
index_sunset = weather.find("sunset", index_forecast)
index_high = weather.find("high", index_forecast)
index_low = weather.find("low", index_forecast)
index_fx = weather.find("fx", index_forecast)
index_fl = weather.find("fl", index_forecast)
index_aqi = weather.find("aqi", index_forecast)
index_type = weather.find("type", index_forecast)
index_notice = weather.find("notice", index_forecast)
           

這是我最終想達到的效果如下:

# 今日天氣預報
# 年月日 + 星期 + 所在地城市
# 天氣類型 + 風向 + 風力
# 溫度範圍(最低溫度~最高溫度)
# 污染指數:PM2.5/PM10/AQI
# 空氣品質
# 目前溫度 + 空氣濕度
# Notice資訊
           

轉換化具體代碼就是這樣子的:

result = \'今日天氣預報\' + \'\n\' \
    + weather[index_ymd + 6:index_week - 3] + " " \
    + weather[index_week + 7:index_fx - 3] + " " \
    + weather[index_cityInfo + 19:index_cityId - 3] + \'\n\' \
    + "天氣: " + weather[index_type + 7:index_notice - 3] + " " \
    + weather[index_fx + 5:index_fl - 3] \
    + weather[index_fl + 5:index_type - 3] + \'\n\' \
    + "溫度範圍:" + weather[index_low + 9:index_sunset - 3] + " ~" \
    + weather[index_high + 10:index_low - 3] + \'\n\' \
    + "污染指數: PM2.5:" + weather[index_pm25 + 6:index_pm10 - 1] + "" \
    + "PM10:" + weather[index_pm10 + 6:index_quality - 1] + " " \
    + "AQI:" + weather[index_aqi + 5:index_ymd - 2] + \'\n\' \
    + "空氣品質:" + weather[index_quality + 10:index_wendu - 3] + \'\n\' \
    + "目前溫度:" + weather[index_wendu + 8:index_ganmao - 3] + " " \
    + "空氣濕度:" + weather[index_shidu + 8:index_pm25 - 3] + \'\n\' \
    + weather[index_notice + 9:weather.find(\'}\', index_notice) - 1]
           

這樣我們的第一步,擷取天氣資訊就完成了。接下來就是登入微信定時發送消息了。

2.2 登入微信定時發送消息

首先要登入微信,一行代碼就搞定了。這裡實際上是掃二維碼登入了一個Web版的微信。

# 初始化機器人,掃碼登陸微信,适用于Windows系統
bot = Bot()

# Linux系統,執行登陸請調用下面的這句
bot = Bot(console_qr=2, cache_path="botoo.pkl")
           

然後我們需要定義一個發送消息的函數,将擷取并解析好的天氣資訊發送給指定微信好友。

# 調用get_weather函數
GW = get_weather()
# 填入你朋友的微信昵稱,注意這裡不是備注,也不是微信帳号
my_friend = bot.friends().search(u\'一個昵稱\')[0]
# 發送微信消息
my_friend.send(u"早上好Y(^o^)Y,這裡是今日份的天氣資訊請查收!")
my_friend.send(GW) 
my_friend.send(u"Have a Nice Day!")

# 每隔86400秒(1天),發送1次
t = Timer(86400, auto_send)
t.start()
           

接下來,你可以使用try...except...語句來實作在消息失敗時發出告警:

try:
    \'\'\'此處為發送消息的代碼,即上一段内容\'\'\'
except:
    # 你的微信昵稱,注意這裡不是備注,也不是微信帳号
    my_friend = bot.friends().search(\'&娴敲棋子&\')[0]
    my_friend.send(u"報告老闆,今日份的資訊發送失敗了!")
           

最後運作主函數,調用發送消息的函數即可。

# 調用函數進行消息發送
auto_send()
           

3 效果展示

這是我清晨收到的微信消息截圖,看上去還不錯。沒白忙活