web微信
本节内容:
1:流程分析
2:实现
1:流程分析
前戏:
轮询:每一秒钟去查看一次 在获取到数据之前。前面的请求都是浪费的
长轮询:在轮询的基础上做了改造,http请求我要是不close请求就一直等待着数据,设置timeout为60秒。
A请求来了,让它等60秒。60秒没之内没有数据就释放这个A请求。A请求回去之后,又马上发起新的请求。
获取消息的是实时的。
websocket:这个是三种方式。就跟跟前面做的socket一样链接了,就可以相互通信。
2:实现
1.微信服务器返回一个会话ID
微信Web版本不使用用户名和密码直接登录,而是采用二维码登录,所以服务器需要首先分配一个唯一的会话ID,用来标识当前的一次登录。
通过查看网络请求我们找到了这个 二维码图片代表的随机字符串,(IcelandB9Entig==),
2.通过会话ID获得二维码
然后找到该随机字符串的来源请求
请求方式为 GET形式 , 具体连接为:
def web_login(request): global ctime,qcode ctime = time.time() response = requests.get(url="https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&fun=new&lang=zh_CN&_=%s"%(ctime,)) # print(response.text) ###获取其uuid qcode = re.findall('uuid = "(.*)"',response.text)[0] return render(request,"login.html",{"qcode":qcode})
template:
<img id="qrcode" src="https://login.weixin.qq.com/qrcode/{{ qcode }}" alt="">
3.轮询手机端是否已经扫描二维码
当我们还没进行扫码登录时,发现微信web网页会自动向服务器 轮询手机端是否已经扫码并且确认登录!!
views:
def web_check_login(request): global tip ret = {'code': 408, 'data': None} response = requests.get(url='https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=%s&tip=%s&r=1261213642&_=%s'%(qcode,tip,ctime)) print(response.text)
template中:一直循环去发现是否有人扫描、登陆
(function () { check_login(); })(); function check_login() { $.ajax({ url:"/check_login/", type:"get", dataType:"JSON", success:function (arg) { if (arg.code == 408){ checkLogin() }else if (arg.code == 201){ $('#qrcode').attr('src',arg.data); checkLogin() }else if(arg.code == 200){ console.log(arg) checkLogin() } } } ) }
response.text返回的结果:
1:window.code=408; ##二维码未扫描 2:window.code=201;window.userAvatar = 'data:img/jpg;base64,/9j/' ###扫描二维码之后的。userAvatar是头像url 3:window.code=200; window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage? \ ticket=AwG2JcXnToluQ_U5p7sMDpMA@qrticket_0&uuid=gYmByqjV8Q==&lang=zh_CN&scan=1527848607"; #点击登陆之后返回的数据。redirect_uri跳转的url
5:点击完确认登陆了。浏览器的pending的程序,会收到server发来的数据。数据如下:
window.code=200; window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage? \ ticket=AwG2JcXnToluQ_U5p7sMDpMA@qrticket_0&uuid=gYmByqjV8Q==&lang=zh_CN&scan=1527848607";
6.获取redirect_uri的地址后,requests去获取这个url返回的数据:
前提:需要带对跳转url进行一个拼接:
views:
elif 'window.code=200' in r1.text: # 用户点击确认登录, """ window.code=200; window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AYKeKS9YQnNcteZCfLeTlzv7@qrticket_0&uuid=QZA2_kDzdw==&lang=zh_CN&scan=1494553432"; window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AYKeKS9YQnNcteZCfLeTlzv7@qrticket_0&uuid=QZA2_kDzdw==&lang=zh_CN&scan=1494553432"; """ ##拼接url地址 redirect_uri = re.findall('window.redirect_uri="(.*)";', r1.text)[0] redirect_uri = redirect_uri + "&fun=new&version=v2" r2 = requests.get(url=redirect_uri) ####获取跳转的url数据 print(r2.text)
返回来的数据:
<error> <ret>0</ret> <message></message> <skey>@crypt_cfdd48c1_12905e6e90f3c3bafe66582479374d46</skey> <wxsid>ecfpaP6u4ZxiJndd</wxsid> <wxuin>2517452105</wxuin> <pass_ticket>MX4lFYu5AOTG%2FgYswPC0R4XEb7g%2FKTuR8x4Rje7cCom5JUA2KQCmsuDi%2BAWR3LSo</pass_ticket> <isgrayscale>1</isgrayscale> </error>
7:pending程序接收到了,code的请求为200之后,就到就需要发起前端的function中的初始化用户数据的url。
初始化地址:
https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=1153560198&lang=zh_CN&
pass_ticket=UERDwIQXyi7GBRdiAYfDDu%252B2qGDbM21QhkK4lYyXc9EISLWkB1KX1f7cUkWwUF9e ##是上一次的跳转url的返回数据
要携带的地址:
views:
get_user_info_data = { 'BaseRequest': { 'DeviceID': "e402310790089148", 'Sid':ticket_dict['wxsid'], 'Uin':ticket_dict['wxuin'], 'Skey':ticket_dict['skey'], } } get_user_info_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=88828930&lang=zh_CN&pass_ticket=" +ticket_dict['pass_ticket'] r3 = requests.post( url=get_user_info_url, json=get_user_info_data )