You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用mitmproxy在Python代码中直接获取请求/响应数据(替代Browsermob-Proxy)

用mitmproxy替代Browsermob-Proxy实现无文件式请求响应捕获

mitmproxy可以通过自定义addon脚本直接在内存中存储请求和响应数据,完全不需要写入文件,实现和Browsermob-Proxy类似的HAR式捕获效果。

实现思路

  1. 编写一个mitmproxy addon类,在内存中维护一个列表,用来存储每个请求的详细信息(请求头、内容、响应头、内容等)。
  2. 在Python主脚本中启动mitmproxy代理线程,同时加载这个addon。
  3. 配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 21:25:23