一、前言
平日的再多的嘘寒问暖也只是无关痛痒,只有及时的关心才深入人心。
如果在每次降温前提醒她添加衣服,每次下雨前提醒她出门带伞,这样才是优雅的舔狗。锦上添花,不如雪中送炭。
那么,便开发一款天气变化提醒程序。在气温变冷或者天气不佳的时候发微信提醒你,好让你及时去关心她。
这,我愿称之为“舔狗天气”
二、 舔狗天气是什么?
2.1 简介
它可以每天实时不间断地获取天气信息,及时分析天气的变化,在降温到来之前提醒你,在下雨到来之前提醒你,好让你去关心你的女神,提醒她穿衣带伞,小心身体。
2.2 程序设计流程
- 从中国天气网获取天气信息,包括今天当前时间至次日凌晨以及未来5天的气温和天气状况。
- 分析天气和气温状况判断是否需要进行提醒
- 利用推送加平台给自己微信发送消息提醒
2.3 使用方法
在使用之前需要获得两个必需的参数,城市ID 和 推送加token。
这里的城市ID是指在请求中国天气网链接时带上的参数。
url = r'https://d1.weather.com.cn/wap_40d/{}.html?_={}'.format(city_id, timestamp)
请求这个链接可以得到未来40天和48小时的天气数据。 (返回的数据无法直接看懂,需要对网页对比分析)
2.3.1 获取中国天气网的城市ID
- 进入中国天气网城市选择界面。
- 输入你想要的城市
- 进入查看该城市的天气状况,该网页内就会包含城市ID。
例如广州的城市ID是101280101。
2.3.2 什么是推送加?
pushplus(推送加)是集成了微信、企业微信、钉钉、短信、邮件等渠道的信息推送平台
只需要调用一个简单的API接口,即可帮助你迅速完成消息推送,使用简单方便[1]
推送加官网地址:http://www.pushplus.plus/
只需要注册一个账号,就可以得到token。整个过程不需要2分钟。
获取到城市ID和推送加token之后,就可以使用该程序了。
你可以把程序添加到电脑开机自动运行,如果你有服务器的话那就更完美了。
三、Python代码
注意要修改城市ID还有你的token哦,不然程序无法使用。
import requests
import json
import time
qxbm = { # 数据来源中国天气网网页js代码https://j.i8tq.com/todayDetail/newMain.js?2019052016
"00": "晴", "01": "多云", "02": "阴", "03": "阵雨", "04": "雷阵雨", "05": "雷阵雨伴有冰雹", "06": "雨夹雪", "07": "小雨",
"08": "中雨", "09": "大雨", "10": "暴雨", "11": "大暴雨", "12": "特大暴雨", "13": "阵雪", "14": "小雪", "15": "中雪",
"16": "大雪", "17": "暴雪", "18": "雾", "19": "冻雨", "20": "沙尘暴", "21": "小到中雨", "22": "中到大雨", "23": "大到暴雨",
"24": "暴雨到大暴雨", "25": "大暴雨到特大暴雨", "26": "小到中雪", "27": "中到大雪", "28": "大到暴雪", "29": "浮尘", "30": "扬沙",
"31": "强沙尘暴", "53": "霾", "99": "无", "32": "浓雾", "49": "强浓雾", "54": "中度霾", "55": "重度霾", "56": "严重霾",
"57": "大雾", "58": "特强浓雾", "301": "雨", "302": "雪"}
def get_weather_data(city_id):
"""
获取当前到次日凌晨的每小时气温和未来5天的每天最低气温
"""
head = {
"referer": "http://m.weather.com.cn/",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44 "
}
timestamp = str(int(time.time())) + '761'
url = r'https://d1.weather.com.cn/wap_40d/{}.html?_={}'.format(city_id, timestamp)
print('正在请求天气信息...')
r = requests.get(url, headers=head)
if r.status_code != 200:
print('status code:', r.status_code)
return False
r.encoding = r.apparent_encoding
html = r.text.split(';') # html[0]为40天预报 html[2]为48小时预报
weather48 = html[2][html[2].find('{'):]
temp24hours = []
wea24hours = []
for hour in json.loads(weather48)['jh']:
if int(hour['jf'][-6:-2]) < int(time.strftime('%d%H')):
continue # jf是天气时间,如果小于当前时间则舍去
if len(temp24hours) <= 24 - int(time.strftime('%H')): # 取当前时间至次日凌晨之间的每小时气温,
temp24hours.append(hour['jb'])
wea24hours.append(hour['ja'])
else:
break
print('现在到次日凌晨的每小时气温:', temp24hours)
print('现在到次日凌晨的每小时天气:', [qxbm[i] for i in wea24hours])
weather40 = html[0][html[0].find('['):]
temp5days = []
wea5days001 = []
wea5days002 = []
for day in json.loads(weather40):
if int(day['009']) < int(time.strftime('%y%m%d')):
continue # 009是日期,如果日期小于今天则舍去
if len(temp5days) < 5: # 取未来5天的每天最低气温
temp5days.append(day['004'])
wea5days001.append(day['001'])
wea5days002.append(day['002'])
else:
break
print('未来5天的每天最低温:', temp5days)
print('未来5天的天气:', [qxbm[i] + '转' + qxbm[j] if i != j else qxbm[i] for i, j in zip(wea5days001, wea5days002)])
print()
# temp5days 未来5日的每日最低气温
# temp24hours 当前时间至次日凌晨的每小时气温
# wea5days001 未来5日的天气状况1
# wea5days002 未来5日的天气状况2 (状况1,2表示2个天气变化,例如暴雨转小雨)
# wea24hours 当前时间至次日凌晨的天气状况
return temp5days, temp24hours, wea5days001, wea5days002, wea24hours
def analyse_weather(temps):
"""
分析气温变化,判断要不要发送消息提醒,如果不需要提醒,返回空字符串
:param temps: 天气信息
:return: 返回发送消息提醒的文本内容
"""
temp5days, temp24hours, wea5days001, wea5days002, wea24hours = temps
global time5, time24, time5_2, time24_2
message = ''
temp5days = list(map(int, temp5days))
temp24hours = list(map(int, temp24hours))
if time.time() - time5 > 3600 * 24: # 间隔上次发消息24小时判断一次未来5天气温变化,再分析要不要发送消息提醒
for i, t in enumerate(temp5days):
dis = temp5days[0] - t
if dis >= 5: # 未来某一天温度比今天下降超过5℃
mouth, days = time.strftime('%m-%d',time.localtime(time.time()+86400)).split('-')
message += '气温将在{}月{}日({}天后)下降{}摄氏度,寒冷将至,气温{}℃,记得关心她。\n'.format(mouth, days, i + 1, dis, t)
time5 = time.time()
if time.time() - time5_2 > 3600 * 24:
for i, t in enumerate(wea5days001):
if (wea5days001[i] not in ('00', '01', '02', '99')) or (wea5days002[i] not in ('00', '01', '02', '99')):
if wea5days001[i] == wea5days002[i]:
wea = qxbm[t]
else:
wea = qxbm[wea5days001[i]] + '转' + qxbm[wea5days002[i]]
mouth, days = time.strftime('%m-%d',time.localtime(time.time()+86400)).split('-')
message += '在{}月{}日({}天后)将会是 {} 天气,记得关心一下女神。\n'.format(mouth, days, i + 1, wea)
time5_2 = time.time()
break
if time.time() - time24 > 3600 * 3: # 间隔上次发消息3小时判断一次气温变化,再分析要不要发送消息提醒
for i, t in enumerate(temp24hours):
dis = temp24hours[0] - t
if dis >= 5: # 温度比当前点钟下降超过5℃
message += '气温将在{}:00下降{}摄氏度,寒冷将至,气温{}℃需要去关心她。\n'.format(int(time.strftime('%H')) + i, dis, t)
time24 = time.time()
if time.time() - time24_2 > 3600 * 6:
for i, t in enumerate(wea24hours):
if t not in ('00', '01', '02', '99'):
message += '在{}:00将会是 {} 天气,去关心一下女神吧。\n'.format(int(time.strftime('%H')) + i, qxbm[t])
time24_2 = time.time()
break
return message
def send_reminder(token, message):
if not message:
print('气温变化适宜,不用发送消息提醒')
return
r = requests.get('http://www.pushplus.plus/send?token={}&content={}&template=txt'.format(token, message))
if r.status_code == 200:
print('发送提醒成功,message:')
print(message)
else:
print('发送提醒失败,status_code:', r.status_code)
if __name__ == '__main__':
you_token = '' # 在推送加官网获取
cityID = '101280101' # 广州
assert you_token and cityID
time5 = time24 = time5_2 = time24_2 = 0
while True:
print('舔狗日记,现在是{}'.format(time.strftime('20%y-%m-%d %H:%M')))
temp = get_weather_data(cityID)
assert temp
message_text = analyse_weather(temp)
send_reminder(you_token, message_text)
if int(time.strftime('%H')) <= 6:
print('.........凌晨至06:59为免打扰时间.........')
while int(time.strftime('%H')) <= 6:
time.sleep(60)
else:
print('{}等待1小时{}'.format('.' * 15, '.' * 15))
time.sleep(3600)
参考:
[1] http://www.pushplus.plus/
[2] http://www.pushplus.plus/doc/guide/api.html