QQ空间模拟登陆

Posted lfri

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QQ空间模拟登陆相关的知识,希望对你有一定的参考价值。

分析

一般地,QQ空间可以通过手机QQ扫码登录和账号密码登录。但是账号密码登录有时候需要验证码,为了保证登录的成功率,我们选择扫码登录的方式。

首先,进入登录界面:

https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https://qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone&pt_qr_app=手机QQ空间&pt_qr_link=https://z.qzone.com/download.html&self_regurl=https://qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=https://z.qzone.com/download.html&pt_no_auth=0

简单抓包可以发现二维码登录的接口很可能是这个(ptqrlogin看着就像是二维码登录):

技术图片

看下请求这个链接需要哪些参数吧:

技术图片

测试一下,可以发现大部分参数是固定的,我们只需要知道以下参数就行啦:

action
login_sig
ptqrtoken

action

很显然,action的构造方式应该是这样的:

0-0-+时间戳

login_sig

好像好几个url返回的都cookie都含有login_sig参数,选一个简单点的 https://xui.ptlogin2.qq.com/cgi-bin/xlogin?(因为它的参数都是固定的)

ptqrtoken

全局搜索一下,可以发现ptqrtoken这个参数在某个js文件里写了计算方式:

技术图片

可见 ptqrtoken=hash33(qrsig),在全局搜索一下,发现hash33的定义如下:

function hash33(t) {
    for (var e = 0, i = 0, n = t.length; i < n; ++i)
        e += (e << 5) + t.charCodeAt(i);
    return 2147483647 & e
}

转为等价python代码就是:

def decryptQrsig(qrsig):
    e = 0
    for c in qrsig:
      e += (e << 5) + ord(c)
    return 2147483647 & e

那么,现在的问题就是qrsig这个参数如何获得呢?和login_sig参数类似,容易发现请求如下链接,在返回的cookies里可以得到qrsig这个参数的值:

技术图片

它的参数也比较简单,除了t其他参数都是不变的,感觉t像个随机数,就当是个随机数呗(反正位数也都是16位)。

至此,3个最重要的参数构造方式都得到了。

代码

import requests
import time
import random
import os
import sys
import re
import warnings
warnings.filterwarnings(ignore)


xlogin_url = https://xui.ptlogin2.qq.com/cgi-bin/xlogin?
qrshow_url = https://ssl.ptlogin2.qq.com/ptqrshow?
qrlogin_url = https://ssl.ptlogin2.qq.com/ptqrlogin?
headers = {
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
}

session = requests.Session()
cur_path = os.getcwd()

def hash33(qrsig):
    e = 0
    for c in qrsig:
        e += (e << 5) + ord(c)
    return 2147483647 & e


# 保存图片
def saveImage(img, img_path):
    if os.path.isfile(img_path):
        os.remove(img_path)
    with open(img_path, wb) as f:
        f.write(img)
        f.close()


# 展示图片
def showImage(img_path):
    if sys.platform.find(darwin) >= 0:
        subprocess.call([open, img_path])
    elif sys.platform.find(linux) >= 0:
        subprocess.call([xdg-open, img_path])
    else:
        os.startfile(img_path)
    return True

# 获取pt_login_sig
params = {
    proxy_url: https://qzs.qq.com/qzone/v6/portal/proxy.html,
    daid: 5,
    hide_title_bar: 1,
    low_login: 0,
    qlogin_auto_login: 1,
    no_verifyimg: 1,
    link_target: blank,
    appid: 549000912,
    style: 22,
    target: self,
    s_url: https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone,
    pt_qr_app: 手机QQ空间,
    pt_qr_link: https://z.qzone.com/download.html,
    self_regurl: https://qzs.qq.com/qzone/v6/reg/index.html,
    pt_qr_help_link: https://z.qzone.com/download.html,
    pt_no_auth: 0
}
all_cookies = {}
res = session.get(xlogin_url, headers=headers, verify=False, params=params)
all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))
pt_login_sig = all_cookies[pt_login_sig]
print(pt_login_sig)

# 获取ptqrtoken
params = {
    appid: 549000912,
    e: 2,
    l: M,
    s: 3,
    d: 72,
    v: 4,
    t: str(random.random()),
    daid: 5,
    pt_3rd_aid: 0
}
res = session.get(qrshow_url, headers=headers, verify=False, params=params)
all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))
ptqrtoken = hash33(all_cookies[qrsig])
print(ptqrtoken)
# 保存验证码图片
saveImage(res.content, os.path.join(cur_path, qrcode.jpg))
showImage(os.path.join(cur_path, qrcode.jpg))
session.cookies.update(all_cookies)

# 检测二维码状态
while True:
    params = {
        u1: https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone,
        ptqrtoken: ptqrtoken,
        ptredirect: 0,
        h: 1,
        t: 1,
        g: 1,
        from_ui: 1,
        ptlang: 2052,
        action: 0-0- + str(int(time.time())),
        js_ver: 20010217,
        js_type: 1,
        login_sig: pt_login_sig,
        pt_uistyle: 40,
        aid: 549000912,
        daid: 5
    }
    res = session.get(qrlogin_url, headers=headers, verify=False, params=params)
    print(res.text)
    if 二维码未失效 in res.text:
        break    
    elif 二维码已经失效 in res.text:
        raise RuntimeError(Fail to login, qrcode has expired...)
    time.sleep(2)

 

 

参考链接:

1. https://zhuanlan.zhihu.com/p/95888605

2. https://github.com/CharlesPikachu/DecryptLogin/blob/master/DecryptLogin/platforms/QQZone.py

以上是关于QQ空间模拟登陆的主要内容,如果未能解决你的问题,请参考以下文章

❤️Java实现模拟QQ(消息通信+登陆界面美化)❤️

为啥我的qq空间里的权限设置里面找不到“qq登陆”?

基于Selenium库模拟用户行为的QQ空间爬虫

WPF和Expression Blend开发实例:模拟QQ登陆界面打开和关闭特效

Xcode上的ios模拟器怎么开QQ啊,求教各位大神

电脑怎么登陆多个qq