mitmproxy是一個支援HTTP和HTTPS的抓包程式,有類似Fiddler、Charles的功能,只不過它是一個控制檯的形式操作。
mitmproxy還有兩個關聯元件。一個是mitmdump,它是mitmproxy的命令列介面,利用它我們可以對接Python指令碼,用Python實現監聽後的處理。另一個是mitmweb,它是一個Web程式,通過它我們可以清楚觀察mitmproxy捕獲的請求。
下面我們來了解它們的用法。
一、準備工作
請確保已經正確安裝好了mitmproxy,並且手機和PC處於同一個區域網下,同時配置好了mitmproxy的CA證照。
二、mitmproxy的功能
mitmproxy有如下幾項功能。
攔截HTTP和HTTPS請求和響應。
儲存HTTP會話並進行分析。
模擬客戶端發起請求,模擬服務端返回響應。
利用反向代理將流量轉發給指定的伺服器。
支援Mac和Linux上的透明代理。
利用Python對HTTP請求和響應進行實時處理。
三、抓包原理
和Charles一樣,mitmproxy執行於自己的PC上,mitmproxy會在PC的8080埠執行,然後開啟一個代理服務,這個服務實際上是一個HTTP/HTTPS的代理。
手機和PC在同一個區域網內,設定代理為mitmproxy的代理地址,這樣手機在訪問網際網路的時候流量資料包就會流經mitmproxy,mitmproxy再去轉發這些資料包到真實的伺服器,伺服器返回資料包時再由mitmproxy轉發回手機,這樣mitmproxy就相當於起了中間人的作用,抓取到所有Request和Response,另外這個過程還可以對接mitmdump,抓取到的Request和Response的具體內容都可以直接用Python來處理,比如得到Response之後我們可以直接進行解析,然後存入資料庫,這樣就完成了資料的解析和儲存過程。
四、設定代理
首先,我們需要執行mitmproxy,命令如下所示:
啟動mitmproxy的命令如下:
mitmproxy複製程式碼
之後會在8080埠上執行一個代理服務,如下圖所示。
右下角會出現當前正在監聽的埠。
或者啟動mitmdump,它也會監聽8080埠,命令如下所示:
mitmdump複製程式碼
執行結果如下圖所示。
將手機和PC連線在同一區域網下,設定代理為當前代理。首先看看PC的當前區域網IP。
Windows上的命令如下所示:
ipconfig複製程式碼
Linux和Mac上的命令如下所示:
ifconfig複製程式碼
輸出結果如下圖所示。
一般類似10.*.*.*或172.16.*.*或192.168.1.*這樣的IP就是當前PC的區域網IP,例如此圖中PC的IP為192.168.1.28,手機代理設定類似如下圖所示。
這樣我們就配置好了mitmproxy的的代理。
五、mitmproxy的使用
確保mitmproxy正常執行,並且手機和PC處於同一個區域網內,設定了mitmproxy的代理,具體的配置方法可以參考官方文件。
執行mitmproxy,命令如下所示:
mitmproxy複製程式碼
設定成功之後,我們只需要在手機瀏覽器上訪問任意的網頁或瀏覽任意的App即可。例如在手機上開啟百度,mitmproxy頁面便會呈現出手機上的所有請求,如下圖所示。
這就相當於之前我們在瀏覽器開發者工具監聽到的瀏覽器請求,在這裡我們藉助於mitmproxy完成。Charles完全也可以做到。
這裡是剛才手機開啟百度頁面時的所有請求列表,左下角顯示的2/38代表一共發生了38個請求,當前箭頭所指的是第二個請求。
每個請求開頭都有一個GET或POST,這是各個請求的請求方式。緊接的是請求的URL。第二行開頭的數字就是請求對應的響應狀態碼,後面是響應內容的型別,如text/html代表網頁文件、image/gif代表圖片。再往後是響應體的大小和響應的時間。
當前呈現了所有請求和響應的概覽,我們可以通過這個頁面觀察到所有的請求。
如果想檢視某個請求的詳情,我們可以敲擊回車,進入請求的詳情頁面,如下圖所示。
可以看到Headers的詳細資訊,如Host、Cookies、User-Agent等。
最上方是一個Request、Response、Detail的列表,當前處在Request這個選項上。這時我們再點選TAB鍵,即可檢視這個請求對應的響應詳情,如下圖所示。
最上面是響應頭的資訊,下拉之後我們可以看到響應體的資訊。針對當前請求,響應體就是網頁的原始碼。
這時再敲擊TAB鍵,切換到最後一個選項卡Detail,即可看到當前請求的詳細資訊,如伺服器的IP和埠、HTTP協議版本、客戶端的IP和埠等,如下圖所示。
mitmproxy還提供了命令列式的編輯功能,我們可以在此頁面中重新編輯請求。敲擊e鍵即可進入編輯功能,這時它會詢問你要編輯哪部分內容,如Cookies、Query、URL等,每個選項的第一個字母會高亮顯示。敲擊要編輯內容名稱的首字母即可進入該內容的編輯頁面,如敲擊m即可編輯請求的方式,敲擊q即可修改GET請求引數Query。
這時我們敲擊q,進入到編輯Query的頁面。由於沒有任何引數,我們可以敲擊a來增加一行,然後就可以輸入引數對應的Key和Value,如下圖所示。
這裡我們輸入Key為wd,Value為NBA。
然後再敲擊esc鍵和q鍵,返回之前的頁面,再敲擊e和p鍵修改Path。和上面一樣,敲擊a增加Path的內容,這時我們將Path修改為s,如下圖所示。
再敲擊esc和q鍵返回,這時我們可以看到最上面的請求連結變成了:https://www.baidu.com/s?wd=NBA。訪問這個頁面,可以看到百度搜尋NBA關鍵詞的搜尋結果,如下圖所示。
敲擊a儲存修改,敲擊r重新發起修改後的請求,即可看到上方請求方式前面多了一個迴旋箭頭,這說明重新執行了修改後的請求。這時我們再觀察響應體內容,即可看到搜尋NBA的頁面結果的原始碼,如下圖所示。
以上內容便是mitmproxy的簡單用法。利用mitmproxy,我們可以觀察到手機上的所有請求,還可以對請求進行修改並重新發起。
Fiddler、Charles也有這個功能,而且它們的圖形介面操作更加方便。那麼mitmproxy的優勢何在?
mitmproxy的強大之處體現在它的另一個工具mitmdump,有了它我們可以直接對接Python對請求進行處理。下面我們來看看mitmdump的用法。
六、mitmdump的使用
mitmdump是mitmproxy的命令列介面,同時還可以對接Python對請求進行處理,這是相比Fiddler、Charles等工具更加方便的地方。有了它我們可以不用手動截獲和分析HTTP請求和響應,只需寫好請求和響應的處理邏輯即可。它還可以實現資料的解析、儲存等工作,這些過程都可以通過Python實現。
1. 例項引入
我們可以使用命令啟動mitmproxy,並把截獲的資料儲存到檔案中,命令如下所示:
mitmdump -w outfile複製程式碼
其中outfile
的名稱任意,截獲的資料都會被儲存到此檔案中。
還可以指定一個指令碼來處理截獲的資料,使用-s
引數即可:
mitmdump -s script.py複製程式碼
這裡指定了當前處理指令碼為script.py,它需要放置在當前命令執行的目錄下。
我們可以在指令碼里寫入如下的程式碼:
def request(flow):
flow.request.headers['User-Agent'] = 'MitmProxy'
print(flow.request.headers)複製程式碼
我們定義了一個request()
方法,引數為flow
,它其實是一個HTTPFlow
物件,通過request
屬性即可獲取到當前請求物件。然後列印輸出了請求的請求頭,將請求頭的User-Agent修改成了MitmProxy。
執行之後我們在手機端訪問http://httpbin.org/get,可以看到如下情況發生。
手機端的頁面顯示如下圖所示。
PC端控制檯輸出如下圖所示。
手機端返回結果的Headers實際上就是請求的Headers,User-Agent被修改成了mitmproxy。PC端控制檯輸出了修改後的Headers內容,其User-Agent的內容正是mitmproxy。
所以,通過這三行程式碼我們就可以完成對請求的改寫。print()
方法輸出結果可以呈現在PC端控制檯上,可以方便地進行除錯。
2. 日誌輸出
mitmdump提供了專門的日誌輸出功能,可以設定不同級別以不同顏色輸出結果。我們把指令碼修改成如下內容:
from mitmproxy import ctx
def request(flow):
flow.request.headers['User-Agent'] = 'MitmProxy'
ctx.log.info(str(flow.request.headers))
ctx.log.warn(str(flow.request.headers))
ctx.log.error(str(flow.request.headers))複製程式碼
這裡呼叫了ctx模組,它有一個log功能,呼叫不同的輸出方法就可以輸出不同顏色的結果,以方便我們做除錯。例如,info()
方法輸出的內容是白色的,warn()
方法輸出的內容是黃色的,error()
方法輸出的內容是紅色的。執行結果如下圖所示。
不同的顏色對應不同級別的輸出,我們可以將不同的結果合理劃分級別輸出,以更直觀方便地檢視除錯資訊。
3. Request
最開始我們實現了request()
方法並且對Headers進行了修改。下面我們來看看Request還有哪些常用的功能。我們先用一個例項來感受一下。
from mitmproxy import ctx
def request(flow):
request = flow.request
info = ctx.log.info
info(request.url)
info(str(request.headers))
info(str(request.cookies))
info(request.host)
info(request.method)
info(str(request.port))
info(request.scheme)複製程式碼
我們修改指令碼,然後在手機上開啟百度,即可看到PC端控制檯輸出了一系列的請求,在這裡我們找到第一個請求。控制檯列印輸出了Request的一些常見屬性,如URL、Headers、Cookies、Host、Method、Scheme等。輸出結果如下圖所示。
結果中分別輸出了請求連結、請求頭、請求Cookies、請求Host、請求方法、請求埠、請求協議這些內容。
同時我們還可以對任意屬性進行修改,就像最初修改Headers一樣,直接賦值即可。例如,這裡將請求的URL修改一下,指令碼修改如下所示:
def request(flow):
url = 'https://httpbin.org/get'
flow.request.url = url複製程式碼
手機端得到如下結果,如下圖所示。
比較有意思的是,瀏覽器最上方還是呈現百度的URL,但是頁面已經變成了httpbin.org的頁面了。另外,Cookies明顯還是百度的Cookies。我們只是用簡單的指令碼就成功把請求修改為其他的站點。通過這種方式修改和偽造請求就變得輕而易舉。
通過這個例項我們知道,有時候URL雖然是正確的,但是內容並非是正確的。我們需要進一步提高自己的安全防範意識。
Request還有很多屬性,在此不再一一列舉。更多屬性可以參考:http://docs.mitmproxy.org/en/latest/scripting/api.html。
只要我們瞭解了基本用法,會很容易地獲取和修改Reqeust的任意內容,比如可以用修改Cookies、新增代理等方式來規避反爬。
4. Response
對於爬蟲來說,我們更加關心的其實是Response的內容,因為Response Body才是爬取的結果。對於Response來說,mitmdump也提供了對應的處理介面,就是response()
方法。下面我們用一個例項感受一下。
from mitmproxy import ctx
def response(flow):
response = flow.response
info = ctx.log.info
info(str(response.status_code))
info(str(response.headers))
info(str(response.cookies))
info(str(response.text))複製程式碼
將指令碼修改為如上內容,然後手機訪問:http://httpbin.org/get。
這裡列印輸出了Response的status_code
、headers
、cookies
、text
這幾個屬性,其中最主要的text
屬性就是網頁的原始碼。
PC端控制檯輸出如下圖所示。
控制檯輸出了Response的狀態碼、響應頭、Cookies、響應體這幾部分內容。
我們可以通過response()
方法獲取每個請求的響應內容。接下來再進行響應的資訊提取和儲存,我們就可以成功完成爬取了。
本資源首發於崔慶才的個人部落格靜覓: Python3網路爬蟲開發實戰教程 | 靜覓
如想了解更多爬蟲資訊,請關注我的個人微信公眾號:進擊的Coder
weixin.qq.com/r/5zsjOyvEZ… (二維碼自動識別)