22.9.18更新
已经更新最新版,最新版比较详细,而且分为python和JavaScript版本
请移步 获取公众号推送 2.0 加强版!22.10.16更新
我已经做出来更优秀的直接在聊天列表中推送的了!
请移步 企业微信推送 超强版!
如何优雅地获取公众号专属推送
目录
前言
我们学校自从更新了选课系统之后,就没有自动的课表推送了。同时,我也想给自己的女朋友做一个推送天气和气温的小东西,以便于她能方便地查看天气进行每天的规划。
于是,这个专属的公众号推送来了。
技术选型
- 编程语言:python(3.0版本以上)
- 包管理工具:pip3
- 代码编辑器:pycharm
- 所用包:request/datetime/date
- 服务器:腾讯云轻量应用服务器
- 服务器自动化运行语言:Shell
产品逻辑
由于是在微信公众号下进行操作,依赖微信的生态进行。所以要先去看看微信官方文档。同时,选定编程语言根据官方文档可知,微信公众号
可实现信息模板的发送,但是只有测试号可以(够用,但是我至今没找到如何部署到自己的公众号而非测试号)
微信公众号发文逻辑
申请测试号:
记录appId及appSecret
由本地向微信服务器发送appID及appSecret获取access_token
确定自己所要发送的信息,并在公众号测试号中设定对应信息模板,并获取模板ID,以下是我的模板。
今天是{{date.DATA}}
城市:{{city.DATA}}
天气:{{weather.DATA}}
最低气温: {{min_temperature.DATA}}
最高气温: {{max_temperature.DATA}}
今天是我们恋爱的第{{love_day.DATA}}天
距离墨墨的生日还有{{birthday.DATA}}天
--------课表--------
8-10 {{firstClass.DATA}}
10-12 {{secondClass.DATA}}
2-4 {{thirdClass.DATA}}
4-6 {{fourthClass.DATA}}
7-10 {{fifthClass.DATA}}
让你的用户扫码,得到该用户openid
对自己所要发送的信息进行包装,并携带access_token发送给微信服务器,之后,你的公众号就会给特定用户发送信息。
将做好的项目放到自己的服务器上,并用设置定时任务,用Shell命令每天7.30定时执行文件。为什么要用到服务器,因为服务器是一直开机的,而我的电脑不会。
代码思路
这个代码相对来说比较简单,我只用了三个文件,分别是
config.py
:配置文件main.py
:主要运行文件cityinfo.py
:城市信息文件(用来请求对应城市的天气)
main.py
中主要为get_access_token
get_weather
send_message
三个函数,他们的内容根据他们的名字一看就懂,分别是获取assess_token
获取天气信息
发送信息
。
你如何修改我的代码
为了提高代码的复用性,拿到代码的同学只用修改config.py
中的配置信息,即把我的配置改成你的配置就行。
不过需要注意的是,我的classes数组是7x5的数组,不要出现索引过界等问题。
源代码
由于代码对这篇文章来说有点多,这里只放main.py
的代码。
更多代码已经上传到我的gitee仓库并已经开源
https://gitee.com/dongshengye/wxPost
以下是main.py
的代码
from time import time, localtime
import cityinfo
import config
from requests import get, post
from datetime import datetime, date
def get_access_token():
# appId
app_id = config.app_id
# appSecret
app_secret = config.app_secret
post_url = ("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}"
.format(app_id, app_secret))
print(get(post_url).json())
access_token = get(post_url).json()['access_token']
# print(access_token)
return access_token
def get_weather(province, city):
# 城市id
city_id = cityinfo.cityInfo[province][city]["AREAID"]
# city_id = 101280101
# 毫秒级时间戳
t = (int(round(time() * 1000)))
headers = {
"Referer": "http://www.weather.com.cn/weather1d/{}.shtml".format(city_id),
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
url = "http://d1.weather.com.cn/dingzhi/{}.html?_={}".format(city_id, t)
response = get(url, headers=headers)
response.encoding = "utf-8"
response_data = response.text.split(";")[0].split("=")[-1]
response_json = eval(response_data)
print(response_json)
weatherinfo = response_json["weatherinfo"]
# 天气
weather = weatherinfo["weather"]
# 最高气温
temp = weatherinfo["temp"]
# 最低气温
tempn = weatherinfo["tempn"]
return weather, temp, tempn
def send_message(to_user, access_token, city_name, weather, max_temperature, min_temperature):
url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}".format(access_token)
week_list = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
year = localtime().tm_year
month = localtime().tm_mon
day = localtime().tm_mday
today = datetime.date(datetime(year=year, month=month, day=day))
week = week_list[today.weekday()]
theClass = classes[today.weekday()]
# 获取在一起的日子的日期格式
love_year = int(config.love_date.split("-")[0])
love_month = int(config.love_date.split("-")[1])
love_day = int(config.love_date.split("-")[2])
love_date = date(love_year, love_month, love_day)
# 获取在一起的日期差
love_days = str(today.__sub__(love_date)).split(" ")[0]
# 获取生日的月和日
birthday_month = int(config.birthday.split("-")[1])
birthday_day = int(config.birthday.split("-")[2])
# 今年生日
year_date = date(year, birthday_month, birthday_day)
# 计算生日年份,如果还没过,按当年减,如果过了需要+1
if today > year_date:
birth_date = date((year + 1), birthday_month, birthday_day)
birth_day = str(birth_date.__sub__(today)).split(" ")[0]
elif today == year_date:
birth_day = 0
else:
birth_date = year_date
birth_day = str(birth_date.__sub__(today)).split(" ")[0]
data = {
"touser": to_user,
"template_id": config.template_id,
"url": "http://weixin.qq.com/download",
"topcolor": "#FF0000",
"data": {
"date": {
"value": "{} {}".format(today, week),
"color": "#00FFFF"
},
"city": {
"value": city_name,
"color": "#808A87"
},
"weather": {
"value": weather,
"color": "#ED9121"
},
"min_temperature": {
"value": min_temperature,
"color": "#00FF00"
},
"max_temperature": {
"value": max_temperature,
"color": "#FF6100"
},
"love_day": {
"value": love_days,
"color": "#87CEEB"
},
"birthday": {
"value": birth_day,
"color": "#FF8000"
},
"firstClass": {
"value": theClass[0],
"color": "#FF8000"
},
"secondClass": {
"value": theClass[1],
"color": "#FF8000"
},
"thirdClass": {
"value": theClass[2],
"color": "#FF8000"
},
"fourthClass": {
"value": theClass[3],
"color": "#FF8000"
},
"fifthClass": {
"value": theClass[4],
"color": "#FF8000"
}
}
}
headers = {
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'
}
response = post(url, headers=headers, json=data)
print(response.text)
if __name__ == '__main__':
# 获取accessToken
accessToken = get_access_token()
print('token', accessToken)
# 接收的用户
user = config.user
# 传入省份和市获取天气信息
province, city = config.province, config.city
classes = config.classes
weather, max_temperature, min_temperature = get_weather(province, city)
# 公众号推送消息
send_message(user, accessToken, city, weather, max_temperature, min_temperature)
写在最后
用一些小小的项目来支撑自己的兴趣,我个人认为还是很有必要的。即可以有实际的应用,也可以让自己更有动力,何乐而不为呢~