如何用mitmproxy在Python代码中直接获取请求/响应数据(替代Browsermob-Proxy)
用mitmproxy替代Browsermob-Proxy实现无文件式请求响应捕获
mitmproxy可以通过自定义addon脚本直接在内存中存储请求和响应数据,完全不需要写入文件,实现和Browsermob-Proxy类似的HAR式捕获效果。
实现思路
- 编写一个mitmproxy addon类,在内存中维护一个列表,用来存储每个请求的详细信息(请求头、内容、响应头、内容等)。
- 在Python主脚本中启动mitmproxy代理线程,同时加载这个addon。
- 配置Selenium使用mitmproxy作为代理,执行爬虫操作后,直接从addon实例中提取存储的数据。
完整代码示例
第一步:编写HAR捕获的Addon
这个addon会自动拦截所有请求和响应,并把数据存在内存里:
from mitmproxy import http from typing import List, Dict class HarRecorder: def __init__(self): # 存储所有请求响应条目 self.entries: List[Dict] = [] def request(self, flow: http.HTTPFlow) -> None: # 捕获请求数据,先存入列表,待响应返回后补全 req = flow.request entry = { "request": { "method": req.method, "url": req.pretty_url, "headers": dict(req.headers), "content": req.content.decode('utf-8', errors='ignore') if req.content else "" }, "response": None } self.entries.append(entry) def response(self, flow: http.HTTPFlow) -> None: # 匹配对应的请求,补全响应数据 resp = flow.response for entry in self.entries: if entry["request"]["url"] == flow.request.pretty_url and entry["response"] is None: entry["response"] = { "status_code": resp.status_code, "headers": dict(resp.headers), "content": resp.content.decode('utf-8', errors='ignore') if resp.content else "" } break
第二步:主脚本结合Selenium使用
启动mitmproxy代理,执行爬虫操作后直接提取数据:
import threading from mitmproxy.tools.main import run from selenium import webdriver from selenium.webdriver.common.by import By # 初始化捕获器实例 har_recorder = HarRecorder() # 启动mitmproxy代理线程 def start_mitmproxy(): # 监听8080端口,忽略SSL证书错误,加载当前脚本作为addon run(["--listen-port", "8080", "--ssl-insecure", "-s", __file__]) proxy_thread = threading.Thread(target=start_mitmproxy, daemon=True) proxy_thread.start() # 配置Chrome使用mitmproxy代理 chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--proxy-server=http://127.0.0.1:8080') chrome_options.add_argument('--ignore-certificate-errors') # 忽略MITM证书错误 driver = webdriver.Chrome(options=chrome_options) try: # 执行你的爬虫操作 driver.get("https://www.baidu.com") driver.find_element(By.ID, "kw").send_keys("python") driver.find_element(By.ID, "su").click() # 等待页面加载完成,确保所有请求被捕获 driver.implicitly_wait(5) # 提取捕获的数据,格式接近Browsermob-Proxy的HAR结构 har_data = { "log": { "version": "1.2", "creator": {"name": "mitmproxy-har-recorder"}, "entries": har_recorder.entries } } # 这里可以直接使用har_data,比如打印、解析特定请求 print("捕获到的请求响应条目数:", len(har_data["log"]["entries"])) # 示例:提取百度搜索的响应内容 for entry in har_data["log"]["entries"]: if "baidu.com/s?" in entry["request"]["url"]: print("搜索请求响应内容:", entry["response"]["content"]) finally: driver.quit()
关键注意事项
- 证书问题:首次运行mitmproxy时,需要在系统或浏览器中安装mitmproxy的CA证书,否则HTTPS请求会失败。如果不想安装证书,可以加
--ssl-insecure参数忽略证书校验(仅测试用)。 - 请求匹配:示例中用URL匹配请求和响应,如果有重复URL的请求,可能需要用更精准的标识(比如请求ID)来匹配,避免数据错乱。
- 数据过滤:如果只需要捕获特定域名或路径的请求,可以在
request方法中添加判断,比如if "your-target-domain.com" in flow.request.pretty_url,只存入符合条件的请求。
内容的提问来源于stack exchange,提问作者summer desire
相关产品推荐
相关产品推荐

