启用Puppeteer请求拦截后请求总数异常,求技术解析
问题
用Node.js结合Puppeteer做网站重载时的特定请求拦截,发现启用请求拦截后,脚本统计的请求数比Chrome DevTools里显示的少。想知道这是不是拦截延迟导致的正常情况?
测试结果:
- 关闭拦截时,首次加载和每次重载的请求数都是22次,和DevTools记录一致;
- 开启拦截后,首次加载有24次请求,重载时请求数甚至不到16次。
是不是漏了什么关键配置?
测试脚本:
/* package.json { "dependencies": { "puppeteer": "latest" } } */ const puppeteer = require(`puppeteer`); let requestCount = [0,0,0,0]; let i = 0; const url = "https://picsum.photos/"; const interceptEnabled = true; (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); if(interceptEnabled){ await page.setRequestInterception(true); } await page.on("request", request => { if(interceptEnabled){ request.continue(); } requestCount[i]++; // console.log(`url[${requestCount[i]}]: ${request.url()}`); }); await page.goto(url,{waitUntil: "networkidle0"}); console.log(`Total requests load: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); console.log(requestCount); await browser.close(); })();
解答
这不是拦截延迟导致的正常现象,核心问题出在事件绑定和拦截启用的顺序错误,还有不必要的await拖慢了事件绑定时机:
- 事件绑定顺序颠倒:你先启用了请求拦截,再绑定
request事件。Puppeteer里,开启拦截后,所有未被处理的请求会被挂起,但如果事件绑定在拦截启用之后,会错过那些在绑定前就触发的请求,直接导致统计不全。 - 多余的await:
page.on是同步方法,不需要加await,加了反而会让事件绑定时机延后,进一步错过早期触发的请求。 - 重载时请求数减少,除了上述问题,还可能因为开启拦截后浏览器默认缓存行为被改变,但核心原因还是请求捕获不完整。
修正后的脚本:
/* package.json { "dependencies": { "puppeteer": "latest" } } */ const puppeteer = require(`puppeteer`); let requestCount = [0,0,0,0]; let i = 0; const url = "https://picsum.photos/"; const interceptEnabled = true; (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 先绑定request事件,再启用拦截 page.on("request", request => { if(interceptEnabled){ request.continue(); } requestCount[i]++; // console.log(`url[${requestCount[i]}]: ${request.url()}`); }); if(interceptEnabled){ await page.setRequestInterception(true); } await page.goto(url,{waitUntil: "networkidle0"}); console.log(`Total requests load: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); i++; await page.reload({waitUntil: "networkidle0"}); console.log(`Total requests after reload: ${requestCount[i]}`); console.log(requestCount); await browser.close(); })();
如果需要确保捕获所有请求(包括服务端推送、预加载请求),还可以额外监听requestfinished和requestfailed事件,但大部分场景下调整顺序后就能解决问题。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

