基於flask開發web微信
阿新 • • 發佈:2018-05-08
window 自己 網頁 time dal -s 最近聯系人 bin in use
流程
階段一
目標:基於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‘manage.py,‘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 htmllogin> <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‘manage
@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()manage
<!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>login
階段三:
確認登錄
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?
ticket=A9QalHCk6CY9iVdnpY9WP9os@qrticket_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/webwxnewloginpage?ticket=A7sp5sbIPRvwPK4QEwKkm6cp@qrticket_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)children
方式二: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)find_all
階段四:
目標:用戶初始化,發送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/webwxnewloginpage?ticket=A7sp5sbIPRvwPK4QEwKkm6cp@qrticket_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>index
註意
這裏發送過去的是json類型
r1 = requests.post(
url=init_url,
# 方式一:默認將json的請求發過去
json=data_dict
# 方式二:自己寫json數據 需要將請求頭寫上
# data = json.dumps(data_dict)
# headers={
# ‘Content-Type‘:‘application/json‘
# }
)
基於flask開發web微信