python定时天气预报(微信提醒)(部署到云服务器)
声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关
需求:拿到当天的天气预报信息,并且把天气预报关键信息合成语音,然后将天气预报信息和合成的语音通过微信公众号发送给粉丝,最后部署程序到云服务器,设置定时任务运行程序。
ps:有了上一篇的邮件提醒才有了这一篇点击跳转
一、准备工作
在我的上一篇博客中列举的那些准备,如果这里也用到的话就不再详细介绍了哈
- 微信公众号测试账号(为了给微信发送信息)
- 云盘存放保存合成的语音(为了拿到能在线播放合成后语音的url地址)
- 云服务器(为了部署到云服务器上)
- 安装
xshell
(为了操作云服务器)
二、准备工作具体步骤
-
微信公众号测试账号
打开测试账号申请页面,用微信扫码登录授权即可http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login点击跳转,登录成功之后你就拥有了一个微信公众号的接口测试账号,因为这些接口包括了很大部分的订阅号和服务号的接口,测试账号基本上都可以调用的,我们个人又申请不了服务号,所以用这个测试账号来练习也是不错的选择,好了,我就不过多地介绍他了,现在的接口文档好像打不开了,不过你可以在这里看服务号的接口文档,需要用到的也就几个而已哈哈,具体步骤如下图
-
云盘存放保存合成的语音
这里的云盘我找了很久,因为要找那种可以通过代码来上传的网站才行,并且上传后能提供在线访问的url
地址,遇到了很多的坑,最后不负有心人,还是找到了一个满意的云盘哈哈,他就是OpenDrive
是个外国的网站https://www.opendrive.com点击跳转,直接注册账号就行了,然后他的接口文档是用php
写的,对我这个只会python
的来说,一开始简直崩溃,不过细细看代码也能看明白的,要相信自己哈哈。具体怎么用python
代码实现请看代码。具体步骤如下图:
-
云服务器
云服务器还是用三丰云的免费服务器点击跳转,因为我的上一篇博客已经介绍过了,这里我就不重复了哈哈 -
安装
xshell
同上
三、开始敲代码
废话不多说,具体细节请看代码以及注释。
- 导入需要用到的包
import requests
import json
import os #获取文件大小
from aip import AipSpeech #百度api
import uuid #用来给合成的语音命名(全球唯一)
import random
- 定义获取用户城市的函数
def get_city_id(token,openid):
#token:凭证,openid:即用户微信号id(是你测试公众号里面别人扫码关注后会有的一个相对于你测试号的唯一id)
url='https://api.weixin.qq.com/cgi-bin/user/info?access_token={0}&openid={1}&lang=zh_CN'.format(token,openid)
r=requests.get(url)
city_id=r.json()['city']
sex=r.json()['sex']
return city_id,sex
- 定义合成语音的函数
def download_mp3(mp3_content,APP_ID,API_KEY,SECRET_KEY,sex):
if sex == 1: #女声
per=random.choice([0,4,5,103,111])
else: #男声
per=random.choice([1,3,106,110])
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
result = client.synthesis(mp3_content, 'zh', 1, {'vol': 15,'spd':3,'pit':8,'per': per})
if not isinstance(result, dict):
with open('/home/Juneway/weather.mp3', 'wb') as f:
f.write(result)
- 定义上传合成语音文件并获取在线播放url函数
def get_mp3_url(username,passwd):
#第一步:获取sessionid
url='https://dev.opendrive.com/api/v1/session/login.json'
data={
'username': username,
'passwd' : passwd
}
r=requests.post(url,data=data)
SessionID=r.json()['SessionID']
# #删除文件
# url = 'https://dev.opendrive.com/api/v1/folder/list.json/%s/NDBfMjA5NDE5MV9KMkNlbw'%SessionID
# r=requests.get(url)
# file_id=r.json()['Files'][0]['FileId']
# url='https://dev.opendrive.com/api/v1/file/trash.json'
# data={
# 'session_id':SessionID,
# 'file_id':file_id,
# 'access_folder_id':'NDBfMjA5NDE5MV9KMkNlbw'
# }
# r=requests.post(url,data=data)
#第二步:上传文件
file_size=os.path.getsize('/home/Juneway/weather.mp3')
url='https://dev.opendrive.com/api/v1/upload/create_file.json'
data={
'session_id':SessionID,
'folder_id':'NDBfMjA5NDE5MV9KMkNlbw', #表示是music这个文件夹
'file_name':str(uuid.uuid1()).replace('-','')+'.mp3',
'file_size':file_size,
'access_folder_id':'NDBfMjA5NDE5MV9KMkNlbw'
}
r=requests.post(url,data=data)
file_id=r.json()['FileId']
DirUpdateTime=r.json()['DirUpdateTime']
url='https://dev.opendrive.com/api/v1/upload/open_file_upload.json'
data={
'session_id':SessionID,
'file_id':file_id,
'file_size':file_size,
'access_folder_id':'NDBfMjA5NDE5MV9KMkNlbw'
}
r=requests.post(url,data=data)
TempLocation=r.json()['TempLocation']
url='https://dev.opendrive.com/api/v1/upload/upload_file_chunk.json'
data={
'session_id':SessionID,
'file_id':file_id,
'temp_location':TempLocation,
'chunk_offset':0,
'chunk_size':file_size
}
files = {'file_data':open('/home/Juneway/weather.mp3','rb')}
r=requests.post(url,data=data,files=files)
url='https://dev.opendrive.com/api/v1/upload/close_file_upload.json'
data={
'session_id':SessionID,
'file_id':file_id,
'temp_location':TempLocation,
'file_size':file_size,
'file_time':DirUpdateTime,
'access_folder_id':'NDBfMjA5NDE5MV9KMkNlbw'
}
r=requests.post(url,data=data)
#第四步:获取文件url地址
StreamingLink=r.json()['StreamingLink']
return StreamingLink
- 主函数
def main(appid,secret,key,mb_id,username,passwd,APP_ID,API_KEY,SECRET_KEY):
url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}'.format(appid,secret)
r=requests.get(url)
token=r.json()['access_token']
url='https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid='%token
r=requests.get(url)
user_list=r.json()['data']['openid']
for openid in user_list:
city_id,sex=get_city_id(token,openid)
url='https://free-api.heweather.net/s6/weather/forecast?location={0}&key={1}'.format(city_id,key)
headers={'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'}
r=requests.get(url,headers=headers)
data=r.json()
#加上下面的判断是因为防止有些人的微信个人信息没有填地区或者填写的地区找不到相应的天气预报
if data['HeWeather6'][0]['status'] == 'ok':
city=data['HeWeather6'][0]['basic']['location'] #城市
forecast_time=data['HeWeather6'][0]['update']['loc'] #预报时间
date=data['HeWeather6'][0]['daily_forecast'][0]['date'] #日期
day_weather=data['HeWeather6'][0]['daily_forecast'][0]['cond_txt_d'] #白天天气
night_weather=data['HeWeather6'][0]['daily_forecast'][0]['cond_txt_n'] #晚间天气
wind_dir=data['HeWeather6'][0]['daily_forecast'][0]['wind_dir'] #风向
wind_sc=data['HeWeather6'][0]['daily_forecast'][0]['wind_sc'] #风力
wind_spd=data['HeWeather6'][0]['daily_forecast'][0]['wind_spd'] #风速 公里/小时
tmp_min=data['HeWeather6'][0]['daily_forecast'][0]['tmp_min'] #最低气温
tmp_max=data['HeWeather6'][0]['daily_forecast'][0]['tmp_max'] #最高气温
sr=data['HeWeather6'][0]['daily_forecast'][0]['sr'] #日出时间
ss=data['HeWeather6'][0]['daily_forecast'][0]['ss'] #日落时间
mr=data['HeWeather6'][0]['daily_forecast'][0]['mr'] #月出时间
ms=data['HeWeather6'][0]['daily_forecast'][0]['ms'] #月落时间
mp3_content='{0}今天早上{1}。晚上{2}。气温{3}到{4}摄氏度。{5}。风力{6}级。风速{7}公里每小时。{8}日出。{9}日落。{10}月出。{11}月落。'.format(city,day_weather,night_weather,tmp_min,tmp_max,wind_dir,wind_sc,wind_spd,sr,ss,mr,ms)
#合成mp3
download_mp3(mp3_content,APP_ID,API_KEY,SECRET_KEY,sex)
#获取mp3的url
mp3_url=get_mp3_url(username,passwd)
msg={
'touser':openid,
'template_id':mb_id, #模板id
'url':mp3_url,
'data':{
'city':{
'value':city,
'color':'#173177'
},
'date':{
'value':date,
'color':'#173177'
},
'day_weather':{
'value':day_weather,
'color':'#173177'
},
'night_weather':{
'value':night_weather,
'color':'#173177'
},
'wind_dir':{
'value':wind_dir,
'color':'#173177'
},
'wind_sc':{
'value':wind_sc,
'color':'#173177'
},
'wind_spd':{
'value':wind_spd,
'color':'#173177'
},
'tmp_min':{
'value':tmp_min,
'color':'#173177'
},
'tmp_max':{
'value':tmp_max,
'color':'#173177'
},
'sr':{
'value':sr,
'color':'#173177'
},
'ss':{
'value':ss,
'color':'#173177'
},
'mr':{
'value':mr,
'color':'#173177'
},
'ms':{
'value':ms,
'color':'#173177'
}
}
}
json_data=json.dumps(msg)
url='https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s'%token
#发送推文
r=requests.post(url,data=json_data)
- 程序入口
if __name__ == '__main__':
key = '你自己和风天气应用的key' #和风天气api
mb_id = '填你的模板id' #模板id
appid = '填你自己的' #测试公众号
secret = '填你自己的' #测试公众号
username = '账号' #OpenDrive
passwd = '密码' #OpenDrive
APP_ID = '填你自己的' #百度api
API_KEY = '填你自己的' #百度api
SECRET_KEY = '填你自己的' #百度api
main(appid,secret,key,mb_id,username,passwd,APP_ID,API_KEY,SECRET_KEY)
四、部署到云服务器
五、结果展示
这个是对应语音的url
https://od.lk/s/NDBfMTEyODk2MDZf/6295074e130411ea863300155d08ba50.mp3点击跳转
ps:如果你不想敲代码自己做的话,可以直接扫一扫下面的二维码关注一下就可以了哦,名额有限哦哈哈
写在最后
一开始,为了想让微信发语音绕了很多弯路,因为微信发送的推文,点击推文的话会进去一个声明好的链接里面,然后我就从这里开始入手,就开始各种百度搜本地文件上传到网络上并拿到其在线访问的url
,一开始想过用selenium
来模拟点击来上传文件,然后想想好像不现实,而且也不帅,于是就再找啊找,就希望能够找到一个可以通过编写代码来上传文件的网站,于是乎,便找到了OpenDrive
,发现他非常符合我的需求,可是他是一个外国的网站,并且其文档是用php
语言来做事例的,一开始我是拒绝的,甚至还想请教一下身边学php
的同事,不过我想了想,这么简单也要问别人?而且都做到这最后一步了,自己做出来成就感才会爆棚。于是乎,我咬紧牙关一行代码一行代码的看php
,发现其实也不是很难嘛,我边看边想着怎么用python
代码来实现,最后在file_data
这个参数上面撞上了,我又开始各种百度python
上传文件的案例,最后恍然大悟中做了出来哈哈。记得当时我大叫了一声,幸好当时已经下班了,没多少人在哈哈哈。