前言mitmproxy 是具有 SSL/TLS 功能的交互式攔截偵聽代理,具有用于HTTP/1,HTTP/2和WebSockets的控制臺(tái)界面。 mitmweb 是用于 mitmproxy 的基于 Web 的界面, 提供一個(gè)可視化界面幫助我們查看抓取的請(qǐng)求,可以修改返回內(nèi)容。 mitmdump 它是mitmproxy的命令行接口,利用它我們可以對(duì)接Python腳本,用Python實(shí)現(xiàn)監(jiān)聽后的處理。
Addons 插件開發(fā)Mitmproxy 的插件機(jī)制是 mitmproxy 的一個(gè)非常強(qiáng)大的部分。事實(shí)上,mitmproxy自己的大部分功能都是在一套內(nèi)置插件中定義的,實(shí)現(xiàn)了從 anticaching 和sticky cookies 到我們的登錄Web應(yīng)用程序的所有功能。 插件通過響應(yīng)事件與 mitmproxy 進(jìn)行交互,這允許它們勾入并改變 mitmprox的行為。它們通過選項(xiàng)進(jìn)行配置,這些選項(xiàng)可以在mitmproxy的配置文件中設(shè)置,用戶可以交互更改,也可以通過命令行傳遞。最后,它們可以公開命令,這允許用戶直接或通過將它們綁定到交互工具中的鍵來調(diào)用它們的操作。 一個(gè)簡單的Addons 插件示例 """ Basic skeleton of a mitmproxy addon.
Run as follows: mitmproxy -s anatomy.py """ from mitmproxy import ctx
class Counter: def __init__(self): self.num = 0
def request(self, flow): self.num = self.num + 1 ctx.log.info("We've seen %d flows" % self.num)
addons = [Counter()]
上面是一個(gè)簡單的插件,它跟蹤我們看到的流(或者更具體地說HTTP請(qǐng)求)的數(shù)量。 每當(dāng)它看到一個(gè)新的流時(shí),它都會(huì)使用mitmproxy的內(nèi)部日志機(jī)制來宣布其計(jì)數(shù)。輸出可以在交互工具的事件日志中找到,也可以在mitmdump的控制臺(tái)上找到。 讓它旋轉(zhuǎn)一下,并通過將其加載到您選擇的mitmproxy工具中,確保它完成了它應(yīng)該做的事情。 我們將在示例中使用mitmdump 命令運(yùn)行插件 mitmdump -s ./anatomy.py
以下是關(guān)于上述代碼的一些注意事項(xiàng): Mitmproxy獲取插件全局列表的內(nèi)容,并將其找到的內(nèi)容加載到插件機(jī)制中。 插件只是對(duì)象——在本例中,我們的插件是Counter的一個(gè)實(shí)例。 request 方法是一個(gè)事件的示例。 插件只需為它們要處理的每個(gè)事件實(shí)現(xiàn)一個(gè)方法。 API文檔中記錄了每個(gè)事件及其簽名。 最后,ctx模塊是一個(gè) holdall 模塊,它公開了一組常用于插件的標(biāo)準(zhǔn)對(duì)象。 我們可以將一個(gè)ctx對(duì)象作為每個(gè)事件的第一個(gè)參數(shù)傳遞,但我們發(fā)現(xiàn)將它作為一個(gè)可導(dǎo)入的全局對(duì)象公開更方便。
在本例中,我們使用ctx.log對(duì)象進(jìn)行日志記錄。
有時(shí),我們希望編寫一個(gè)快速腳本,而不必經(jīng)歷創(chuàng)建類的麻煩。 插件機(jī)制有一個(gè)簡寫,允許將模塊作為一個(gè)整體處理為插件對(duì)象。 這使我們可以將事件處理程序函數(shù)放置在模塊范圍中。例如,這里有一個(gè)完整的腳本,它為每個(gè)請(qǐng)求添加一個(gè)頭: """An addon using the abbreviated scripting syntax."""
def request(flow): flow.request.headers["myheader"] = "value"
抓取瀏覽器上的請(qǐng)求簡單示例目標(biāo)是抓取瀏覽器上的訪問頁面的請(qǐng)求,比如訪問https://www.cnblogs.com/yoyoketang/ 我的博客地址,通過插件抓取請(qǐng)求 demo1.py 代碼如下: from mitmproxy import http # 作者:上海-悠悠 微信號(hào):283340479
def request(flow: http.HTTPFlow): # 對(duì)url 過濾,僅抓取我的博客地址 if "https://www.cnblogs.com/yoyoketang/" == flow.request.url: print('請(qǐng)求方法', flow.request.method) print('請(qǐng)求類型', flow.request.scheme) print('請(qǐng)求url', flow.request.url) print('域名', flow.request.host) print('請(qǐng)求路徑', flow.request.path) # 返回MultiDictView類型的數(shù)據(jù),URL的鍵值參數(shù) print('url的鍵值參數(shù)', flow.request.query) print('請(qǐng)求頭', flow.request.headers) print('cookies', flow.request.cookies)
啟動(dòng)服務(wù) >mitmdump -s ./demo1.py Loading script ./demo1.py Proxy server listening at http://*:8080
默認(rèn)監(jiān)聽端口8080 設(shè)置本機(jī)代理
瀏覽器上訪問我的博客,就可以看到抓取請(qǐng)求了
爬取數(shù)據(jù)爬取數(shù)據(jù)用到response 方法 目標(biāo):收集網(wǎng)站打開時(shí),加載的jpg圖片,如下打開網(wǎng)站后,加載出來的圖片
from mitmproxy import http # 作者:上海-悠悠 微信號(hào):283340479
def response(flow: http.HTTPFlow): print('===========下載==============') if "pic.netbian.com" == flow.request.host: if flow.request.url.endswith('jpg'): with open(flow.request.url[-18:].replace('/', ''), 'wb') as f: f.write(flow.response.get_content())
運(yùn)行后收集到網(wǎng)頁上加載的圖片 除了爬取圖片,也可以爬取頁面上的其它數(shù)據(jù)。 如果想自動(dòng)控制頁面操作,可以結(jié)合selenium等前端自動(dòng)化的工具。Mitmproxy 起到抓取網(wǎng)絡(luò)請(qǐng)求的request 和 response 對(duì)象。 2023年第 13期《python接口web自動(dòng)化+測(cè)試開發(fā)》課程,12月24號(hào)開學(xué)!
2022年第 2 期《Python 測(cè)試平臺(tái)開發(fā)》進(jìn)階課程(10月30號(hào)開學(xué))
|