WeChat subscribe number of life assistant

生活小助手订阅号python后台

Brief: We applied for a subscribe number to provide some help fornormal life.

It provide weather report、scheduled busrequest、cookbook request and so on.Weather report is based on a device whichcan monitor environment situation and upload to server thus server can transmitto subscribe number. The cookbook will be uploaded to server every week forrequest. Other information will be published in real time.The device is basedon Arduino platform.Transmit server is based on

每天户外运动,想有个能自动查询天气的方式,然而单位地方比较偏,周边没有气象部门站点,最近的有天气预报的地方也是三十多公里外的城区了。那就DIY一个呗。

某宝上找了找有各种模块,最近又学习了python,很快就有了思路。先做个硬件定时采集气象数据发送到服务端,服务端收到数据记录下以供查找中。结合微信的公众号接口,响应公众号查询请求。

硬件部分参考另一篇博文【气象信息采集装置】。

服务端

微信订阅号对服务器端有约束,必须是80端口,收发均封装成XML格式,微信官网提供了xml解析封装的示例代码,直接使用就可以。

服务器端由python搭建,引用web模块监听80端口,同时服务端监听另一个端口,气象采集端将采集到的气象数据发送至该端口,服务端接收后按格式处理好并记录。

用户在订阅号后台发送消息后,微信服务器会封装成xml消息转发至python服务端,服务端对80端口传入的xml请求解析并获取请求用户等信息,并提取最近一次采集到的气象数据,根据请求封装成规定的xml格式返回微信后台,由微信后台发送至用户端。

除天气查询外的其他功能都是通过python服务端直接处理并响应。

python端代码如下:

该代码包含

main.py:程序入口

basic.py:按照微信接口进行相关的验证, 里面的appId和appSecret填成自己申请的公众号的值

其中run函数无限循环驻留,不断重复与微信服务器连接,获取访问令牌。

receive.py:对来自微信服务器的信息进行解析,主要是从xml格式中提取信息

parse_xml对传入xml字符串解析后根据其中标示的消息类型分别处理。

reply.py:receive的对应反向操作,对要发送的信息按照微信约定封装并提交至微信服务器

封装文本和图片消息。

以上四部分微信官方都提供了样例,直接下载引用即可。

Handle.py是功能实现的主要地方,按照web模块application函数要求提供了针对Get和Post方法的请求响应方法,微信的消息都是通过POST传输的,所以重点是post处理函数。Post里对xml解析处理的文本进行判断,根据文本头进行不同的操作。

WriteToLog对用户请求进行记录形成日志

GetLogReport将上一次查询以来的最近的日志返回,以供查询,响应请求头为logget:的消息。这个仅供管理员使用,主要是当有用户发起其他请求,通过查询日志可以获知。这里吐槽下微信公众号给个人用户提供的权限很有限,即给订阅号的权限很有限,比如用微信的菜单功能就不能使用自定义回复,订阅号只能被动回复消息,一次只能回复一条。所以才导致该程序这么设计。在写该订阅号的时候微信小程序还没开放注册,所以当时没考虑用小程序做。

SetLogNotReceive主要响应消息头为norecv:的,也是供管理员使用的,因为服务器不在国内,日志信息比较长,故而在获取日志的时候经常会收不到,而当日志请求发生后程序会标记获取日志的时间,导致再次请求仍无法获取该次标记时间前的日志,因而需要该函数取消上一次日志获取时间设置,然后就可以再次申请获取日志。当然也可以借助该函数使得每次可以查看完日志再回复状态下次可以继续查看。

GetCookBook响应消息头为2的菜谱信息查询,从上传的菜谱文件中提取下一顿的菜谱。

菜谱文件内容格式:

按天列出,冒号前是标示,冒号后是菜谱,菜之间斜杠分隔。最后一行是上传者的昵称。文件名“17-06.txt”代表17年第6周。

GetDishes辅助实现GetCookBook功能。

RepairReport响应消息头为4的维修报备功能,由于暂时没能和后勤部门协商好,因而该功能及以下几个功能未启用,原理是当有人发起维修申请,公众号将转发消息至对应用户,这也是user.py(见下文)维护用户信息的目的之一。

MedicineReport和SuggestFeedback都是类似的方法,只是转发的对象不同,该程序都没有对这几个功能做下一步完善。

SetName用于用户设置自己的昵称,便于转发消息时供管理员识别,也使得对用户的回复称呼更友好。

Getweather.py是后来增加的一个模块,主要用于当气象采集装置因故障不可用或者想查询其他地方天气的时候,主要是通过抓取网络上的天气数据并返回。不多说,最基本的爬虫技能,抓取html页面信息。

user.py该模块最初用于记录用户信息,主要是完成后台的简单统计功能,比如我作为管理者不需要登陆微信订阅号后台就可以查看最近大家的请求情况等。通过读写文本文件维护一个字典,实现对用户id和用户名之间的解析查询。后来干脆把天气信息和一些系统信息都用类似方法维护,所以又增加了一个文本文件用来存储系统信息字典,一个文件用来存储气象数据。

构造函数初始化打开三个文件。

SetUserName设置用户ID及对应昵称。

GetUserName根据用户ID返回用户昵称。

TestUserExist测试用户ID是否已存在,从而在程序处理上进行区别。

GetWeather从气象采集器上传的信息中获取气象情况,该函数供查询马道天气时使用,当最近周期内气象采集装置或人工未更新气象信息或查询其他地区天气信息,则需要从网上抓取,即weather类的getweather方法。

SetWeather响应请求头为wset:的消息,即手动设置气象信息。主要是当气象采集装置失效时,手动上传气象信息。

GetSysInfo和SetSysInfo通过对维护的字典进行读写实现键值对形式的系统信息存储读取。

AutoWeatherServer.py就是气象信息采集装置对应的服务端,通过监听端口对传入的气象信息进行记录,仅此而已。

tcplink处理气象采集装置连接请求并记录。

writeToLog记录日志信息

   

图1 公众号运行截图

整个下来涉及的程序并不多也不难,只是作为初学python的练手,顺便实现了点小功能方便生活,所以里面还有很多不完善的地方,距离实用还有些距离,比如性能、容错性、可用性、安全性等等。仅供大家参考。

【附录】:

代码及相关资料下载:wechat

也可以看github,那里的是最新的:https://github.com/atp798/BlogStraka/tree/master/WechatSubscriptionServ

发表评论