小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

JavaScript 逆向爬取實(shí)戰(zhàn)

 liqualife 2020-05-04

閱讀本文大概需要 25 分鐘。

在上一節(jié)總結(jié)一些網(wǎng)站加密和混淆技術(shù)中,我們介紹了網(wǎng)頁(yè)防護(hù)技術(shù),包括接口加密和 JavaScript 壓縮、加密和混淆。這就引出了一個(gè)問(wèn)題,如果我們碰到了這樣的網(wǎng)站,那該怎么去分析和爬取呢?

本節(jié)我們就通過(guò)一個(gè)案例來(lái)介紹一下這種網(wǎng)站的分析思路,本節(jié)介紹的這個(gè)案例網(wǎng)站不僅在 API 接口層有加密,而且前端 JavaScript 也帶有壓縮和混淆,其前端壓縮打包工具是使用了現(xiàn)在流行的 Webpack,混淆工具是使用了 javascript-obfuscator,這二者結(jié)合結(jié)合起來(lái),前端的代碼會(huì)變得難以閱讀和分析。

如果我們不使用 Selenium 或 Pyppeteer 等工具來(lái)模擬瀏覽器的形式爬取的話(huà),要想直接從接口層面上獲取數(shù)據(jù),基本上我們就要一點(diǎn)點(diǎn)調(diào)試分析 JavaScript 的調(diào)用邏輯、堆棧調(diào)用關(guān)系來(lái)整個(gè)弄清楚網(wǎng)站加密的實(shí)現(xiàn)方法了,我們可以稱(chēng)之為這個(gè)過(guò)程叫 JavaScript 逆向。這些接口的加密參數(shù)往往都是一些加密算法或編碼的組合,完全搞明白其中的邏輯之后,我們就能把這個(gè)算法用 Python 模擬出來(lái),從而實(shí)現(xiàn)接口的請(qǐng)求了。

案例介紹

案例的地址為:https://dynamic6.scrape./,頁(yè)面如圖所示。

初看之下并沒(méi)有什么特殊的,但仔細(xì)觀察可以發(fā)現(xiàn)其 Ajax 請(qǐng)求接口和每部電影的 URL 都包含了加密參數(shù)。

比如我們點(diǎn)擊任意一部電影,觀察一下 URL 的變化,如圖所示。

這里我們可以看到詳情頁(yè)的 URL 和包含了一個(gè)長(zhǎng)字符串,看似是一個(gè) Base64 編碼的內(nèi)容。

那么接下來(lái)直接看看 Ajax 的請(qǐng)求,我們從列表頁(yè)的第 1 頁(yè)到第 10 頁(yè)依次點(diǎn)一下,觀察一下 Ajax 請(qǐng)求是怎樣的,如圖所示。

可以看到 Ajax 接口的 URL 里面多了一個(gè) token,而且不同的頁(yè)碼這個(gè) token 還是不一樣的,這個(gè) token 同樣看似是一個(gè) Base64 編碼的字符串。

另外更困難的是,這個(gè)接口還是有時(shí)效性的,如果我們把 Ajax 接口 URL 直接復(fù)制下來(lái),短期內(nèi)是可以訪問(wèn)的,但是過(guò)段時(shí)間之后就無(wú)法訪問(wèn)了,會(huì)直接返回 401 狀態(tài)碼。

接下來(lái)我們?cè)倏聪铝斜眄?yè)的返回結(jié)果,比如我們打開(kāi)第一個(gè)請(qǐng)求,看看第一部電影數(shù)據(jù)的返回結(jié)果,如圖所示。

這里我們把看似是第一部電影的返回結(jié)果全展開(kāi)了,但是剛才我們觀察到第一步電影的 URL 的鏈接卻為 https://dynamic6.scrape./detail/ZWYzNCN0ZXVxMGJ0dWEjKC01N3cxcTVvNS0takA5OHh5Z2ltbHlmeHMqLSFpLTAtbWIx,看起來(lái)是 Base64 編碼,我們解碼一下,結(jié)果為 ef34#teuq0btua#(-57w1q5o5--j@98xygimlyfxs*-!i-0-mb1,但是看起來(lái)似乎還是毫無(wú)規(guī)律,這個(gè)解碼后的結(jié)果又是怎么來(lái)的呢?返回結(jié)果里面也并不包含這個(gè)字符串,那這又是怎么構(gòu)造的呢?

再然后,這僅僅是某一個(gè)詳情頁(yè)頁(yè)面的 URL,其真實(shí)數(shù)據(jù)是通過(guò) Ajax 加載的,那么 Ajax 請(qǐng)求又是怎樣的呢,我們?cè)儆^察下,如圖所示。

好,這里我們發(fā)現(xiàn)其 Ajax 接口除了包含剛才所說(shuō)的 URL 中攜帶的字符串,又多了一個(gè) token,同樣也是類(lèi)似 Base64 編碼的內(nèi)容。

那么總結(jié)下來(lái)這個(gè)網(wǎng)站就有如下特點(diǎn):

·列表頁(yè)的 Ajax 接口參數(shù)帶有加密的 token·詳情頁(yè)的 URL 帶有加密 id·詳情頁(yè)的 Ajax 接口參數(shù)帶有加密 id 和加密 token

那如果我們要想通過(guò)接口的形式來(lái)爬取,必須要把這些加密 id 和 token 構(gòu)造出來(lái)才行,而且必須要一步步來(lái),首先我們要構(gòu)造出列表頁(yè) Ajax 接口的 token 參數(shù),然后才能獲取每部電影的數(shù)據(jù)信息,然后根據(jù)數(shù)據(jù)信息構(gòu)造出加密 id 和 token。

OK,那到現(xiàn)在為止我們就知道了這個(gè)網(wǎng)站接口的加密情況了,我們下一步就是去找這個(gè)加密實(shí)現(xiàn)邏輯了。

由于是網(wǎng)頁(yè),所以其加密邏輯一定藏在前端代碼里面,但上節(jié)課我們也說(shuō)了,前端為了保護(hù)其接口加密邏輯不被輕易分析出來(lái),會(huì)采取壓縮、混淆的一些方式來(lái)加大分析的難度。

好,那么我們 就來(lái)看看這個(gè)網(wǎng)站的源代碼和 JavaScript 文件是怎樣的吧。

首先看看網(wǎng)站源代碼,我們?cè)诰W(wǎng)站上點(diǎn)擊右鍵,彈出選項(xiàng)菜單,然后點(diǎn)擊「查看源代碼」,可以看到結(jié)果如圖所示。

內(nèi)容如下:

<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content='IE=edge'><meta name=viewport content='width=device-width,initial-scale=1'><link rel=icon href=/favicon.ico><title>Scrape | Movie</title><link href=/css/chunk-19c920f8.2a6496e0.css rel=prefetch><link href=/css/chunk-2f73b8f3.5b462e16.css rel=prefetch><link href=/js/chunk-19c920f8.c3a1129d.js rel=prefetch><link href=/js/chunk-2f73b8f3.8f2fc3cd.js rel=prefetch><link href=/js/chunk-4dec7ef0.e4c2b130.js rel=prefetch><link href=/css/app.ea9d802a.css rel=preload as=style><link href=/js/app.5ef0d454.js rel=preload as=script><link href=/js/chunk-vendors.77daf991.js rel=preload as=script><link href=/css/app.ea9d802a.css rel=stylesheet></head><body><noscript><strong>We're sorry but portal doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/js/chunk-vendors.77daf991.js></script><script src=/js/app.5ef0d454.js></script></body></html>

這是一個(gè)典型的 SPA (單頁(yè) Web 應(yīng)用)的頁(yè)面, 其 JavaScript 文件名帶有編碼字符、chunk、vendors 等關(guān)鍵字,整個(gè)這就是經(jīng)過(guò) Webpack 打包壓縮后的源代碼,目前主流的前端開(kāi)發(fā),如 Vue.js、React.js 的輸出結(jié)果都是類(lèi)似這樣的結(jié)果。

好,那么我們?cè)倏聪缕?JavaScript 代碼是什么樣子的,我們?cè)陂_(kāi)發(fā)者工具中打開(kāi) Sources 選項(xiàng)卡下的 Page 選項(xiàng)卡,然后打開(kāi) js 文件夾,這里我們就能看到 JavaScript 的源代碼,如圖所示。

我們隨便復(fù)制一些出來(lái),看看是什么樣子的,結(jié)果如下:

(window['webpackJsonp']=window['webpackJsonp']||[])['push']([['chunk-19c920f8'],{'5a19':function(_0x3cb7c3,_0x5cb6ab,_0x5f5010){},'c6bf':function(_0x1846fe,_0x459c04,_0x1ff8e3){},'ca9c':function(_0x195201,_0xc41ead,_0x1b389c){'use strict';var _0x468b4e=_0x1b389c('5a19'),_0x232454=_0x1b389c['n'](_0x468b4e);_0x232454['a'];},'d504':...,[_0xd670a1['_v'](_0xd670a1['_s'](_0x2227b6)+'\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20')]);}),0x1),_0x4ef533('div',{'staticClass':'m-v-sm\x20info'},[_0x4ef533('span',[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['regions']['join']('、')))]),_0x4ef533('span',[_0xd670a1['_v']('\x20/\x20')]),_0x4ef533('span',[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['minute'])+'\x20分鐘')])]),_0x4ef533('div',...,_0x4ef533('el-col',{'attrs':{'xs':0x5,'sm':0x5,'md':0x4}},[_0x4ef533('p',{'staticClass':'score\x20m-t-md\x20m-b-n-sm'},[_0xd670a1['_v'](_0xd670a1['_s'](_0x1cc7eb['score']['toFixed'](0x1)))]),_0x4ef533('p',[_0x4ef533('el-rate',{'attrs':{'value':_0x1cc7eb['score']/0x2,'disabled':'','max':0x5,'text-color':'#ff9900'}})],0x1)])],0x1)],0x1);}),0x1)],0x1),_0x4ef533('el-row',[_0x4ef533('el-col',{'attrs':{'span':0xa,'offset':0xb}},[_0x4ef533('div',{'staticClass':'pagination\x20m-v-lg'},[_0x4ef533('el-pagination',...:function(_0x347c29){_0xd670a1['page']=_0x347c29;},'update:current-page':function(_0x79754e){_0xd670a1['page']=_0x79754e;}}})],0x1)])],0x1)],0x1);},_0x357ebc=[],_0x18b11a=_0x1a3e60('7d92'),_0x4369=_0x1a3e60('3e22'),...;var _0x498df8=...['then'](function(_0x59d600){var _0x1249bc=_0x59d600['data'],_0x10e324=_0x1249bc['results'],_0x47d41b=_0x1249bc['count'];_0x531b38['loading']=!0x1,_0x531b38['movies']=_0x10e324,_0x531b38['total']=_0x47d41b;});}}},_0x28192a=_0x5f39bd,_0x5f5978=(_0x1a3e60('ca9c'),_0x1a3e60('eb45'),_0x1a3e60('2877')),_0x3fae81=Object(_0x5f5978['a'])(_0x28192a,_0x443d6e,_0x357ebc,!0x1,null,'724ecf3b',null);_0x6f764c['default']=_0x3fae81['exports'];},'eb45':function(_0x1d3c3c,_0x52e11c,_0x3f1276){'use strict';var _0x79046c=_0x3f1276('c6bf'),_0x219366=_0x3f1276['n'](_0x79046c);_0x219366['a'];}}]);

嗯,就是這種感覺(jué),可以看到一些變量都是一些十六進(jìn)制字符串,而且代碼全被壓縮了。

沒(méi)錯(cuò),我們就是要從這里面找出 token 和 id 的構(gòu)造邏輯,看起來(lái)是不是很崩潰?

要完全分析出整個(gè)網(wǎng)站的加密邏輯還是有一定的難度的,不過(guò)不用擔(dān)心,我們本節(jié)會(huì)一步步地講解逆向的思路、方法和技巧,如果你能跟著這個(gè)過(guò)程走完,相信還是能學(xué)會(huì)一定的 JavaScript 逆向技巧的。

為了適當(dāng)降低難度,本節(jié)的案例的 JavaScript 混淆其實(shí)并沒(méi)有設(shè)置特別復(fù)雜,并沒(méi)有開(kāi)啟字符串編碼、控制流扁平化等混淆方式。

列表頁(yè) Ajax 入口尋找

好,那么接下來(lái)我們就開(kāi)始第一步入口的尋找吧,這里就簡(jiǎn)單介紹兩種尋找入口的方式:

·全局搜索標(biāo)志字符串·設(shè)置 Ajax 斷點(diǎn)

全局搜索標(biāo)志字符串

一些關(guān)鍵的字符串通常會(huì)作為找尋 JavaScript 混淆入口的依據(jù),我們可以通過(guò)全局搜索的方式來(lái)查找,然后根據(jù)搜索到的結(jié)果大體觀察是否是我們想找的入口。

好,我們重新打開(kāi)列表頁(yè)的 Ajax 接口,看下請(qǐng)求的 Ajax 接口,如圖所示。

這里的 Ajax 接口的 URL 為 https://dynamic6.scrape./api/movie/?limit=10&offset=0&token=NTRhYWJhNzAyYTZiMTc0ZThkZTExNzBiNTMyMDJkN2UxZWYyMmNiZCwxNTg4MTc4NTYz,可以看到帶有 offset、limit、token 三個(gè)參數(shù),那關(guān)鍵就是找 token,我們就全局搜索下 token 是不是存在吧,我們可以點(diǎn)擊開(kāi)發(fā)者工具右上角的下拉選項(xiàng)卡,然后點(diǎn)擊 Search,如圖所示。

這樣我們就能進(jìn)入到一個(gè)全局搜索模式,我們搜索 token,可以看到的確搜索到了幾個(gè)結(jié)果,如圖所示。
觀察一下,下面的兩個(gè)結(jié)果可能是我們想要的,我們點(diǎn)擊進(jìn)入第一個(gè)看下,定位到了一個(gè) JavaScript 文件,如圖所示。

這時(shí)候可以看到整個(gè)代碼都是壓縮過(guò)后的,只有一行,不好看,我們可以點(diǎn)擊左下角的 {} 按鈕,美化一下 JavaScript 代碼,如圖所示。

美化后的結(jié)果就是這樣子了,如圖所示。

這時(shí)候可以看到這里彈出來(lái)了一個(gè)新的選項(xiàng)卡,其名稱(chēng)是 JavaScript 文件名加上了 :formatted,代表格式化后代碼結(jié)果,在這里我們?cè)俅味ㄎ坏?token 觀察一下。

那可以看到這里有 limit、offset、token 然后觀察下其他的邏輯,基本上能夠確定這就是構(gòu)造 Ajax 請(qǐng)求的地方了,如果不是的話(huà)可以繼續(xù)搜索其他的文件觀察下。

那現(xiàn)在,混淆的入口點(diǎn)我們就成功找到了,這是一個(gè)首選的找入口的方法。

XHR 斷點(diǎn)

由于這里 token 這個(gè)字符串并沒(méi)有被混淆,所以上面的這個(gè)方法是奏效的。之前我們也講過(guò),這種字符串由于非常容易成為找尋入口點(diǎn)的依據(jù),所以這樣的字符串也會(huì)被混淆成類(lèi)似 Unicode、Base64、RC4 的一些編碼形式,這樣我們就沒(méi)法輕松搜索到了。

那如果遇到這種情況,我們可以怎么辦呢?這里再介紹一種通過(guò)打 XHR 斷點(diǎn)的方式來(lái)尋找入口。

XHR 斷點(diǎn),顧名思義,就是在發(fā)起 XHR 的時(shí)候進(jìn)入斷點(diǎn)調(diào)試模式,JavaScript 會(huì)在發(fā)起 Ajax 請(qǐng)求的時(shí)候挺住,這時(shí)候我們可以通過(guò)當(dāng)前的調(diào)用棧的邏輯順著找到入口。

怎么設(shè)置呢?我們可以在 Sources 選項(xiàng)卡的右側(cè),XHR/fetch Breakpoints 處添加一個(gè)斷點(diǎn)選項(xiàng)。首先點(diǎn)擊 + 號(hào),然后這里就會(huì)讓我們輸入匹配的 URL 內(nèi)容,由于 Ajax 接口的形式是 /api/movie/?limit=10... 這樣的格式,所這里我們就截取一段填進(jìn)去就好了,這里填的就是 /api/movie,如圖所示。

添加完畢之后重新刷新下頁(yè)面,可以發(fā)現(xiàn)就進(jìn)入了斷點(diǎn)模式,如圖所示。

好,接下來(lái)我們重新點(diǎn)下 {} 格式化一下代碼,看看斷點(diǎn)是在哪里,如圖所示。

那這里看到有個(gè) send 的字符,我們可以初步猜測(cè)這就是相當(dāng)于發(fā)送 Ajax 請(qǐng)求的一瞬間。

那到了這里感覺(jué) Ajax 都馬上要發(fā)出去了,是不是有點(diǎn)太晚了,我們想找的是構(gòu)造 Ajax 的那個(gè)時(shí)候來(lái)分析 Ajax 參數(shù)啊?不用擔(dān)心,這里我們通過(guò)調(diào)用棧就可以找回去。我們點(diǎn)擊右側(cè)的 Call Stack,這里記錄了 JavaScript 的方法逐層調(diào)用過(guò)程,如圖所示。

這里當(dāng)前指向的是一個(gè)名字為 anonymouns,也就是匿名的調(diào)用,在它的下方就顯示了調(diào)用這個(gè) anonymouns 的方法,名字叫做 _0x594ca1,然后再下一層就又顯示了調(diào)用 _0x594a1 這個(gè)方法的方法,依次類(lèi)推。

這里我們可以逐個(gè)往下找下去,然后通過(guò)一些觀察看看有沒(méi)有 token 這樣的信息,就能找到對(duì)應(yīng)的位置了,最后我們就可以找到 onFetchData 這個(gè)方法里面實(shí)現(xiàn)了這個(gè) token 的構(gòu)造邏輯,這樣我們也成功找到 token 的參數(shù)構(gòu)造的位置了,如圖所示。

好,那到現(xiàn)在為止我們就通過(guò)兩個(gè)方法找到入口點(diǎn)了。

其實(shí)還有其他的尋找入口的方式,比如 Hook 關(guān)鍵函數(shù)的方式,稍后后文我們會(huì)講到,這里就暫時(shí)不講了。

列表頁(yè)加密邏輯尋找

好,那么接下來(lái)我們已經(jīng)找到 token 的位置了,可以觀察一下這個(gè) token 對(duì)應(yīng)的變量叫做 _0xa70fc9,所以我們的關(guān)鍵就是要找這個(gè)變量是哪里來(lái)的了。

怎么找呢?我們打個(gè)斷點(diǎn)就好了。

看下這個(gè)變量是在哪里生成的,我們?cè)趯?duì)應(yīng)的行打一個(gè)斷點(diǎn),如果打了剛才的 XHR 斷點(diǎn)的話(huà)可以先取消掉,如圖所示。

這時(shí)候我們就設(shè)置了一個(gè)新的斷點(diǎn)了。由于只有一個(gè)斷點(diǎn),可以重新刷新下網(wǎng)頁(yè),這時(shí)候我們會(huì)發(fā)現(xiàn)網(wǎng)頁(yè)停在了新的斷點(diǎn)上面。

那這里我們就可以觀察下運(yùn)行的一些變量了,比如我們把鼠標(biāo)放在各個(gè)變量上面去,可以看到變量的一些值和類(lèi)型,比如我們看 _0x18b11a 這個(gè)變量,會(huì)有一個(gè)浮窗顯示,如圖所示。

另外我們還可以通過(guò)在右側(cè)的 Watch 面板添加想要查看的變量名稱(chēng),如這行代碼的內(nèi)容為:

, _0xa70fc9 = Object(_0x18b11a['a'])(this['$store']['state']['url']['index']);

我們比較感興趣的可能就是 _0x18b11a 還有 this 里面額這個(gè)值了,我們可以展開(kāi) Watch 面板,然后點(diǎn)擊 + 號(hào),把想看的變量添加到 Watch 面板里面,如圖所示。

觀察下可以發(fā)現(xiàn) _0x18bba 這是一個(gè) Object,它有個(gè) a 屬性,其值是一個(gè) function,然后 this['$store']['state']['url']['index'] 的值其實(shí)就是 /api/movie,就是 Ajax 請(qǐng)求 URL 的 Path。_0xa70fc9 就是調(diào)用了前者這個(gè) function 然后傳入了 /api/movie 得到的。

那么下面一步就是去尋找這個(gè) function 在哪里了,我們可以把 Watch 面板的 _0x18bba 展開(kāi),這里會(huì)顯示一個(gè) FunctionLocation,就是這個(gè) function 的代碼位置,如圖所示。

點(diǎn)擊進(jìn)入之后發(fā)現(xiàn)其仍然是未格式化的代碼,再次點(diǎn)擊 {} 格式化一下代碼。

這時(shí)候我們就進(jìn)入到了一個(gè)新的名字為 _0xc9e475 這個(gè)方法里面,這個(gè)方法里面應(yīng)該就是 token 的生成邏輯了,我們?cè)俅蛏蠑帱c(diǎn),然后執(zhí)行面板右上角藍(lán)色箭頭狀的 Resume 按鈕,如圖所示。

這時(shí)候就發(fā)現(xiàn)我們就單步執(zhí)行到這個(gè)位置了。

接下來(lái)我們不斷進(jìn)行單步調(diào)試,觀察一下這里面的執(zhí)行邏輯和每一步調(diào)試過(guò)程中結(jié)果都有什么變化,如圖所示。

在每步的執(zhí)行過(guò)程中,我們可以發(fā)現(xiàn)一些運(yùn)行值會(huì)被打到代碼的右側(cè)并帶有高亮表示,同時(shí)在 watch 面板還能看到每步的變量具體結(jié)果。

最后我們總結(jié)出這個(gè) token 的構(gòu)造邏輯如下:

·傳入的 /api/movie 會(huì)構(gòu)造一個(gè)初始化列表,變量命名為 _0x3dde76。·獲取當(dāng)前的時(shí)間戳,命名為 _0x4c50b4,push 到 _0x3dde76 這個(gè)變量里面。·將 _0x3dde76 變量用 , 拼接,然后進(jìn)行 SHA1 編碼,命名為 _0x46ba68。·將 _0x46ba68 (SHA1 編碼的結(jié)果)和 _0x4c50b4 (時(shí)間戳)用逗號(hào)拼接,命名為 _0x495a44·將 _0x495a44 進(jìn)行 Base64 編碼,命名為 _0x2a93f2,得到最后的 token。

以上的一些邏輯經(jīng)過(guò)反復(fù)的觀察就可以比較輕松地總結(jié)出來(lái)了,其中有些變量可以實(shí)時(shí)查看,同時(shí)也可以自己輸入到控制臺(tái)上進(jìn)行反復(fù)驗(yàn)證,相信總結(jié)出這個(gè)結(jié)果并不難。

好,那現(xiàn)在加密邏輯我們就分析出來(lái)啦,基本的思路就是:

·先將 /api/movie 放到一個(gè)列表里面·列表中加入當(dāng)前時(shí)間戳·將列表內(nèi)容用逗號(hào)拼接·將拼接的結(jié)果進(jìn)行 SHA1 編碼·將編碼的結(jié)果和時(shí)間戳再次拼接·將拼接后的結(jié)果進(jìn)行 Base64 編碼

驗(yàn)證下邏輯沒(méi)問(wèn)題的話(huà),我們就可以用 Python 來(lái)實(shí)現(xiàn)出來(lái)啦。

Python 實(shí)現(xiàn)列表頁(yè)的爬取

要 Python 實(shí)現(xiàn)這個(gè)邏輯,我們需要借助于兩個(gè)庫(kù),一個(gè)是 hashlib,它提供了 sha1 方法;另外一個(gè)是 base64 庫(kù),它提供了 b64encode 方法對(duì)結(jié)果進(jìn)行 Base64 編碼。

代碼實(shí)現(xiàn)如下:

import hashlibimport timeimport base64from typing import List, Anyimport requests
INDEX_URL = 'https://dynamic6.scrape./api/movie?limit={limit}&offset={offset}&token={token}'LIMIT = 10OFFSET = 0
def get_token(args: List[Any]): timestamp = str(int(time.time())) args.append(timestamp) sign = hashlib.sha1(','.join(args).encode('utf-8')).hexdigest() return base64.b64encode(','.join([sign, timestamp]).encode('utf-8')).decode('utf-8')
args = ['/api/movie']token = get_token(args=args)index_url = INDEX_URL.format(limit=LIMIT, offset=OFFSET, token=token)response = requests.get(index_url)print('response', response.json())

這里我們就根據(jù)上面的邏輯把加密流程實(shí)現(xiàn)出來(lái)了,這里我們先模擬爬取了第一頁(yè)的內(nèi)容,最后運(yùn)行一下就可以得到最終的輸出結(jié)果了。

另外,還有一些

·Hook 原理·Hook 注入·Overrides 功能·Tampermonkey 插件·Python 模擬實(shí)現(xiàn)

的內(nèi)容,我放在了下一節(jié),下一節(jié)會(huì)于 5.3 號(hào)發(fā)出,我們不見(jiàn)不散~



崔慶才

靜覓博客博主,《Python3網(wǎng)絡(luò)爬蟲(chóng)開(kāi)發(fā)實(shí)戰(zhàn)》作者

隱形字

個(gè)人公眾號(hào):進(jìn)擊的Coder

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多