微信公众号开发——关键词自动回复

来源:互联网 发布:美工招聘信息怎么写 编辑:程序博客网 时间:2024/05/16 14:00

最近忙国赛的一个项目,我得做一个微信公众号。功能就是调数据并回复给用户,需要用户发送给公众号一个关键词,通过关键词自动回复消息。

这时就是查询微信公众平台文档了,地址如下:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432
按照它的入门指南,我基本上了解了用户给公众号发送消息的一个机制,并且一旦给公众号发送消息,在开发者后台,会收到公众平台发送的一个xml,所以通过编写Python脚本进行xml的解析与自动发送功能。

如果用户给公众号发送一段text消息,比如“hello”,那么后台就会收到一个xml为:

<xml><ToUserName><![CDATA[公众号]]></ToUserName><FromUserName><![CDATA[粉丝号]]></FromUserName><CreateTime>1460541339</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[hello]]></Content></xml>

注意这里面有一些标记对于我们开发者来说是非常有用的:ToUserName,FromUserName,MsgType,Content
所以我们只要知道了这些信息,我们就能做到自动回复的功能。
我们发现这个MsgType 为 ‘text’。而微信中的MsgType有“text”(文本)、“image”(图像)、“voice”(语音)、“video”(视频)、“shortvideo”(短视频)、“location”(位置)、“link”(链接)、“event”(事件)


首先我们写一个main.py文件
main.py

# -*- coding: utf-8 -*-# filename: main.pyimport webfrom handle import Handleurls = (    '/wx', 'Handle',)if __name__ == '__main__':    app = web.application(urls, globals())    app.run()

然后写一个receive.py,作为接受用户发送过来的数据,并解析xml,返回数据的脚本。
receive.py

import xml.etree.ElementTree as ETdef parse_xml(web_data):    if len(web_data) == 0:        return None    xmlData = ET.fromstring(web_data)    msg_type = xmlData.find('MsgType').text    if msg_type == 'text':        #print('text')        return TextMsg(xmlData)    elif msg_type == 'image':        return ImageMsg(xmlData)    elif msg_type == 'location':        #print('location')        return LocationMsg(xmlData)    elif msg_type == 'event':        #print('event')        return EventMsg(xmlData)class Event(object):    def __init__(self, xmlData):        self.ToUserName = xmlData.find('ToUserName').text        self.FromUserName = xmlData.find('FromUserName').text        self.CreateTime = xmlData.find('CreateTime').text        self.MsgType = xmlData.find('MsgType').text        self.Eventkey = xmlData.find('EventKey').textclass Msg(object):    def __init__(self, xmlData):        self.ToUserName = xmlData.find('ToUserName').text        self.FromUserName = xmlData.find('FromUserName').text        self.CreateTime = xmlData.find('CreateTime').text        self.MsgType = xmlData.find('MsgType').text        self.MsgId = xmlData.find('MsgId').textclass TextMsg(Msg):    def __init__(self, xmlData):        Msg.__init__(self, xmlData)        self.Content = xmlData.find('Content').text.encode("utf-8")class ImageMsg(Msg):    def __init__(self, xmlData):        Msg.__init__(self, xmlData)        self.PicUrl = xmlData.find('PicUrl').text        self.MediaId = xmlData.find('MediaId').textclass LocationMsg(Msg):    def __init__(self, xmlData):        Msg.__init__(self, xmlData)        self.Location_X = xmlData.find('Location_X').text        self.Location_Y = xmlData.find('Location_Y').textclass EventMsg(Msg):    def __init__(self, xmlData):        Event.__init__(self, xmlData)        self.Event = xmlData.find('Event').text

其中,我们使用xml.etree.ElementTree,这是一个简单而有效的用户解析和创建XML数据的API。而fromstring()就是解析xml的函数,然后通过标签进行find(),即可得到标记内的内容。

同时还要写一个reply.py,作为自动返回数据的脚本。
刚才提到了,用户给公众号发送消息,公众号的后台会接收到一个xml,那么如果公众号给用户发送消息呢,其实也就是公众号给用户发送一个xml,只是ToUserName,FromUserName换了一下而已,内容自己定。

<xml><ToUserName><![CDATA[粉丝号]]></ToUserName><FromUserName><![CDATA[公众号]]></FromUserName><CreateTime>1460541339</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[test]]></Content></xml>

reply.py

import timeclass Msg(object):    def __init__(self):        pass    def send(self):        return "success"class TextMsg(Msg):    def __init__(self, toUserName, fromUserName, content):        self.__dict = dict()        self.__dict['ToUserName'] = toUserName        self.__dict['FromUserName'] = fromUserName        self.__dict['CreateTime'] = int(time.time())        self.__dict['Content'] = content    def send(self):        XmlForm = """        <xml>        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>        <CreateTime>{CreateTime}</CreateTime>        <MsgType><![CDATA[text]]></MsgType>        <Content><![CDATA[{Content}]]></Content>        </xml>        """        return XmlForm.format(**self.__dict)class ImageMsg(Msg):    def __init__(self, toUserName, fromUserName, mediaId):        self.__dict = dict()        self.__dict['ToUserName'] = toUserName        self.__dict['FromUserName'] = fromUserName        self.__dict['CreateTime'] = int(time.time())        self.__dict['MediaId'] = mediaId    def send(self):        XmlForm = """        <xml>        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>        <CreateTime>{CreateTime}</CreateTime>        <MsgType><![CDATA[image]]></MsgType>        <Image>        <MediaId><![CDATA[{MediaId}]]></MediaId>        </Image>        </xml>        """        return XmlForm.format(**self.__dict)

接着我们要写一个handle.py,作为对消息进行反映处理(自动回复)的脚本。
handle.py

import webimport replyimport receiveimport JsonDataimport xml.dom.minidomclass Handle(object):    def GET(self):        try:            data = web.input()            if len(data) == 0:                return "hello, this is handle view"            signature = data.signature            timestamp = data.timestamp            nonce = data.nonce            echostr = data.echostr            token = "hello2016"            list = [token, timestamp, nonce]            list.sort()            sha1 = hashlib.sha1()            map(sha1.update, list)            hashcode = sha1.hexdigest()            #print("handle/GET func: hashcode, signature: ", hashcode, signature)            if hashcode == signature:                return echostr            else:                return ""        except Exception as Argument:            return Argument    def POST(self):        try:            webData = web.data()            #print(webData)            recMsg = receive.parse_xml(webData)            #print(recMsg)            if isinstance(recMsg, receive.Msg):                toUser = recMsg.FromUserName                fromUser = recMsg.ToUserName                if recMsg.MsgType == 'text':                    try:                        a = JsonData.praserJsonFile()                        #print(a)                    except Exception as Argument:                        return Argument                    if a['status'] == '1':                        content = "No equipment"                    else:                        if a['data'][0]['weather']=='0':                            israin = '7.没有下雨'                        else:                            israin = '7.下雨'                        #print(israin)                        content = "此设备数据如下:\n"+"1.id号为 "+a['data'][0]['id']+"\n"+"2.温度为 "+a['data'][0]['temp']+"\n"+"3.湿度为 "+a['data'][0]['humidity']+"\n"+"4.PM2.5浓度为 "+a['data'][0]['pm25']+"ug\n"+"5.PM10浓度为 "+a['data'][0]['pm10']+"\n"+"6.光照 "+a['data'][0]['illumination']+"L\n"+israin                        #content = "%s\n%s %s\n%s %s\n%s %s\n%s %s\n%s %s\n%s" %('环境数据如下:','设备id号为',a['data']['id'],'temp is', a['data']['temp'], 'humidity is', a['data']['humidity'],'PM25 is',a['data']['pm25'],'illumination',a['data']['illumination'],israin)                        #print(content)                    replyMsg = reply.TextMsg(toUser, fromUser, content)                    return replyMsg.send()                if recMsg.MsgType == 'image':                    mediaId = recMsg.MediaId                    replyMsg = reply.ImageMsg(toUser, fromUser, mediaId)                    return replyMsg.send()                if recMsg.MsgType == 'location':                    location_x = recMsg.Location_X                    location_y = recMsg.Location_Y                    content = "您所在的位置是在:经度为"+location_x+";纬度为:"+location_y                    replyMsg = reply.TextMsg(toUser, fromUser, content)                    return replyMsg.send()                if recMsg.MsgType == 'event':                    #print('yes')                    event = recMsg.Event                    if event == 'subscribe':                        content = "欢迎关注,您好!雨燕城市环境小助手微信公众号:发送 获取数据,公众号会自动发送当前环境数据(目前为调试数据,不是真实数据).将要调试GPS,根据手机定位位置与设备位置相关联,取最近距离的设备所获取到的数据并进行返回."                        replyMsg = reply.TextMsg(toUser, fromUser, content)                        return replyMsg.send()                else:                    return reply.Msg().send()            else:                print("not do")                return reply.Msg().send()        except Exception as Argment:            return Argment

注:代码贴了目前写的所有功能,接收关键字并自动返回数据;关注后自动回复欢迎文字;发送定位获得GPS信息。

那么我怎么样使用微信公众号去调取服务器上的数据呢,因为有了数据的json文件,我们就可以使用Python脚本进行json的解析,然后将数据在content中体现出来就可以了。

Json文件解析

import typesimport urllib.requestimport jsondef praserJsonFile():    url = "http://118.89.244.53:8080/index.php/home/api/present_data"    data = urllib.request.urlopen(url).read()    value = json.loads(data.decode())    #print(value)        #print(value['data'])    return value#praserJsonFile()

这个value就是我们解析json出来的一个list

阅读全文
0 0
原创粉丝点击