Puppeteer设置headless:'new'|false时请求统计异常求助
Puppeteer headless:'new'模式请求捕获数量减少的原因及解决办法
你遇到的问题源于新旧headless模式、非无头模式之间的浏览器资源加载策略差异,具体原因和解决方式如下:
核心原因
页面加载等待逻辑不同
旧版headless: true基于Chrome旧无头实现,page.goto()默认的等待逻辑会让页面加载更“彻底”;而新版headless: 'new'和非无头模式更贴近真实用户浏览器行为,默认仅等待DOM加载完成(DOMContentLoaded),此时很多低优先级资源如字体、第三方脚本还未触发加载,就被提前关闭的浏览器打断,导致请求未被捕获。资源加载策略差异
新版headless模式启用了和真实浏览器一致的资源节流机制:比如后台页面不会加载非关键资源、懒加载资源会延迟触发;而旧无头模式没有这些限制,会强制加载所有资源。视口与渲染状态影响
新版headless模式默认视口尺寸极小甚至为空,部分响应式网站会根据视口大小加载不同资源,导致部分外部请求不会触发。
解决办法
1. 延长页面等待时间,确保资源加载完成
修改page.goto的等待策略,使用networkidle2或load,等待网络请求趋于稳定后再关闭浏览器:
// 替换原page.goto行 await page.goto(url, { waitUntil: 'networkidle2', // 网络连接数≤2且持续500ms时认为加载完成 timeout: 60000 // 超时时间设为60秒,避免因加载慢导致提前终止 });
如果需要更彻底的等待,可以用waitUntil: 'load'等待所有资源加载完成,包括图片、字体等,但耗时会更长。
2. 设置真实浏览器视口
模拟真实用户的视口尺寸,确保网站加载完整资源:
// 在page.newPage()后添加 await page.setViewport({ width: 1280, height: 720 });
3. 调整浏览器启动参数
禁用部分资源节流特性,确保所有资源都能被加载:
const browser = await puppeteer.launch({ headless: 'new', args: [ '--disable-background-throttling', // 禁用后台页面资源节流 '--disable-lazy-loading', // 禁用懒加载 '--disable-features=ImprovedCookieControls,LazyFrameLoading' // 关闭可能影响资源加载的特性 ] });
4. 优化域名判断逻辑
确保extractDomain能准确识别外部域名,避免因子域名判断错误漏统计。比如改用精确域名匹配替代includes:
// 替换原域名判断逻辑 const originalHostname = new URL(url).hostname; const requestHostname = new URL(request.url()).hostname; if (requestHostname !== originalHostname) { // 统计外部请求 }
修改后的完整代码示例
export async function getExternalFonts(url) { const containHttpS = /^https?:\/\//i; if (!containHttpS.test(url)) { url = `http://${url}`; } const browser = await puppeteer.launch({ headless: 'new', args: [ '--disable-background-throttling', '--disable-lazy-loading' ] }); const page = await browser.newPage(); // 设置真实视口 await page.setViewport({ width: 1280, height: 720 }); await page.setRequestInterception(true); const externalLinks = []; const originalHostname = new URL(url).hostname; page.on('request', (request) => { const requestHostname = new URL(request.url()).hostname; if (requestHostname !== originalHostname) { externalLinks.push({ url: request.url(), type: request.resourceType(), method: request.method(), headers: request.headers() }); } request.continue(); }); // 等待网络空闲后再关闭浏览器 await page.goto(url, { waitUntil: 'networkidle2', timeout: 60000 }); await browser.close(); console.log("external links count:", externalLinks.length); return externalLinks; }
内容的提问来源于stack exchange,提问作者DWORD
相关产品推荐
相关产品推荐

