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

分享

爬蟲神器!用它可以實(shí)時(shí)處理和保存 Ajax 數(shù)據(jù)

 heii2 2020-06-23

做爬蟲的時(shí)候我們經(jīng)常會遇到這么一個(gè)問題:

網(wǎng)站的數(shù)據(jù)是通過 Ajax 加載的,但是 Ajax 的接口又是加密的,不費(fèi)點(diǎn)功夫破解不出來。這時(shí)候如果我們想繞過破解抓取數(shù)據(jù)的話,比如就得用 Selenium 了,Selenium 能完成一些模擬點(diǎn)擊、翻頁等操作,但又不好獲取 Ajax 的數(shù)據(jù)了,通過渲染后的 HTML 提取數(shù)據(jù)又非常麻煩。

或許你會心想:要是我能用 Selenium 來驅(qū)動頁面,同時(shí)又能把 Ajax 請求的數(shù)據(jù)保存下來就好了。

辦法自然是有,比如可以加層代理,用 mitmdump 來實(shí)時(shí)處理就好了。

但如果不用代理,沒有好的辦法呢?

這里我們介紹一個(gè)工具,叫做 AjaxHook,利用它我們可以把 Ajax 請求的數(shù)據(jù)都攔截下來,只要發(fā)生了一個(gè) Ajax 請求,它就能把請求和響應(yīng)截獲下來,這樣我們就能實(shí)現(xiàn) Ajax 數(shù)據(jù)的實(shí)時(shí)處理了。

Ajax Hook

Hook 大家估計(jì)不陌生了吧,這里我就不再展開講了,不太明白的可以自行搜索「Hook 技術(shù)」就能搜到一把資料。

那 Ajax Hook 顧名思義就是 Hook Ajax 請求了,Ajax 最重要的兩個(gè)部分?當(dāng)然就是 Request、Response 了,有了 Hook,我們就能在發(fā)起 Request 前和得到 Response 后對二者進(jìn)行處理了。

其基本作用點(diǎn)如圖所示:

那我們怎么來 Hook Ajax 請求呢?那自然就需要深入到 Ajax 的原生實(shí)現(xiàn)了。Ajax 其實(shí)就是利用 XMLHttpRequest 這個(gè)對象來實(shí)現(xiàn)的,要 Hook Ajax 的 Request 和 Response,那其實(shí)就是對它里面的一些屬性做一些處理,比如 send、onreadystatechange 等等。

聽起來似乎很麻煩的樣子,不用擔(dān)心,已經(jīng)有人把這個(gè)寫好了,我們直接拿來用就好了,GitHub 地址為:https://github.com/wendux/Ajax-hook。

其實(shí)這個(gè)內(nèi)部實(shí)現(xiàn)原理非常簡單,其實(shí)剛才就簡單提了一下,要想深入了解的話可以看下這篇文章:https://www.jianshu.com/p/7337ac624b8e。

OK,那這個(gè)怎么用呢?

Ajax-hook 的這個(gè)作者提供了兩個(gè)主要方法,一個(gè)是 proxy,一個(gè)是 hook,起作用都是來 Hook XMLHttpRequest 的。

這里借用一下官方介紹:

proxy 和 hook 方法都可以用于攔截全局XMLHttpRequest。它們的區(qū)別是:hook 的攔截粒度細(xì),可以具體到 XMLHttpRequest 對象的某一方法、屬性、回調(diào),但是使用起來比較麻煩,很多時(shí)候,不僅業(yè)務(wù)邏輯需要散落在各個(gè)回調(diào)當(dāng)中,而且還容易出錯(cuò)。而 proxy 抽象度高,并且構(gòu)建了請求上下文,請求信息 config 在各個(gè)回調(diào)中都可以直接獲取,使用起來更簡單、高效。

大多數(shù)情況下,我們建議使用 proxy 方法,除非 proxy 方法不能滿足你的需求。

那我們就來看看 proxy 方法的用法吧,其用法如下:

proxy({//請求發(fā)起前進(jìn)入 onRequest: (config, handler) => { console.log(config.url) handler.next(config);},//請求發(fā)生錯(cuò)誤時(shí)進(jìn)入,比如超時(shí);注意,不包括http狀態(tài)碼錯(cuò)誤,如404仍然會認(rèn)為請求成功 onError: (err, handler) => { console.log(err.type) handler.next(err)},//請求成功后進(jìn)入 onResponse: (response, handler) => { console.log(response.response) handler.next(response)}})

很清楚了,Ajax-hook 給我們提供了三個(gè)方法供復(fù)寫,onRequest、onResponse、onError 分別是在請求發(fā)起前的處理、請求成功后的處理、發(fā)生錯(cuò)誤時(shí)的處理。

那我們?nèi)绻鰯?shù)據(jù)爬取的話,其實(shí)就是為了截獲 Response 的結(jié)果,那其實(shí)實(shí)現(xiàn) onResponse 方法就好了。

再仔細(xì)看看,這個(gè) onResponse 方法接收兩個(gè)參數(shù),為 response 對象和 handler 對象,這都是 Ajax-hook 為我們封裝好的,其實(shí)這里我們只需要用 response 里面的內(nèi)容就好了,比如把 Response Body 打印出來,其實(shí)就是把 Ajax 得到的結(jié)果打印出來了。

行,那我們就來試試吧。

案例介紹

下面我們就拿一個(gè)我自己的案例來講吧,鏈接為:https://dynamic2./,界面如下:

這個(gè)網(wǎng)站是一個(gè)電影數(shù)據(jù)網(wǎng)站,其數(shù)據(jù)都是通過 Ajax 加載的,但是這些 Ajax 請求都帶著加密參數(shù) token,如圖所示:

其實(shí)這個(gè)參數(shù)你要解的話倒不是很難,不過也得費(fèi)點(diǎn)時(shí)間。

然后再看下 Ajax 的返回結(jié)果,如圖所示:

很純很清晰!所以我們?nèi)绻軌蛟诘玫?Ajax Response 的時(shí)候就把這些數(shù)據(jù)直接拿到,那就美滋滋了。

怎么辦?自然是用剛才所說的 Ajax-hook 了。

所以,我們這里就用上這個(gè) Ajax-hook 來對這些數(shù)據(jù)進(jìn)行實(shí)時(shí)處理吧。

實(shí)戰(zhàn)操作

首先,第一步那我們得能用上 Ajax-hook,怎么用呢?那肯定得需要引入一下這個(gè) Ajax-hook 庫,瀏覽器里的這個(gè)頁面又怎么引入呢?

答案有很多,比如復(fù)寫 JavaScript、Tampermonkey、Selenium 等等。

這里我們就用最簡單的方法,Selenium 自動執(zhí)行一下 Ajax-hook 的源代碼就好了。

那這時(shí)候我們就需要找到 Ajax-hook 的源碼了,去 GitHub 一找就有了,鏈接為:https://raw./wendux/Ajax-hook/master/dist/ajaxhook.min.js,如圖所示:

看,代碼量真不多吧。

我們把這個(gè)代碼復(fù)制,粘貼到 https://dynamic2./ 這個(gè)網(wǎng)站的控制臺里。

這時(shí)候我們會得到一個(gè) ah 對象,代表 Ajax-hook,我們就能用它里面的 proxy 方法了。

怎么用呢?就直接實(shí)現(xiàn) onResponse 方法,打印 Response 的結(jié)果就好了,實(shí)現(xiàn)如下:

ah.proxy({//請求成功后進(jìn)入  onResponse: (response, handler) => {if (response.config.url.startsWith('/api/movie')) {      console.log(response.response)      handler.next(response)}}})

把這段代碼也放在控制臺運(yùn)行下,這時(shí)候我們就實(shí)現(xiàn)了 Ajax Response 的 Hook 了,只要有 Ajax 請求,Response 的結(jié)果就會被輸出出來。

這時(shí)候如果我們點(diǎn)擊翻頁,觸發(fā)一個(gè)新的 Ajax 請求,就可以看到控制臺輸出了 Response 的結(jié)果,如圖所示:


嗯,這下我們就能獲取到 Ajax 的數(shù)據(jù)了。

數(shù)據(jù)轉(zhuǎn)發(fā)

那現(xiàn)在數(shù)據(jù)在瀏覽器里面啊,我們怎么存下來呢?

存還不簡單,最簡單的,把這個(gè)數(shù)據(jù)轉(zhuǎn)發(fā)給自己的一個(gè)接口保存下來就好了。

那我們就用 Flask 簡單弄一個(gè)接口吧,記得解除跨域限制,實(shí)現(xiàn)如下:

import jsonfrom flask import Flask, request, jsonifyfrom flask_cors import CORS
app = Flask(__name__)CORS(app)

@app.route('/receiver/movie', methods=['POST'])def receive(): content = json.loads(request.data)print(content)# to somethingreturn jsonify({'status': True})

if __name__ == '__main__': app.run(host='0.0.0.0', port=80, debug=True)

這里我就簡單寫了個(gè)示例,寫了一個(gè)能接收 POST 請求的 API,地址為 /receiver/movie,然后把 POST 的數(shù)據(jù)打印出來再返回一個(gè)響應(yīng)。

當(dāng)然這里你可以做很多操作了,比如把數(shù)據(jù)切割,存儲到數(shù)據(jù)庫等都是可以的。

好的,那現(xiàn)在服務(wù)器有了,我們就在 Ajax-hook 這邊把數(shù)據(jù)發(fā)過來吧。

這里我們借助于 axios 這個(gè)庫,其庫地址為 https:///axios@0.19.2/dist/axios.min.js,也是放在瀏覽器執(zhí)行就能用。

引入 axios 之后,我們把之前的 proxy 方法修改為如下內(nèi)容:

ah.proxy({//請求成功后進(jìn)入  onResponse: (response, handler) => {if (response.config.url.startsWith('/api/movie')) {      axios.post('http://localhost/receiver/movie', {        url: window.location.href,        data: response.response})      console.log(response.response)      handler.next(response)}}})

其實(shí)這里就是調(diào)用了 axios 的 post 方法,然后把當(dāng)前 url 和 Response 的數(shù)據(jù)發(fā)給了 Server。

到現(xiàn)在為止,每次 Ajax 請求的 Response 結(jié)果都會被發(fā)給這個(gè) Flask Server,F(xiàn)lask Server 對其進(jìn)行存儲和處理就好了。

自動化

OK,那現(xiàn)在我們已經(jīng)可以實(shí)現(xiàn) Ajax 攔截和數(shù)據(jù)轉(zhuǎn)發(fā)了,最后一步自然就是把爬取自動化了。

自動化就分為三部分:

·打開網(wǎng)站?!ぷ⑷?Ajax-hook、axios、proxy 的代碼。·自動點(diǎn)擊下一頁翻頁。

最關(guān)鍵的就是第二步了,我們把剛才 Ajax-hook、axios、proxy 的代碼都放在一個(gè) hook.js 文件里面,用 Selenium 的 execute_script 來執(zhí)行就好了。

其他的幾步很簡單,最后實(shí)現(xiàn)如下:

from selenium import webdriverimport time
browser = webdriver.Chrome()browser.get('https://dynamic2./')browser.execute_script(open('hook.js').read())time.sleep(2)
for index in range(10):print('current page', index) btn_next = browser.find_element_by_css_selector('.btn-next') btn_next.click() time.sleep(2)

最后,運(yùn)行一下。

可以發(fā)現(xiàn)瀏覽器先打開了頁面,然后模擬點(diǎn)擊了下一頁,再回過頭來觀察下 Flask Server 這邊,可以看到 Ajax 的數(shù)據(jù)就接收到了,如圖所示:

OK,到此為止。

總結(jié)

至此,我們就完成了:

·Ajax Response Hook·數(shù)據(jù)轉(zhuǎn)發(fā)與接收·瀏覽器自動化

以后我們再遇到類似的情形,也可以用同樣的思路來處理了。

本節(jié)代碼:https://github.com/Python3WebSpider/AjaxHookSpider。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多