基于aiohttp web框架的微信公众号开发(项目)

微信公众号基础开发概知(个人理解)

微信公众号:
    把用户的请求转发给服务器,服务器对请求进行处理,然后按照微信的规则返还请求,再由公众号把结果显示给用户。(类似浏览器) 

linux 服务器:
   linux 服务器上的web服务才是真正的对用户请求进行正真的处理和响应。

linux服务器环境配置
    python3.6 + aiohttp web框架 + mysql数据库

linux服务器aiohttp web框架

关于aiohttp web框架主体有以下部分:
(关于aiohttp web框架可学习廖雪峰Python教程实战部分 https://www.liaoxuefeng.com

关于微信部分程序
1
微信公众号大概原理:微信公众号是当用户发送给公众号请求时,微信公众号会把用户请求包装,给web服务器发送一个对应的http请求,web会处理此请求,并把结果返还给公众号,公众号再把结果进行对应解析,发送给用户。
2
handler.py 就是把公众号发送来的请求进行处理,再返还给公众号,定义了一系列处理方法。
3
basic.py   服务器与公众号连接的验证信息设置。
4
recevie.py 对于公众号发来的请求进行解析的一些处理函数。
5
reply.py   服务器返还公众号数据的格式(将返还数据格式转换为公众号能处理的格式)
(关于微信部分学习微信公众号技术文档 https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1472017492_58YV5


项目 雾霾监测系统 说明(仅说明微信公众号相关程序,不详细说明aiohttp web框架通用部分)

    雾霾监测系统主要由两部分构成:
    1是雾霾检测装置上传数据给服务器的数据库,服务器接收;
    2是服务器数据库在发现用户请求本地雾霾数据信息时,从数据库提取对应信息并推送。

app.py 主体程序


数据库的创建和web框架的信息对应

    数据库mysql库创建(sql语句)
1
drop database if exists hazeserver;
2
3
create database hazeserver;
4
5
use hazeserver;
6
7
grant select,insert,update,delete on hazeserver.* to 'haze'@'127.0.0.1' identified by 'hazepasswd';
8
9
CREATE TABLE messages(
10
`id` VARCHAR(50) not null, 
11
`addr` VARCHAR(50) not null,
12
`data` VARCHAR(50) not null,
13
`pm25` VARCHAR(20) not null,
14
`pm10` VARCHAR(20) not null,
15
PRIMARY KEY (`id`)
16
)engine=innodb default charset=utf8;
(库中存放雾霾监测点地址,时间和对应的pm2.5和pm10值,id为唯一索引)
对应
    models.py 对应数据库表单的定义:

雾霾检测装置上传数据给服务器的数据库,服务器接收

handlers.py
1
# 数据输入
2
@get('/messages')
3
async def messages(addr, pm25, pm10):
4
    data = time.strftime('%Y-%m-%d %H:%M')
5
    messages = Messages(addr = addr, data = data, pm25 = pm25, pm10 = pm10)
6
    await messages.save()
7
    response = '<h1>OK!!!</h1>'
8
    return web.Response(body=response.encode('utf-8'), content_type='text/html')
雾霾监测传感装置通过http请求来上传数据:
格式example:
http://139.199.82.84/messages?addr=xautnew&pm25=100&pm10=200

登录到数据库查看如下

服务器数据库在发现用户请求本地雾霾数据信息时,从数据库提取对应信息并推送

    微信基本配置验证
1
# 微信基本配置验证
2
# 微信接口测试发送请求为:
3
# "GET /weixin?signature=...&echostr=...&timestamp=...&nonce=... HTTP/1.0" 200 173 "-" "Mozilla/4.0"
4
@get('/weixin')
5
async def getwx(signature,echostr,timestamp,nonce):
6
    # wxdict = request_query_url(request.query_string)
7
    # signature = wxdict['signature']
8
    # echostr = wxdict['echostr']
9
    # timestamp = wxdict['timestamp']
10
    # nonce = wxdict['nonce']
11
    token='weixin' # 此处填写平台的token
12
    # 字典序排序(以下为微信验证哈希处理)
13
    tmp_list = [token, timestamp, nonce]
14
    tmp_list.sort()
15
    tmp_str = "%s%s%s" % tuple(tmp_list)
16
    tmp_str = hashlib.sha1(tmp_str.encode('utf8')).hexdigest()
17
    if tmp_str == signature:
18
        return web.Response(body=echostr)

    用户向微信公众号发送请求时,公众号会对服务器的web应用 以post的方式发送对应信息的xml格式的数据流的http请求,服务器处理完成后也会以xml格式进行回复。

    receive.py 微信对请求xml数据进行提取
reply.py web 回复微信的格式
1
#!/usr/bin/env python3
2
# -*- coding: utf8 -*-
3
4
# 对微信回复信息进行格式规范
5
import time
6
7
class Msg(object):
8
    def __init__(self):
9
        pass
10
    def send(self):
11
        return "success"
12
13
class TextMsg(Msg):
14
    def __init__(self, toUserName, fromUserName, content):
15
        self.__dict = dict()
16
        self.__dict['ToUserName'] = toUserName
17
        self.__dict['FromUserName'] = fromUserName
18
        self.__dict['CreateTime'] = int(time.time())
19
        self.__dict['Content'] = content
20
21
    def send(self):
22
        XmlForm = """<xml>
23
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
24
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
25
        <CreateTime>{CreateTime}</CreateTime>
26
        <MsgType><![CDATA[text]]></MsgType>
27
        <Content><![CDATA[{Content}]]></Content>
28
        </xml>
29
        """
30
        return XmlForm.format(**self.__dict)
31
32
33
class ImageMsg(Msg):
34
    def __init__(self, toUserName, fromUserName, mediaId):
35
        self.__dict = dict()
36
        self.__dict['ToUserName'] = toUserName
37
        self.__dict['FromUserName'] = fromUserName
38
        self.__dict['CreateTime'] = int(time.time())
39
        self.__dict['MediaId'] = mediaId
40
41
    def send(self):
42
        XmlForm = """
43
        <xml>
44
        <ToUserName><![CDATA[{ToUserName}]]></ToUserName>
45
        <FromUserName><![CDATA[{FromUserName}]]></FromUserName>
46
        <CreateTime>{CreateTime}</CreateTime>
47
        <MsgType><![CDATA[image]]></MsgType>
48
        <Image>
49
        <MediaId><![CDATA[{MediaId}]]></MediaId>
50
        </Image>
51
        </xml>
52
        """
53
        return XmlForm.format(**self.__dict)
    web 关于微信的接口程序
   1.首次关注自动回复
   2.用户发送请求,回复对应请求所需数据,其中数据是从数据库进行调用对应地址最新的1条数据信息。

测试效果图(图片是以前的)


遇到的问题:
  遇到主要问题是当时雾霾检测装置上传数据,因为用的网络传输,自身服务器有带http服务,所以选择http传输最简单,再考虑下传输数据量不大,直接就是用get的方式进行访问传输数据。
  参数解析当时是遇到了个坎。
  查手册,http协议,了解到参数是放到了‘requst.query_string'的字符中。
  开始时是一直以为原框架没有提参(其实没看懂。。),就用了一个相当相当low的方法来提参,利用正则表达式,把query_string存储的字符全读出然后切切切,分割完后存入字典。然后调用。如下程序中,把变量和值通过split切割,然后分别放入列表,再把列表转换为字典。
1
+# 导入正则库
2
 +import re
3
 +'''
4
 +# url的请求参数解析函数
5
 +def request_query_url(query_url_string):
6
 +    # 正则分割把参数提取转换成列表
7
 +    rq = re.split(r'[&=]', query_url_string)
8
 +    # 把参数中的变量和值分别对应放入两个列表
9
 +    i = 0
10
 +    rq1 = []
11
 +    rq2 = []
12
 +    for element in rq:
13
 +        if i % 2 == 0:
14
 +            rq1.append(element)
15
 +        else:
16
 +            rq2.append(element)
17
 +        i = i + 1
18
 +    # 将两个列表转换为字典
19
 +    rq_dict = dict(zip(rq1, rq2))
20
 +    # 返回字典
21
 +    return rq_dict
22
 +'''
23
 +# API 数据输入
24
 +@get('/messages')
25
 +async def messages(addr, data, pm25, pm10):
26
 +    # messagesdict = request_query_url(request.query_string)
27
 +    # addr = messagesdict['addr']
28
 +    # data = messagesdict['data']
29
 +    # pm25 = messagesdict['pm25']
30
 +    # pm10 = messagesdict['pm10']
31
 +    messages = Messages(addr = addr, data = data, pm25 = pm25, pm10 = pm10)
32
 +    await messages.save()
33
 +    response = '<h1>OK!!!</h1>'
34
 +    return web.Response(body=response.encode('utf-8'), content_type='text/html')
后来,觉得不可能啊,web框架杂可能没有参数提取,就再查查,仔细再看程序。才发现,原框架确实是用了解析,不过,挺难还绕。如下是封装的参数调用。

    通过装饰器来来附参数。
    类定义解析参数的处理,解析query_string直接用的是parse.parse_qs解析成参,然后通过for...in...放入字典。
1
# 作用是把handlers中url处理函数需接收的参数分析出来
2
# 从request(http请求的对象)中获取请求的参数
3
# 把request的参数放入对应的url处理函数中
4
class RequestHandler(object):
5
    def __init__(self, func):
6
        self._func = func
7
    # 定义__call__方法可是为函数,导入request参数(对request处理)
8
    async def __call__(self, request):
9
        # 获取函数的需传入参数存入required_args字典{key(参数名),value(inspect.Parameter对象(包含参数信息))}
10
        required_args = inspect.signature(self._func).parameters
11
        logging.info('requerid args:%s' % required_args)
12
13
        # 获取url请求参数存入request_data字典
14
        if request.method == 'GET':
15
            qs = request.query_string
16
            request_data = {key:value[0] for key,value in parse.parse_qs(qs, True).items()}
17
            logging.info('request form:%s' % request_data)
18
        # 因为微信POST过来数据不规则,所以不在此对数据进行参数提取
19
        else:
20
            request_data = {}
21
22
        # kw字典即是把函数需要的参数从request中提取出来
23
        kw = { arg : value for arg, value in request_data.items() if arg in required_args}
24
25
        # 添加request参数
26
        if 'request' in required_args:
27
            kw['request'] = request
28
        # 检测参数表中有没有缺失
29
        for key, arg in required_args.items():
30
            # request参数不能为可变长参数
31
            if key == 'request' and arg.kind in (arg.VAR_POSITIONAL, arg.VAR_KEYWORD):
32
                return web.HTTPBadRequest(text='request parameter cannot be the var argument.')
33
            # 如果参数类型不是变长列表和变长字典,变长参数是可缺省的
34
            if arg.kind not in (arg.VAR_POSITIONAL, arg.VAR_KEYWORD):
35
                # 如果还是没有默认值,而且还没有传值的话就报错
36
                if arg.default == arg.empty and arg.name not in kw:
37
                    return web.HTTPBadRequest(text='Missing argument: %s' % arg.name)
38
39
        logging.info('call with args: %s' % kw)
40
        # 将request参数填入函数
41
        try:
42
            return await self._func(**kw)
43
        except APIError as e:
44
            return dict(error=e.error, data=e.data, message=e.message)

完整基于aiohttp web框架的微信公众号工程 https://github.com/msun1996/Hazeweb 
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值