参考:https://www.52pojie.cn/thread-836149-1-1.html
1,先分析二维码,多次刷新页面对比,红色部分属于变动的参数
二维码请求地址:https://login.weixin.qq.com/qrcode/wbHpeNosSQ==
2,接着倒推,找出是哪个请求返回的此参数wbHpeNosSQ==
GET:https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage&fun=new&lang=zh_CN&_=1544935484177
响应内容:window.QRLogin.code = 200; window.QRLogin.uuid = "wbHpeNosSQ==";
分析:
请求方式:get
域名路由:https://login.wx.qq.com/jslogin
参数:
appid=wx782c26e4c19acffb(不需要管,直接带入)
redirect_uri=https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage(不需要管,直接带入)
fun=new&lang=zh_CN(不需要管,直接带入)
_=1544935484177(当前时间戳)
3,通过工具解析二维码,得到内容:https://login.weixin.qq.com/l/wbHpeNosSQ==
与二维码请求地址对比:https://login.weixin.qq.com/qrcode/wbHpeNosSQ==
也就是说当我们扫描二维码的时候,用微信访问了https://login.weixin.qq.com/l/wbHpeNosSQ==这个地址
总结:
首先浏览器访问:https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage&fun=new&lang=zh_CN&_=时间戳
获取到uuid(二维码需要的参数)
紧接着浏览器访问:https://login.weixin.qq.com/qrcode/uuid
获取到二维码
最后我们微信扫描二维码,访问了:https://login.weixin.qq.com/l/uuid
4,继续分析,图中红色部分不停的向服务器获取二维码状态,返回window.code=408;(处于等待状态)
GET访问:https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=wbHpeNosSQ==&tip=1&r=1249597736&_=1544938628299
返回:window.code=408
分析:
请求方式:get
域名路由:https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login
参数:
loginicon=true(不需要管,直接带入)
uuid=wbHpeNosSQ==(二维码重要参数)
tip=1(不需要管,直接带入)
r=1249597736(不需要管,直接带入)
_=1544938628299(当前时间戳)
window.code=408(服务器返回的数据,408代表二维码未失效,也未被扫描)
window.code=400(二维码超时,已失效)
当我们用微信扫描二维码,并登陆返回内容
window.code=200;(扫描成功,二维码已被登录)
window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A6MgV6Y2cFTdpnYpTFlIiWTB@qrticket_0&uuid=4cPXU7HERw==&lang=zh_CN&scan=1545024906";
出现redirect_uri返回的url,就代表登陆成功了,下一步访问这个地址,来获取返回用户信息和最重要的cookies
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A6MgV6Y2cFTdpnYpTFlIiWTB@qrticket_0&uuid=4cPXU7HERw==&lang=zh_CN&scan=1545024906
5,获取cookies
当我们访问redirect_uri返回的url时,从下图可以看出此链接返回了cookies,不过要注意此处访问返回的状态码301(重定向),在写代码时一定要禁用自动跳转
而返回的响应体:
{'skey': '@crypt_9bf897a2_d38a192ab54ece589fd59590a82dbcb4', 'wxsid': '9ScRHvQW23TYyyq1', 'wxuin': '2494888724', 'pass_ticket': 'nRxq1M%2BpTOyOloS4bgKofSlqKeiOcatTPd6HVhbJiz8qkgTLwGpy2ji%2Fx0xlueJQ'}
得到的是一个xml格式的消息,其中
附上python源码:
import requests import time import re import qrcode_terminal from lxml import etree """ 需要下载的模块 pip3 install qrcode_terminal pip3 install lxml """ headers = { 'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0", 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Enocding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', } class Login(): def __init__(self): # 创建会话 session = requests.session() # 设置响应头 session.headers = headers self.session = session def run(self): # 第一步:发送请求,获取二维码关键参数 url = "https://login.web.wechat.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https://web.wechat.com/cgi-bin/mmwebwx-bin/webwxnewloginpage&fun=new&lang=zh_CN&_=%s" % int( time.time() * 1000) # 发送请求 res_data = self.session.get(url) # 正则:提取uuid uuid = re.search(r'"(.*?==)', res_data.text).group(1) # 第二步:打印二维码 url = "https://login.weixin.qq.com/l/%s" % uuid qrcode_terminal.draw(url) # 第三部等待用户连接 url = "https://login.web.wechat.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=%s&tip=0&r=1765586131&_=%s" % ( uuid, int(time.time() * 1000)) while True: # 发送请求 res_data = self.session.get(url) # 正则:提取code code = re.search("redirect_uri", res_data.text) if code is not None: if code.group() == "redirect_uri": print("已确认登录!") # 正则:提取redirect_uri redirect_uri = re.search("\"(.*)\"", res_data.text).group(1) # 请求,allow_redirects=False必须禁止重定向 res_data = self.session.get(redirect_uri, allow_redirects=False) # 把返回的cookieJar转换为字典类型cookies cookies = requests.utils.dict_from_cookiejar(res_data.cookies) # etree库处理返回的xml文本,创建对象 html = etree.XML(res_data.text) # 类似于正则,分割元素, html = html.xpath("//*") # 存入字典 para = {} for i in html: if i.text is not None: para[i.tag] = i.text # 保存cookies到本地 with open("cookies.ini", "w")as f: f.write(str(cookies)) # 保存返回的内容到本地, , with open("para.txt", "w") as f: f.write(str(para)) break def __del__(self): self.session.close() if __name__ == '__main__': # 创建对象 l = Login() # 登录 l.run()