步驟
1、分析qzone請(qǐng)求
2、分析參數(shù)來源
3、仿照數(shù)據(jù)請(qǐng)求
上次寫的一個(gè)qzone登陸寫的不詳細(xì)這次決定寫一個(gè)詳細(xì)分析qzone js 獲取好友列表
分析qzone請(qǐng)求
我們的好友列表要從 qzone 獲取,現(xiàn)在打開 qzone 的鏈接 https://h5.qzone.qq.com/mqzone/index 并且登陸
你可能會(huì)說你在逗我,這特么哪里來的好友列表
別急,好友列表肯定是有的不然你發(fā)表說說怎么@你的好友呢
說到@好友都明白了吧,我們的好友列表接口就從這里開始攔截接口請(qǐng)求。
先把打開我們發(fā)說說的那個(gè)框框,再把瀏覽器開啟調(diào)試模式,清空網(wǎng)絡(luò)請(qǐng)求攔截列表
現(xiàn)在你應(yīng)該在發(fā)說說的那個(gè)界面,點(diǎn)一下說說框下面的 @符號(hào)
盯住網(wǎng)絡(luò)請(qǐng)求那一塊,找一下那個(gè)像是獲取好友列表的,發(fā)現(xiàn)一共就6個(gè)請(qǐng)求,我一眼就看到了mfriend_list 接口意思很直白啊
好友列表已經(jīng)找到,接下來就是分析參數(shù)了,這個(gè)過程很痛苦
分析參數(shù)來源
首先點(diǎn)我剛剛說到的那一條請(qǐng)求記錄 就是這樣子的 我對(duì)自己的qq號(hào)打了碼畢竟這個(gè)東西獲取到可以直接用cookie登陸的
這里可能有人會(huì)說,為什么不直接點(diǎn)擊攔截列表上面有個(gè)可以定位js發(fā)出請(qǐng)求的位置,這樣找分析請(qǐng)求參數(shù)不是更簡(jiǎn)單嗎
這邊呢我只能說我之前也找過,但是找不到,因?yàn)辄c(diǎn)擊過去找到的是封裝類的位置
這邊參數(shù)呢不多 六個(gè) 需要分析的就兩個(gè)
qzonetoken c2176b5d6f0deff03d0dd0f59f26e51c2b408aa83419d416c737cc1b21d1e913c861ca780ad34ff4293ca5640b69
g_tk:1760587213
res_uin:***
res_type:normal
format:json
timestamp 時(shí)間戳
我們現(xiàn)在看一下這個(gè) qzonetoken 使用全局搜索找一下看是不是寫在靜態(tài)頁面中的
繼續(xù)搜索 window.shine0callback
發(fā)現(xiàn)都是一個(gè)結(jié)果。。。。 后面我試著搜索一下html 里面 發(fā)現(xiàn)竟然真的有
window.shine0callback = 自執(zhí)行函數(shù)
所以呢 qzonetoken 參數(shù)直接用 window.shine0callback 就好了
繼續(xù)全局搜索 g_tk
這邊呢有三個(gè)方法獲取token
1、userHelper.getPskeyToken()
2、userHelper.getToken()
3、user.getToken()
我們先在控制臺(tái)執(zhí)行一下這些方法
發(fā)現(xiàn) user 能執(zhí)行也和請(qǐng)求的參數(shù)對(duì)上了,不過我還是想找一下 userHelper 這個(gè)東西
先把a(bǔ)jax.js 這個(gè)類給弄到本地來 搜索 userHelper
既然寫在里面的那copy到控制臺(tái)就可以執(zhí)行了
開始我把 userHelper copy進(jìn)去發(fā)現(xiàn)少了一個(gè)getCookie,再把getCookie 也復(fù)制到控制臺(tái)就好了
這樣子執(zhí)行就能獲取到 token 了
res_uin qq號(hào)碼,我在搜索靜態(tài)html的時(shí)候無意間發(fā)現(xiàn)了可以從 FrontPage 對(duì)象中獲取,當(dāng)然也可以從 user 對(duì)象中獲取
res_type 固定normal
format 固定json
timestamp 時(shí)間戳拿一下系統(tǒng)時(shí)間戳就好
現(xiàn)在參數(shù)都分析完畢,qzone 的接口分析還是蠻簡(jiǎn)單的,不像某寶網(wǎng)站的程序
仿照數(shù)據(jù)請(qǐng)求
請(qǐng)到我上一篇文章拿 qzone登陸 的源碼 傳送到源碼
找到 paresHtml 函數(shù) 在這里先切換到默認(rèn)窗口
def paresHtml(self):
self.driver.switch_to.default_content()
獲取 qzonetoken 這邊直接執(zhí)行window.shine0callback 就能獲取
qzonetoken = self.driver.execute_script('return window.shine0callback')
獲取 g_tk 上面說到user里面可以直接獲取,那我們就偷個(gè)懶使用 user.getToken()
g_tk = self.driver.execute_script('return user.getToken()')
獲取 res_uin 直接從user 里面 getUin()
res_uin = self.driver.execute_script('return user.getUin()')
獲取時(shí)間戳 由于python 中的time.time()是秒,需要乘個(gè)1000
import time
timestamp = time.time() * 1000
拼接url
list = 'https://mobile.qzone.qq.com/friend/mfriend_list?' \
'qzonetoken=%s&g_tk=%s&res_uin=%s&res_type=normal&format=json×tamp=%d' % (
qzonetoken, g_tk, res_uin, timestamp)
本身我想偷懶的直接用 self.driver.get() 直接執(zhí)行的 后來想想還是算了,沒有一點(diǎn)技術(shù)含量的東西怎么好意思寫呢
最后決定使用js中的XMLHttpRequest 來模仿請(qǐng)求
self.driver.execute_script('window.xhr = new XMLHttpRequest;')
self.driver.execute_script('window.xhr.withCredentials=true;')
self.driver.execute_script(
'window.xhr.open(\'GET\',\'%s\',false)' % list)
self.driver.execute_script('window.xhr.onload = function (e){window.xhrsuccess = window.xhr.responseText}')
self.driver.execute_script('window.xhr.send()')
print(self.driver.execute_script('return window.xhrsuccess'))
請(qǐng)求完成后的結(jié)果是這個(gè)樣子的
下面是請(qǐng)求返回的結(jié)果
{
"code":0,
"subcode":0,
"message":"",
"default":0,
"data":{
"gpnames":[//分組列表
{
"gpid":0,//分組id
"gpname":"agp"http://分組名稱
}
],
"list":[//好友列表
{
"groupid":0,//分組id
"isvip":1,//是否是vip 1 是 vip
"nick":"消費(fèi)主張", //昵稱
"remark":"消費(fèi)主張",//備注
"searchField":"12315 消費(fèi)主張 消費(fèi)主張 xiaofeizhuzhang xfzz xiaofeizhuzhang xfzz",//關(guān)鍵字
"uin":12315,//qq號(hào)碼
"viplevel":1 //qq等級(jí)
}
],
"mayknow":{
"allnum":0,
"list":null,
"page":1
},
"speciallist":null
}
}
最后發(fā)一下模仿請(qǐng)求的源碼 結(jié)合我上一篇文章的源碼可以直接執(zhí)行出結(jié)果
import time
def paresHtml(self):
# 切換到默認(rèn)窗口
self.driver.switch_to.default_content()
# 請(qǐng)求狀態(tài)
shine0callback = self.driver.execute_script('return window.shine0callback')
# 一定要暫停一下不然 執(zhí)行user的時(shí)候拿不到,因?yàn)閼屑虞d
time.sleep(1)
g_tk = self.driver.execute_script('return window.user.getToken()')
uin = self.driver.execute_script('return window.user.getUin()')
timestamp = time.time() * 1000
list = 'https://mobile.qzone.qq.com/friend/mfriend_list?' \
'qzonetoken=%s&g_tk=%s&res_uin=%s&res_type=normal&format=json×tamp=%d' % (
shine0callback, g_tk, uin, timestamp)
# self.load_cookies()
# self.driver.get(list)
self.driver.execute_script('window.xhr = new XMLHttpRequest;')
self.driver.execute_script(
'window.xhr.open(\'GET\',\'%s\',false)' % list)
self.driver.execute_script('window.xhr.onload = function (e){window.xhrsuccess = window.xhr.responseText}')
self.driver.execute_script('window.xhr.send()')
print(self.driver.execute_script('return window.xhrsuccess'))
總結(jié)
1、qzone 里面的接口參數(shù)都差不多,總歸來講都能搜索出來
2、qzone 壓縮了js提高了分析的難度
3、好友列表模擬請(qǐng)求時(shí)記得把cookie帶過去否則t不認(rèn)
4、有時(shí)候登陸會(huì)登不上,拿到的好友列表數(shù)據(jù)是請(qǐng)先登錄,刪掉cookie重試即便就好