以pay.qq.com查詢QQ賬號Q幣信息為例,了解一下網站的二維碼登陸大致是如何實現的
首先打開騰訊pay.qq.com主頁上的登陸就可以獲取到二維碼了,使用瀏覽器的F12分析請求過程
發現通過打開的https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=11000101&target=self&style=40&s_url=https://pay.qq.com/ipay/login-proxy.html可以獲取到cookies,這個url就先記下來
繼續往下,打開下面的url,響應回來的就是二維碼了
那這些請求的參數是如何得到的呢,多次請求分析發現只有t是隨機變化的,那就給個隨機數吧
參數t的python生成方式(python生成的隨機數多一位)
import random a=str(random.random()) print(a) print(a[:-1])
當用手機掃了二維碼之后,會發現一直請求一個地址,而返回的內容就是判定二維碼是否過期的結果。但是請求的url隨二維碼的更新而變化的
獲取是否過期(通過請求的url發現如下規律)
https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1300613866&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514654333018&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&
https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1641999182&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514655242011&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&
https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken=1460309603&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1514656150867&js_ver=10233&js_type=1&login_sig=pGo5iOnV6O*DY3BgsPM22zAvlWCnVl48PPjrmWIJtQKMHpvYCoWpavmP1JcdWn6g&pt_uistyle=40&aid=11000101&
這些url返回結果如下這樣的形式
ptuiCB('66','0','','0','二維碼未失效。(2079330212)', '')
那么,這次的url所附帶的參數更多了,究竟是如何生成的,由於沒有學習過JavaScript,但是猜想這種交互式的網頁一定有js控制的。
打開請求主頁中所有的js鏈接,文件中都沒有相關信息,於是重頭分析請求過程,發現請求了一個url里面返回大量函數,里面有且僅有一個ptqrtoken變量
https://imgcache.qq.com/ptlogin/ver/10233/js/c_login_2.js?max_age=604800&ptui_identifier=000E010D989AA31CE07BA6E98F56BC76012729B221D540BFF0DE375CAC8A
這個url返回的代碼里面找到getSubmitUrl函數如下:
三個參數ptqrtoken、action、login_sig。兩個參數都在函數中說明了,login_sig同樣在這段返回的代碼里面,事實上就是cookies里面的pt_login_sig
於是乎可以試着構造一個這樣的url,判斷二維碼是否有效。響應的代碼里面跟三個參數有關的代碼如下
函數的具體實現—ptqrtoken生成
hash33:function(t){
for(var e=0,i=0,n=t.length;i<n;++i)
e+=(e<<5)+t.charCodeAt(i);
return 2147483647&e
}
函數的具體實現—action生成
,pt.plogin={account:"",at_account:"",uin:"",salt:"",checkState:!1,lastCheckAccount:"",needVc:!1,vcFlag:!1,ckNum:{},action:[0,0],passwordErrorNum:1,isIpad:!1,seller_id:703010802
action.join(“-”)+”-”+(new Date-0)
函數的具體實現—login_sig生成(這個是http響應時返回的)
login_sig=pt.ptui.login.sig
用javascript測試下實現函數功能的代碼(不懂js所以先試下運行出來是什么結果)
1、ptqrtoken
<script type="text/javascript">
document.write(isNaN(123)+ "<br />")
function test(t){
for(var e=0,i=0,n=t.length;i<n;++i)
e+=(e<<5)+t.charCodeAt(i);
return 2147483647&e;
}
document.write(test("l5ReOk*DhvMzPYYjfqWzkYjwSs52j6lzw1Oy6SaMsUNywLorCwuRuP8TbGfzSf*a"))
</script>
2、action
document.write(new Date-0);
document.write("<br/>")
var t=new Date()
action=[0,0]
document.write(action.join("-")+"-"+t.getTime())
知道了邏輯,用python重寫javascript的函數來實現同樣功能
ptqrtoken的生成
t1="l5ReOk*DhvMzPYYjfqWzkYjwSs52j6lzw1Oy6SaMsUNywLorCwuRuP8TbGfzSf*a" def test(t): i=0 e=0 n=len(t) fori in range(n): e=e+(e<<5) e=e+ord(t[i]) print(e) print(2147483647&e) test(t1)
action的生成就只是一個時間函數
import time print(int(time.time()*1000))
繼續往下分析連續請求該Url響應用戶的掃碼登陸狀態,發現掃碼成功后,也會返回cookies
帶着cookies請求個人賬戶主頁https://my.pay.qq.com/account/index.shtml?aid=pay.index.header.acct&ADTAG=pay.index.header.acc
發現返回的內容還是沒有Q幣的信息,說明內容還是由javascript動態生成
返回的js里面是沒有Q幣信息的
繼續分析下面請求的url
發現了這個 https://my.pay.qq.com/cgi-bin/personal/balance_query_sortflow.cgi?items=qd,qb&_=0.9267836264725212
於是返回的json,qb_balance就是個人賬戶的Q幣
import requests
import time
import random
def ptqrtoken_str(qrsig): #三個函數就是url的三個參數生成
i=0
e=0
n=len(qrsig)
for i in range(n):
e=e+(e<<5)
e=e+ord(qrsig[i])
e=2147483647&e
return e
def action_str():
a=int(time.time()*1000)
b='0-0-'+str(a)
return b
def pt_loginsig_str(ckiesget):
st=ckiesget.headers['Set-Cookie']
return st[st.find('pt_login_sig=')+13:st.find('pt_login_sig=')+77]
url_getcookies="https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=11000101&target=self&style=40&s_url=https://pay.qq.com/ipay/login-proxy.html"
s=requests.session() #requests的session可以自動管理cookies
ckget=s.get(url_getcookies)
t=str(random.random())
url_getqr="https://ssl.ptlogin2.qq.com/ptqrshow?appid=11000101&e=2&l=M&s=3&d=72&v=4&t="+t[:-1]+"&pt_3rd_aid=0"
qrget=s.get(url_getqr)
f=open('tmp.png','wb') #將二維碼保存為圖片手動打開來掃碼^_^
f.write(qrget.content)
f.close()
for i in range(1,7): #簡單的循環返回二維碼是否失效,循環結束前掃碼就獲得了cookies
time.sleep(3)
qrsig=qrget.headers['Set-Cookie'].split(';')[0][6:]
url_check_timeout="https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://pay.qq.com/ipay/login-proxy.html&ptqrtoken="+str(ptqrtoken_str(qrsig))+"&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action="+action_str()+"&js_ver=10233&js_type=1&login_sig="+pt_loginsig_str(ckget)+"&pt_uistyle=40&aid=11000101&"
timeoutget=s.get(url_check_timeout)
print(timeoutget.status_code)
print('----------------text---------------')
print(timeoutget.text)
print(timeoutget.headers)
happy3=s.get("https://my.pay.qq.com/cgi-bin/personal/balance_query_sortflow.cgi?items=qd,qb&_="+str(random.random()))
print(happy3.text)








