Docker容器中Headless Chrome网络请求拦截及请求负载读取方法问询
当然有办法!我之前在Docker环境下处理过类似的需求,下面几种方案都能帮你拦截Headless Chrome的网络请求并读取请求负载,你可以根据自己的场景选择:
这是最贴合Headless Chrome原生能力的方案,你可以用Puppeteer或者Playwright这类自动化工具来封装CDP操作,它们本身就支持在Docker环境中运行。
核心思路是启用Chrome的网络请求拦截,监听请求发送前的事件,从中提取请求负载(也就是postData)。下面是一个用Puppeteer实现的示例:
const puppeteer = require('puppeteer'); (async () => { // Docker环境下启动Headless Chrome必须加这些参数,避免沙箱和资源限制问题 const browser = await puppeteer.launch({ headless: 'new', args: [ '--no-sandbox', '--disable-dev-shm-usage', '--disable-gpu', '--disable-setuid-sandbox' ] }); const page = await browser.newPage(); // 启用请求拦截功能 await page.setRequestInterception(true); // 监听每个请求的发送事件 page.on('request', (request) => { // 只处理有负载的POST/PUT等请求 if (request.postData()) { console.log(`=== 捕获到带负载的请求 ===`); console.log(`请求URL: ${request.url()}`); console.log(`请求方法: ${request.method()}`); console.log(`原始请求负载:`); console.log(request.postData()); // 如果负载是JSON格式,可以解析成对象方便查看 try { const parsedPayload = JSON.parse(request.postData()); console.log(`解析后的JSON负载:`); console.log(parsedPayload); } catch (err) { // 非JSON格式,跳过解析 } } // 一定要调用continue(),否则请求会被阻塞 request.continue(); }); // 导航到目标页面,或者执行触发请求的操作 await page.goto('https://your-target-url.com'); // 比如模拟点击按钮触发请求:await page.click('#submit-form-btn'); await browser.close(); })();
在Docker里运行这个脚本的话,记得要使用包含Node.js和Puppeteer的镜像,或者自己构建镜像时安装依赖,确保Chrome的启动参数正确配置。
如果你不想用自动化工具,只是想被动拦截Headless Chrome的所有网络请求,mitmproxy是个非常好用的选择。它可以作为中间人代理捕获所有HTTP/HTTPS请求,包括请求负载。
步骤如下:
- 在Docker中启动mitmproxy容器:
docker run -d \ -p 8080:8080 \ -p 8081:8081 \ -v ~/.mitmproxy:/home/mitmproxy/.mitmproxy \ mitmproxy/mitmproxy
这里8080是代理端口,8081是mitmweb的Web界面端口,挂载目录是为了保存证书。
- 配置Headless Chrome使用这个代理:
启动Chrome时添加代理参数,同时要处理HTTPS证书的问题(因为mitmproxy会生成自签名证书):
google-chrome \ --headless=new \ --no-sandbox \ --disable-dev-shm-usage \ --proxy-server=http://<mitmproxy-container-ip>:8080 \ --ignore-certificate-errors
注意:--ignore-certificate-errors只适合测试场景,生产环境建议将mitmproxy的根证书导入Chrome的信任存储中。
- 查看请求负载:
你可以通过mitmweb的Web界面(访问http://localhost:8081)或者mitmproxy的命令行界面,找到对应的请求,查看Request Body部分就是你要的负载。
如果需要长期拦截特定请求,你可以开发一个简单的Chrome扩展,利用webRequest API来捕获请求负载。不过在Headless Chrome中加载扩展需要特殊配置:
- 编写扩展的
manifest.json,需要申请webRequest和webRequestBlocking权限,以及目标域名的权限:
{ "manifest_version": 3, "name": "Request Payload Capturer", "version": "1.0", "permissions": ["webRequest", "webRequestBlocking"], "host_permissions": ["<all_urls>"], "background": { "service_worker": "background.js" } }
- 编写
background.js监听请求:
chrome.webRequest.onBeforeRequest.addListener( (details) => { if (details.requestBody && details.requestBody.raw) { // 解析原始请求体(raw是ArrayBuffer数组) const payload = new TextDecoder('utf-8').decode(details.requestBody.raw[0].bytes); console.log(`捕获到请求负载: ${payload}`); } }, { urls: ["<all_urls>"] }, ["requestBody"] );
- 在Docker中启动Chrome时加载扩展:
google-chrome \ --headless=new \ --no-sandbox \ --disable-dev-shm-usage \ --load-extension=/path/to/your/extension
记得把扩展目录挂载到Docker容器里,比如用-v ./my-extension:/path/to/your/extension参数。
这个方案适合需要持续监控请求的场景,但开发和配置相对前两种要繁琐一些。
总结一下:
- 如果你在用代码控制Headless Chrome,优先选方案1(Puppeteer/Playwright + CDP),集成度最高;
- 如果你只是想被动拦截所有请求,方案2(mitmproxy)最灵活,不需要修改Chrome的控制代码;
- 方案3适合需要长期、特定规则的拦截场景。
内容的提问来源于stack exchange,提问作者Vinny

