基于flask开发web微信
Posted jassin-du
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于flask开发web微信相关的知识,希望对你有一定的参考价值。
流程
阶段一
目标:基于falsk编写登录页面,获取二维码
解析:1:、二维码图片地址有个后缀字符串
2、图片生成之前,先获取到随机字符串再生成二维码
3、二维码的图片的来源
4、时间戳
from flask import Flask,request,render_template import time # 获取时间戳 import requests import re app = Flask(__name__) # app.run(debug=True) or app.debug = True @app.route(‘/login‘,methods=[‘GET‘,‘POST‘]) def login(): if request.method == ‘GET‘: ctime = str(int(time.time() * 1000)) qcode_url = ‘https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={0}‘.format(ctime) ret = requests.get(qcode_url) print(ret.text) # 正则 匹配出来uuid qcode = re.findall(‘uuid = "(.*)";‘,ret.text)[0] print(qcode) return render_template(‘login.html‘,qcode=qcode) else: pass if __name__ == ‘__main__‘: app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>登录页面</title> </head> <body> <div style="width: 200px;margin: 0 auto"> <h1 style="text-align: center">微信登录</h1> <img style="height: 200px;width: 200px" src="https://login.weixin.qq.com/qrcode/{{qcode}}" alt=""> </div> </body> </html>
效果
阶段二
目标:获取头像
长轮询
长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,
客户端处理完响应信息后再向服务器发送新的请求。
优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
实例:WebQQ、Hi网页版、Facebook IM。
1、长轮询
2:检测用户是否扫码,未扫码的状态码为408
3:扫码成功,并获取用户头像
利用ajax写长轮询
<!--制作长轮询--> <script src="/static/jquery-3.2.1.min.js"></script> <script> $(function () { checkLogin(); }); function checkLogin() { $.ajax({ url:‘/check_login‘, type:‘GET‘, dataType:‘JSON‘, // 指定数据类型 success:function (arg) { // 扫码 $(‘#img‘).attr(‘src‘,arg.src); checkLogin() } }) } </script>
@app.route(‘/check_login‘) def check_login(): import time time.sleep(10) return ‘asassassas‘
@app.route(‘/check_login‘) def check_login(): ‘‘‘ 未扫码的状态码为408,及其连接 https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=YdXFD_pPqg==&tip=0&r=-1052203142&_=1525764993167 需要uuid及其时间戳 :return: ‘‘‘ response = {‘code‘:408} qcode = session.get(‘qcode‘) ctime = str(int(time.time() * 1000)) check_url = ‘https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip=0&r=-1052203142&_={1}‘.format(qcode,ctime) # 发送get请求检测是否扫码 ret = requests.get(check_url) print(ret.text) # 不扫码则返回408 window.code=408; if "code=201" in ret.text: # 扫码成功 生成用户头像 src = re.findall("userAvatar = ‘(.*)‘;",ret.text)[0] # print(src) # 获取到用户的头像地址 response[‘code‘] = 201 response[‘src‘] = src return jsonify(response) if __name__ == ‘__main__‘: app.run()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>登录页面</title> </head> <body> <div style="width: 200px;margin: 0 auto"> <h1 style="text-align: center">微信登录</h1> <img id="img" style="height: 200px;width: 200px" src="https://login.weixin.qq.com/qrcode/{{qcode}}" > </div> <!--制作长轮询--> <script src="/static/jquery-3.2.1.min.js"></script> <script> $(function () { checkLogin(); }); function checkLogin() { $.ajax({ url:‘/check_login‘, type:‘GET‘, dataType:‘JSON‘, // 指定数据类型 success:function (arg) { if(arg.code === 201){ // 扫码 $(‘#img‘).attr(‘src‘,arg.src); }else if(arg.code === 200){ // 重定向到用户信息列表 location.href = ‘/index‘ }else { checkLogin(); } } }) } </script> </body> </html>
阶段三:
确认登录
1、获取凭证信息
接着会往这个地址发送请求,获取凭证(xml格式)
注意
确认登录的地址
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A9QalHCk6CY9iVdnpY9WP9os
@qrticket_0&uuid=QcVoiPFXYw==&lang=zh_CN&scan=1525771690
获取凭证地址
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?
[email protected]_0&uuid=QcVoiPFXYw==&lang=zh_CN&scan=1525771690
&fun=new&version=v2&lang=zh_CN
初始化
当发的数据是json格式就用payload
为字典格式 发送过去的数据
BaseRequest: {Uin: "736490221", Sid: "5S/x/NshjYS7Oq1T", Skey:"@crypt_34187f1b_b2d9f745b8ea17106a3aed8f64b6bd36",…} DeviceID:"e132063792738476" Sid:"5S/x/NshjYS7Oq1T" Skey:"@crypt_34187f1b_b2d9f745b8ea17106a3aed8f64b6bd36" Uin:"736490221"
上面是需要凭证的一些内容
凭证的数据
<error> <ret>0</ret> <message></message>
<skey>@crypt_34187f1b_94ee8455819fb0b67ee356a1d34f6d7c</skey>
<wxsid>oWrr1oPRVKLNs4SI</wxsid> <wxuin>736490221</wxuin>
<pass_ticket>svwwPifX3lEpWr36wXSEc4ufYTQZ9r5i6UmJvTXxfz168gMQtXuSskG%2FCb5%2B3tfy</pass_ticket> <isgrayscale>1</isgrayscale> </error>
最终取值方式
ticket_dict = session.get(‘ticket_dict‘)
init_url = ‘https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1058298025&lang=zh_CN&pass_ticket={0}‘.format(ticket_dict.get("pass_ticket"))
data_dict = {
"BaseRequest":{
"DeviceID":"e132063792738476",
"Sid":ticket_dict.get("wxsid"),
"Skey":ticket_dict.get("Skey"),
"Uin":ticket_dict.get("wxuin")
}
}
@app.route(‘/check_login‘) def check_login(): ‘‘‘ 未扫码的状态码为408,及其连接 https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=YdXFD_pPqg==&tip=0&r=-1052203142&_=1525764993167 需要uuid及其时间戳 :return: ‘‘‘ response = {‘code‘:408} qcode = session.get(‘qcode‘) ctime = str(int(time.time() * 1000)) check_url = ‘https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip=0&r=-1052203142&_={1}‘.format(qcode,ctime) # 发送get请求检测是否扫码 ret = requests.get(check_url) # print(ret.text) # 不扫码则返回408 window.code=408; if "code=201" in ret.text: # 扫码成功 生成用户头像 src = re.findall("userAvatar = ‘(.*)‘;",ret.text)[0] # print(src) # 获取到用户的头像地址 response[‘code‘] = 201 response[‘src‘] = src elif ‘code=200‘ in ret.text: # 确认登录 ‘‘‘ window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/[email protected]_0&uuid=4bMd7uwPpg==&lang=zh_CN&scan=1525769290"; ‘‘‘ # 获取凭证的地址 redirect_url = re.findall(‘redirect_uri="(.*)";‘,ret.text)[0] # 到取凭证的地址得到凭证 redirect_uri = redirect_url + "&fun=new&version=v2" ticket_ret = requests.get(redirect_uri) print(ticket_ret.text) # 解析 字典 ticket_dict = xml_parser(ticket_ret.text) # 下面初始化需用到凭证 session[‘ticket_dict‘] = ticket_dict response[‘code‘] = 200 return jsonify(response)
关于解析xml数据
方式一:children
from bs4 import BeautifulSoup text ="""<error><ret>0</ret> <message></message><skey>@crypt_2ccf8ab9_70b4bfadb5aeb520357d4ecf46c23713</skey><wxsid>xryEESU5QgXX61ji</wxsid><wxuin>981579400</wxuin><pass_ticket>3nIORdKsOyenOh1%2FoH4U17Qhw8YBkGHJl%2BfqVvaoGoDnmBoQxEJdA%2BZyuHixW1Ow</pass_ticket><isgrayscale>1</isgrayscale></error>""" soup = BeautifulSoup(text,‘html.parser‘) div = soup.find(name=‘error‘) for i in div.children: print(i)
方式二:find_all,参数recursive,=True(递归,往子子孙孙里面找) =false(只找儿子)
from bs4 import BeautifulSoup def xml_parser(text): dic = {} soup = BeautifulSoup(text,‘html.parser‘) div = soup.find(name=‘error‘) for item in div.find_all(recursive=False): dic[item.name] = item.text return dic text ="""<error><ret>0</ret> <message></message><skey>@crypt_2ccf8ab9_70b4bfadb5aeb520357d4ecf46c23713</skey><wxsid>xryEESU5QgXX61ji</wxsid><wxuin>981579400</wxuin><pass_ticket>3nIORdKsOyenOh1%2FoH4U17Qhw8YBkGHJl%2BfqVvaoGoDnmBoQxEJdA%2BZyuHixW1Ow</pass_ticket><isgrayscale>1</isgrayscale></error>""" dic = xml_parser(text) print(dic)
阶段四:
目标:用户初始化,发送POST请求:、
from flask import Flask,request,render_template,session,jsonify import time # 获取时间戳 import requests import re from bs4 import BeautifulSoup app = Flask(__name__) # app.run(debug=True) or app.debug = True app.secret_key = ‘safsfsfs‘ # 生成密钥, 头像 # 解析xml文件 def xml_parser(text): dic = {} soup = BeautifulSoup(text,‘html.parser‘) div = soup.find(name=‘error‘) for item in div.find_all(recursive=False): dic[item.name] = item.text return dic @app.route(‘/login‘,methods=[‘GET‘,‘POST‘]) def login(): if request.method == ‘GET‘: ctime = str(int(time.time() * 1000)) qcode_url = ‘https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={0}‘.format(ctime) ret = requests.get(qcode_url) print(ret.text) # 正则 匹配出来uuid qcode = re.findall(‘uuid = "(.*)";‘,ret.text)[0] # 将uuid放到session里面以便下面调用 session[‘qcode‘] = qcode print(qcode) return render_template(‘login.html‘,qcode=qcode) else: pass @app.route(‘/check_login‘) def check_login(): ‘‘‘ 未扫码的状态码为408,及其连接 https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=YdXFD_pPqg==&tip=0&r=-1052203142&_=1525764993167 需要uuid及其时间戳 :return: ‘‘‘ response = {‘code‘:408} qcode = session.get(‘qcode‘) ctime = str(int(time.time() * 1000)) check_url = ‘https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip=0&r=-1052203142&_={1}‘.format(qcode,ctime) # 发送get请求检测是否扫码 ret = requests.get(check_url) # print(ret.text) # 不扫码则返回408 window.code=408; if "code=201" in ret.text: # 扫码成功 生成用户头像 src = re.findall("userAvatar = ‘(.*)‘;",ret.text)[0] # print(src) # 获取到用户的头像地址 response[‘code‘] = 201 response[‘src‘] = src elif ‘code=200‘ in ret.text: # 确认登录 ‘‘‘ window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/[email protected]_0&uuid=4bMd7uwPpg==&lang=zh_CN&scan=1525769290"; ‘‘‘ # 获取凭证的地址 redirect_url = re.findall(‘redirect_uri="(.*)";‘,ret.text)[0] # 到取凭证的地址得到凭证 redirect_uri = redirect_url + "&fun=new&version=v2" ticket_ret = requests.get(redirect_uri) print(ticket_ret.text) # 解析 字典 ticket_dict = xml_parser(ticket_ret.text) # 下面初始化需用到凭证 session[‘ticket_dict‘] = ticket_dict response[‘code‘] = 200 return jsonify(response) @app.route(‘/index‘) def index(): ‘‘‘ 用户初始化: https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1058298025&lang=zh_CN&pass_ticket=9179zbgvzg%252BstA95JF5QmlL1mQ%252BLKqunCOs56ac%252FejGXMC9WrgwRoUi4N7xkdDNL ‘‘‘ ticket_dict = session.get(‘ticket_dict‘) init_url = ‘https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1058298025&lang=zh_CN&pass_ticket={0}‘.format(ticket_dict.get("pass_ticket")) data_dict = { "BaseRequest":{ "DeviceID":"e132063792738476", "Sid":ticket_dict.get("wxsid"), "Skey":ticket_dict.get("Skey"), "Uin":ticket_dict.get("wxuin") } } r1 = requests.post( url=init_url, json=data_dict ) # 编码 r1.encoding = ‘utf-8‘ user_dict = r1.json() print(user_dict) return render_template(‘/index.html‘,user_dict=user_dict) if __name__ == ‘__main__‘: app.run()
<!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>欢迎登录:{{user_dict.User.NickName}}</h1> <h3>最近联系人</h3> <ul> {% for user in user_dict.ContactList%} <li>{{user.NickName}}</li> {% endfor %} </body> </html>
注意
这里发送过去的是json类型
r1 = requests.post(
url=init_url,
# 方式一:默认将json的请求发过去
json=data_dict
# 方式二:自己写json数据 需要将请求头写上
# data = json.dumps(data_dict)
# headers={
# ‘Content-Type‘:‘application/json‘
# }
)
以上是关于基于flask开发web微信的主要内容,如果未能解决你的问题,请参考以下文章
学习参考《Flask Web开发:基于Python的Web应用开发实战(第2版)》中文PDF+源代码
[分享]《Flask Web开发:基于Python的Web应用开发实战(第2版)》中文PDF+源代码