微信公众号推送天气预报
天气API
使用聚合网的天气API,每天免费50次
接口地址: http://apis.juhe.cn/simpleWeather/query
请求方式: GET
请求参数; city
拼接方式: http://apis.juhe.cn/simpleWeather/query?city={city}&key={key}
请求Key: 实名认证后会有
测试账号
微信公众平台接口测试账号,注册一个测试账号,记下appid和secret,扫码后产生的用户ID、模板ID,填入config.txt
文件中
自己的公众号不记得密码了,擦,先用测试的吧
{{date.DATA}}
城市:{{city.DATA}}
天气:{{weather.DATA}}
实时气温:{{temperature.DATA}}
湿度:{{humioity.DATA}}
风向:{{direct.DATA}}
您已经在地球上存活了:{{live.DATA}}天
{{note_ch.DATA}}
{{note_en.DATA}}
配置文件
{
"appid": "appid",
"secret": "secret",
"template_id": "0sXNi6sorkdKHVKS8UuQdRARS39vaBu94YyqbmW7GtI",
"user": ["oGeX96kGhg-wEhbKEstfGe93cAiQ","oGeX96pRe_r-0PfdsJ09zzk5juHI"],
"key": "7ccd03d19e2920224cdadd2ae2bdfd07",
"birthday": "2000-03-11",
"weather_key": "7ccd03d19e2920224cdadd2ae2bdfd07",
"region": ["保定","石家庄"],
"note_ch": "good good learn,day day up",
"note_en": "study hard and make progress every day!"
}
代码
在main中读取配置文件并调用函数
if __name__ == "__main__":
try:
with open("config.txt", encoding="utf-8") as f:
config = eval(f.read())
except FileNotFoundError:
print("推送消息失败,请检查config.txt文件是否与程序位于同一路径")
os.system("pause")
sys.exit(1)
except SyntaxError:
print("推送消息失败,请检查配置文件格式是否正确")
os.system("pause")
sys.exit(1)
# 获取accessToken
accessToken = get_access_key()
# 接收的用户
users = config["user"]
# 传入地区获取天气信息
citys = config["region"]
note_ch = config["note_ch"]
note_en = config["note_en"]
#模板id
template_id = config["template_id"]
for usr,city in zip(users,citys):
weather, temperature, humidity, direct = get_weather(city)
send_msg(usr,accessToken,template_id,weather,temperature,humidity,direct,note_ch,note_en)
同时循环两个及以上列表要加zip()
for usr,city in zip(users,citys):
weather, temperature, humidity, direct = get_weather(city)
send_msg(usr,accessToken,template_id,weather,temperature,humidity,direct,note_ch,note_en)
这个循环考虑了多个用户,不同城市,目前存放的时候只能一一对应,后面可以将配置文件读入转化为Json,里面放一个users,每一个user对应城市、生日等等用户信息。读入程序后,赋给实体对象,这样外循环只遍历用户对象就行了,还方便增删查改。没毛病 。用户id
、city
。定义一个user类
class User:
def __init__(self, id, city,birthday):
self.id = id
self.city = city
self.birthday = birthday
//TODO 能不能获取用户微信上的地址,更方便
将txt文件转换为json文件
读取文件中的每一行,并将其拆分为键和值对,来创建一个Python字典对象。对于值是一个JSON字符串的情况下,我们使用 json.loads() 函数将其解析成Python对象。最后,我们可以使用 json.dump() 将字典对象写入新的JSON文件中。
import json
def txt2json():
# 读取文本文件
with open('config.txt', 'r') as f:
lines = f.readlines()
# 将文本转换为字典对象
data = {}
for line in lines:
key, val = line.strip().split(': ')
try:
val = json.loads(val)
except ValueError:
pass
data[key] = val
# 将字典对象写入JSON文件
with open('config.json', 'w') as f:
json.dump(data, f)
读取Json文件建立userduix
def CreateUsersByJson():
with open('config.json', 'r') as f:
data = json.load(f)
users = []
for user_data in data['users'].values():
users.append(User(user_data['id'], user_data['city'],user_data['birthday']))
return users
根据appid
和 secret
获取密钥accessToken
这个在后面发消息会用到
def get_access_key():
appid = config['appid']
secret = config['secret']
url = f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={appid}&secret={secret}'
response = requests.get(url).json()
access_token = ''
if response['expires_in'] == 7200:
access_token = response['access_token']
return access_token
else:
print("appid或secret错误")
根据城市获得天气
聚合网查询得到的json数据为:
{"reason":"查询成功!","result":{"city":"保定","realtime":{"temperature":"37","humidity":"23","info":"晴","wid":"00","direct":"西南风","power":"5级","aqi":"125"},"future":[{"date":"2023-06-16","temperature":"23\/38℃","weather":"晴","wid":{"day":"00","night":"00"},"direct":"南风"},{"date":"2023-06-17","temperature":"23\/36℃","weather":"晴转多云","wid":{"day":"00","night":"01"},"direct":"西南风转东北风"},{"date":"2023-06-18","temperature":"24\/36℃","weather":"多云转中雨","wid":{"day":"01","night":"08"},"direct":"东北风"},{"date":"2023-06-19","temperature":"19\/27℃","weather":"雷阵雨转阴","wid":{"day":"04","night":"02"},"direct":"东北风转北风"},{"date":"2023-06-20","temperature":"17\/25℃","weather":"雷阵雨转多云","wid":{"day":"04","night":"01"},"direct":"北风转东北风"}]},"error_code":0}
未来天气就算了吧,毕竟每天推送,郁闷的是当日天气没有最低最高温度,只有实时温度。。。。这个API不行
r = requests.get(url,headers)
得到的是一个response对象,需要调用res = r.json()
转换为json格式,然后就可以访问键值。- 函数返回天气、实时温度、湿度、风向。
def get_weather(city):
key = config["key"]
headers = {
'Referer': 'http://apis.juhe.cn/simpleWeather/query',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36'
}
url = f'http://apis.juhe.cn/simpleWeather/query?city={city}&key={key}'
r = requests.get(url,headers)
r.encoding = "utf8"
res = r.json()
realtime = res['result']['realtime']
temperature = realtime['temperature']
humidity = realtime['humidity']
weather = realtime['info'] #晴
direct = realtime['direct'] #风
return weather,temperature,humidity,direct
推送消息
strptime(要转换为datetime的字符串,输入的格式)
reques.post(sendMessage_url, data=json.dumps(data)).json()
向指定的URL发送POST请求,并将发送的数据以JSON格式进行编码。将响应结果保存为json数据
json.dumps(data)
将字典转换成一个Json字符串
这个不用了,太蠢了
def send_msg(user,accessToken,template_id,weather,temperature,humioity,direct, note_ch, note_en):
sendMessage_url = f"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={accessToken}"
# 当前日期和星期
week_list = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
year = localtime().tm_year
month = localtime().tm_mon
day = localtime().tm_mday
week = week_list[datetime.date(int(year), int(month), int(day)).weekday()]
date = f'{year}年{month}月{day}日 {week}'
# 活了多久
birthday_date = datetime.datetime.strptime(config['birthday'], "%Y-%m-%d")
curr_datetime = datetime.datetime.now()
minus_datetime = curr_datetime - birthday_date
data = {
"touser": user,
"template_id": template_id,
"appid": config['appid'],
"data": {
"live": {
"value": minus_datetime.days,
"color": get_color()
},
"city": {
"value": city,
"color": get_color()
},
"weather": {
"value": weather,
"color": get_color()
},
"temperature": {
"value": temperature,
"color": get_color()
},
"humioity": {
"value": humioity,
"color": get_color()
},
"direct": {
"value": direct,
"color": get_color()
},
'note_ch': {
"value": note_ch,
"color": get_color()
},
'note_en': {
"value": note_en,
"color": get_color()
}
}
}
getTemp = requests.post(sendMessage_url, data=json.dumps(data)).json()
修改之后的推送消息
参数只有user,看着舒服多了
def SendMsg(user):
city = user.city
weather, temperature, humidity, direct = get_weather(city)
sendMessage_url = f"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={accessToken}"
birthday_date = datetime.datetime.strptime(config['birthday'], "%Y-%m-%d")
curr_datetime = datetime.datetime.now()
minus_datetime = curr_datetime - birthday_date
data = {
"touser": user.id,
"template_id": template_id,
"appid": config['appid'],
"data": {
"live": {
"value": minus_datetime.days,
"color": get_color()
},
"city": {
"value": city,
"color": get_color()
},
"weather": {
"value": weather,
"color": get_color()
},
"temperature": {
"value": temperature,
"color": get_color()
},
"humioity": {
"value": humidity,
"color": get_color()
},
"direct": {
"value": direct,
"color": get_color()
},
'note_ch': {
"value": note_ch,
"color": get_color()
},
'note_en': {
"value": note_en,
"color": get_color()
}
}
}
getTemp = requests.post(sendMessage_url, data=json.dumps(data)).json()
//TODO 对getTemp判断
get_color()
随机选择颜色,抄的
def get_color():
# 获取随机颜色
get_colors = lambda n: list(map(lambda i: "#" + "%06x" % random.randint(0, 0xFFFFFF), range(n)))
color_list = get_colors(100)
return random.choice(color_list)
结果
测试号上可行,推送样式如图:
做好了才发现个人公众号不能推送模板信息。。。搞不了。。。