原文鏈接 https://blog.csdn.net/qianwenjun_19930314/article/details/88227335
1、腳本編寫的兩個條件
1.1 編寫一個 py 文件供 mitmproxy 加載,文件中定義了若干函數,這些函數實現了某些 mitmproxy 提供的事件,mitmproxy 會在某個事件發生時調用對應的函數
1.2 編寫一個 py 文件供 mitmproxy 加載,文件定義了【變量 addons】,addons 是個數組,每個元素是一個類實例,這些類有若干方法,這些方法實現了某些 mitmproxy 提供的事件,mitmproxy 會在某個事件發生時調用對應的方法。這些類,稱為一個個 addon。
基本模板為
from mitmproxy import http, ctx
import json
class xxx:
def xxx:
def xxx
addons = [
xxx() //類名的加載,也可以定義多個類,然后以數組的形式添加,進行加載
]
1.3 針對 HTTP 生命周期
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 收到了來自客戶端的 HTTP CONNECT 請求。在 flow 上設置非 2xx 響應將返回該響應並斷開連接。CONNECT 不是常用的 HTTP 請求方法,目的是與服務器建立代理連接,僅是 client 與 proxy 的之間的交流,所以 CONNECT 請求不會觸發 request、response 等其他常規的 HTTP 事件。
def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 來自客戶端的 HTTP 請求的頭部被成功讀取。此時 flow 中的 request 的 body 是空的。
def request(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 來自客戶端的 HTTP 請求被成功完整讀取。
def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 來自服務端的 HTTP 響應的頭部被成功讀取。此時 flow 中的 response 的 body 是空的。
def response(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 來自服務端端的 HTTP 響應被成功完整讀取。
def error(self, flow: mitmproxy.http.HTTPFlow):
(Called when) 發生了一個 HTTP 錯誤。比如無效的服務端響應、連接斷開等。注意與“有效的 HTTP 錯誤返回”不是一回事,后者是一個正確的服務端響應,只是 HTTP code 表示錯誤而已。
2 、腳本函數編寫
2.1 替換請求
from mitmproxy import ctx, http
import json
class Modify:
def request(self, flow):
#替換請求鏈接
if flow.request.url.startswith("http://spay1.shuqireader.com/api/ios/info?method=priceList"):
#有分享
flow.request.url = "http://activity.x.xxx.xx.cn/share?id=2653&useShare=1"
ctx.log.info("修改鏈接")
addons = [
Modify()
]
2.2 修改cookies
from mitmproxy import ctx, http
import json
class Modify:
def request(self, flow):
#替換cookie,兩種匹配請求鏈接的方式
# if flow.request.host == "xxx.x.xxx.com.cn":
if flow.request.url.startswith("https://xxx.x.xxx.com.cn/"):
print(flow.request.url)
print(flow.request.cookies)
flow.request.cookies["_testCookie1"] = "xxx-91"
flow.request.cookies["testCookie2"] = "123"
req = flow.request.cookies["_testCookie1"]
ctx.log.info(req)
addons = [
Modify()
]
2.3 修改請求參數
from mitmproxy import ctx, http
import json
class Modify:
def request(self, flow):
if flow.request.url.startswith("http://xxx.x.xxx.com.cn/customActivity/bookcode/doJoin"):
ctx.log.info("modify request form")
if flow.request.urlencoded_form:
flow.request.urlencoded_form["code"] = "11111"
else:
flow.request.urlencoded_form = [
("actId", "20727"),("nick","name")
]
addons = [
Modify()
]
2.4 修改相應狀態
from mitmproxy import ctx, http
import json
class Modify:
def response(self, flow):
if flow.request.url.startswith("http://baidu.com.cn"):
flow.response = http.HTTPResponse.make(404)
ctx.log.info("modify status code")
addons = [
Modify()
]
2.5 修改響應體
from mitmproxy import ctx, http
import json
class Modify:
def response(self, flow):
if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
//獲取響應的json字符串,轉成python對象進行解析和修改
response = json.loads(flow.response.get_text())
response['limitCount'] = 1
//修改完成后,獎python對象轉成json字符串,set進請求的響應體重發送給客戶端
flow.response.set_text(json.dumps(response))
ctx.log.info('modify limitCount')
addons = [
Modify()
]
2.6 讀取json文件中字符串返回客戶端
from mitmproxy import ctx, http
import json
class Modify:
def response(self, flow):
if flow.request.url.startswith("https://xxx.x.xxx.com.cn/activityInfo/getPrizeInfo=="):
//讀取文件,在當前文件路徑下執行腳本,否則需要寫文件的絕對路徑;不然會找不到該json文件
with open('getStatus.json','rb') as f:
//從json文件中讀取數據成python對象
res = json.load(f)
//將讀取的python對象轉成json字符串發送給客戶端
flow.response.set_text(json.dumps(res))
ctx.log.info("modify order status")
addons = [
Modify()
]
2.7 Request的一些方法:
get_query():得到請求的url的參數,被存放成了字典。
set_query(odict):設置請求的url參數,參數是字典。
get_url():請求的url。 set_url(url):設置# url的域。
get_cookies():得到請求的cookie。 headers:請求的header的字典。
content:請求的內容,如果請求時post,那么content就是指代post的參數。
Response的一些方法如下: Headers:返回的header的字典。
Code:返回數據包的狀態,比如200,301之類的狀態。
Httpversion:http版本。
3、腳本加載
mitmdump -s script.py
4、插件腳本的基本使用
4.1 日志輸出,
日志輸出
調用ctx模塊:from mitmproxy import ctx引入,然后通過ctx.log.xxx輸出:
ctx.log.info(顯示白色)
ctx.log.wran(顯示黃色)
ctx.log.error(顯示紅色)
4.2 參數flow,我們可以通過flow.request屬性獲取當前請求,
通過flow.request.xxx獲取相應屬性,如:
flow.request.url(請求的url地址)
flow.request.headers(請求頭信息)
flow.request.cookies(cookies信息)
flow.request.host(host標頭值)
flow.request.method(請求方法)
flow.request.port(請求的端口)
flow.request.scheme(請求協議)
更多內容請查看mitmproxy的API接口
不僅可以獲取相應的值,我們也可以對其值進行修改:
flow.request.url = 新的url
# 通過這種方式我們就可以進行修改和偽造請求,通過此方式我們知道,在日常上網的過程中,有時候我們輸入的url是正確的,但是頁面內容卻與我們所需要看到的不同, 有的釣魚網站可能是通過此方式進行改變網頁信息的,因此我們在日常上網過程中應注意網絡安全。
# 在日常爬蟲過程中,我們可以通過修改cookies和添加代理的方式來規避網站的反爬。
4.3 參數flow,我們可以通過flow.response屬性獲取當前請求
# 對於爬蟲來說,我們更想獲取其響應的內容,對於響應來說,我們采用response()方法來獲取響應的內容:
通過flow.response.xxx獲取相應屬性,如:
flow.repsonse.status_code(獲取響應的狀態碼)
flow.repsonse.headers(獲取響應頭信息)
flow.repsonse.cookies(獲取響應的cookies信息)
flow.repsonse.text(獲取響應的內容)
通過上述的這些基本方法再加上一些數據的存儲技術,就可以實現對數據的抓取了
