• 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

  • 相关阅读:
    LeeCode-Spiral Matrix II
    HDU1281(二分图最大匹配,棋盘建图,找关键点)
    HDU1083(二分图最大匹配vector实现)
    HDU2444(判断是否为二分图,求最大匹配)
    HDU1166(线段树单点更新区间查询)
    HDU1045(二分图经典建模)
    POJ1220(大数进制转换)
    POJ3466(01背包变形)
    POJ3180(有向图强连通分量结点数>=2的个数)
    POJ1236 (强连通分量缩点求入度为0和出度为0的分量个数)
  • 原文地址:https://www.cnblogs.com/lfri/p/12207472.html
Copyright © 2020-2023  润新知