python模拟qq空间登录_模拟登录系列 | QQ空间模拟登录

原文链接模拟登录系列 | QQ空间模拟登录​mp.weixin.qq.com

本系列所有代码均在这CharlesPikachu/DecryptLogin​github.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看着就像是二维码登录):

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

测试一下,可以发现大部分参数是固定的,即:

u1:https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone

ptredirect: 0

h: 1

t: 1

g: 1

from_ui: 1

ptlang: 2052

js_ver: 19112817

js_type: 1

pt_uistyle: 40

aid: 549000912

daid: 5

ptdrvs: AnyQUpMB2syC5zV6V4JDelrCvoAMh-HP6Xy5jvKJzHBIplMBK37jV1o3JjBWmY7j*U1eD8quewY_

has_onekey: 1

所以我们只需要知道以下参数就行啦:

action

login_sig

ptqrtoken

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

'0-0-'+时间戳

至于login_sig参数,容易发现可以通过请求以下链接:

然后在返回的cookies里得到login_sig参数。

而请求:

https://xui.ptlogin2.qq.com/cgi-bin/xlogin?

需要携带的参数为:

通过测试可以发现上面这些参数都是固定的。最后就剩下ptqrtoken这个参数啦,全局搜索一下,可以发现ptqrtoken这个参数在某个js文件里写了计算方式:

其中,hash33的js代码为:

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这个参数的值:

而请求:

https://ssl.ptlogin2.qq.com/ptqrshow

需要携带的参数如下图所示:

除了t其他参数都是不变的,感觉t像个随机数(因为测试了下,发现t就算一直保持不变也没关系),既然影响不大,就懒得继续分析t到底是个啥了,就当是个随机数呗(反正位数也都是16位)。

OK,到此为止,我们大概已经了解了整个模拟登录的流程了,那就开始边写代码边进一步明确该流程呗~首先自然是获得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'

}

res = self.session.get(self.xlogin_url, headers=self.headers, verify=False, params=params)

all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))

pt_login_sig = all_cookies['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 = self.session.get(self.qrshow_url, headers=self.headers, verify=False, params=params)

all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))

ptqrtoken = self.__decryptQrsig(all_cookies['qrsig'])

同时,在请求上述链接的过程中,也就是:

https://ssl.ptlogin2.qq.com/ptqrshow

我们还可以获得二维码图片(即res.content其实就是二维码的图片数据),并将其显示出来:

saveImage(res.content, 'qrcode.jpg')

showImage('qrcode.jpg')

接着我们通过不断请求一开始发现的二维码登录链接,即:

https://ssl.ptlogin2.qq.com/ptqrlogin

来检测二维码当前的状态:

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': '19112817',

'js_type': '1',

'login_sig': pt_login_sig,

'pt_uistyle': '40',

'aid': '549000912',

'daid': '5',

'ptdrvs': 'AnyQUpMB2syC5zV6V4JDelrCvoAMh-HP6Xy5jvKJzHBIplMBK37jV1o3JjBWmY7j*U1eD8quewY_',

'has_onekey': '1'

}

res = self.session.get(self.qrlogin_url, headers=self.headers, verify=False, params=params)

if '登录成功' in res.text:

break

elif '二维码已经失效' in res.text:

raise RuntimeError('Fail to login, qrcode has expired...')

time.sleep(2)

若登录成功,则用该请求返回的链接来更新session的cookies从而获得最终的QQ空间登录会话对象:

all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))

qq_number = re.findall(r'&uin=(.+?)&service', res.text)[0]

print('[INFO]: Account -> %s, login successfully...' % qq_number)

url_refresh = res.text[res.text.find('http'): res.text.find('pt_3rd_aid=0')] + 'pt_3rd_aid=0'

self.session.cookies.update(all_cookies)

res = self.session.get(url_refresh, allow_redirects=False, verify=False)

all_cookies.update(requests.utils.dict_from_cookiejar(res.cookies))

self.session.cookies.update(all_cookies)

OK,大功告成,完整源代码详见最前面的Github链接(小伙伴们记得随手给的星呀~)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值