最近忙国赛的一个项目,我得做一个微信公众号。功能就是调数据并回复给用户,需要用户发送给公众号一个关键词,通过关键词自动回复消息。
这时就是查询微信公众平台文档了,地址如下: 文档
按照它的入门指南,我基本上了解了用户给公众号发送消息的一个机制,并且一旦给公众号发送消息,在开发者后台,会收到公众平台发送的一个xml,所以通过编写Python脚本进行xml的解析与自动发送功能。
如果用户给公众号发送一段text消息,比如“hello”,那么后台就会收到一个xml为:
1
2
3
4
5
6
7
|
< 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
1
2
3
4
5
6
7
8
9
10
11
12
|
# -*- coding: utf-8 -*-
# filename: main.py
import web
from handle import Handle
urls = (
'/wx' , 'Handle' ,
)
if __name__ = = '__main__' :
app = web.application(urls, globals ())
app.run()
|
然后写一个receive.py,作为接受用户发送过来的数据,并解析xml,返回数据的脚本。
receive.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
import xml.etree.ElementTree as ET
def 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' ).text
class 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' ).text
class 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' ).text
class 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' ).text
class 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换了一下而已,内容自己定。
1
2
3
4
5
6
7
|
< xml >
< ToUserName > <![CDATA[粉丝号]]> </ ToUserName >
< FromUserName > <![CDATA[公众号]]> </ FromUserName >
< CreateTime >1460541339</ CreateTime >
< MsgType > <![CDATA[text]]> </ MsgType >
< Content > <![CDATA[test]]> </ Content >
</ xml >
|
reply.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import time
class 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
import web
import reply
import receive
import JsonData
import xml.dom.minidom
class 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文件解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import types
import urllib.request
import json
def 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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/karry_zzj/article/details/78451901