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位数字,如下示例:
1
2
3
4
5
6
7
|
{ "_id" : 58 , "id" : 59 , "pid" : 3 , "city_code" : "101230201" , "city_name" : "厦门" } |
大家可以从_city.json文件中获取各个城市对应的编号。该文件我已经放在github本文章对应的目录下了,大家可自行查询使用。
1
2
3
4
5
6
7
8
9
10
11
|
# 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接口的返回值内容很多,以下仅展示返回的部分信息。实际使用中仅用到三块内容,首先是城市信息。
1
2
3
4
5
6
|
"cityinfo" : { "city" : "海淀区" , / / 请求城市 "cityid" : "101010200" , / / 城市 id "parent" : "北京市" , / / 上级,一般是省份 "updatetime" : "09:02" / / 天气更新时间 } |
其次是,该城市当前天气的空气相关指数。
1
2
3
4
5
6
7
8
|
"data" : { "shidu" : "32%" , / / 湿度 "pm25" : 35.0 , / / pm2. 5 "pm10" : 97.0 , / / pm10 "quality" : "良" , / / 空气质量 "wendu" : "7" , / / 温度 "ganmao" : "极少数敏感人群应减少户外活动" , / / 感冒提醒(指数) } |
第三部分,该城市当前天气的温度风力等另外一些指数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
"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文件。
拿到返回值之后,需要解析,并转换组装成我们想要的格式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 解析服务器返回的数据,具体可参考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信息
转换化具体代码就是这样子的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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版的微信。
1
2
3
4
5
|
# 初始化机器人,扫码登陆微信,适用于windows系统 bot = bot() # linux系统,执行登陆请调用下面的这句 bot = bot(console_qr = 2 , cache_path = "botoo.pkl" ) |
然后我们需要定义一个发送消息的函数,将获取并解析好的天气信息发送给指定微信好友。
1
2
3
4
5
6
7
8
9
10
11
12
|
# 调用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...语句来实现在消息失败时发出告警:
1
2
3
4
5
6
|
try : '''此处为发送消息的代码,即上一段内容''' except : # 你的微信昵称,注意这里不是备注,也不是微信帐号 my_friend = bot.friends().search( '&娴敲棋子&' )[ 0 ] my_friend.send(u "报告老板,今日份的信息发送失败了!" ) |
最后运行主函数,调用发送消息的函数即可。
1
2
|
# 调用函数进行消息发送 auto_send() |
3 效果展示
这是我清晨收到的微信消息截图,看上去还不错。没白忙活