page.on('response')未记录部分链接,因其仅监听当前页面主文档及子资源请求,不自动跟踪跳转、js跳转、非http协议链接、csp拦截请求及新标签页,需显式goto并重新绑定监听。

page.on('response') 捕获 404 状态码时,为什么有些链接没被记录?
因为 page.on('response') 只监听当前 page.goto() 触发的主文档及其子资源(脚本、样式、图片、AJAX),但不会自动跟踪页面内 <a></a> 标签跳转产生的新导航请求——除非你显式调用 page.goto() 访问每个链接。
常见误判场景包括:
- 页面用
window.location.href = 'xxx'或history.pushState跳转,不触发新response事件 - 链接是 mailto:、tel:、javascript: 协议,Puppeteer 默认不发起网络请求
- 目标链接被 CSP 或同源策略拦截,请求根本未发出,自然无
response - 你监听的是某个
page实例,但后续新开的page(如page.click()后弹窗或新标签页)没重新绑定监听
正确做法是:先用 page.evaluate 提取所有 href,过滤出 http/https 协议的内部链接,再逐个 page.goto(url, { waitUntil: 'networkidle0', timeout: 15000 }) 并捕获其 response;对失败的导航,用 page.url() 和 page.title() 辅助判断是否为软 404。
如何判断一个返回 200 的页面其实是“结构异常”?
真实业务中,大量页面返回 200 却内容缺失:标题为空、关键模块 DOM 不存在、JSON-LD 数据缺失、或渲染后只剩骨架屏。仅靠状态码完全不可靠。
必须结合 DOM 检查做二次判定,例如:
- 检查
document.title是否为空或含 “404”“Error”“Not Found” 字样 - 用
page.$(selector)尝试定位核心容器(如#app、.main-content),返回null即结构异常 - 执行
page.evaluate(() => !!document.querySelector('script[type="application/ld+json"]'))验证结构化数据存在性 - 对 SPA 页面,加
await page.waitForFunction(() => window.__POWERED_BY_QIANKUN__ || document.querySelector('#root')?.children.length > 0)确保框架已挂载
注意:不要在 page.goto() 后立刻检查,需配合 waitUntil: 'networkidle0' 或显式 waitForSelector,否则可能读到未渲染的初始 HTML。
死链检测时,page.goto() 报错但 response.status 是多少?
page.goto() 抛出异常时,response.status() 根本不存在——因为请求都没完成,更谈不上响应。典型报错包括:
-
net::ERR_CONNECTION_REFUSED(目标端口关闭) -
net::ERR_NAME_NOT_RESOLVED(DNS 失败) -
net::ERR_TIMED_OUT(超时,此时你设的timeout参数起效) -
net::ERR_ABORTED(页面跳转被中断,比如重定向链过长)
这些都属于网络层失败,不是 HTTP 状态码问题。处理逻辑应是:
- 用
try/catch捕获page.goto()异常,归类为「不可达」而非「404」 - 对
TimeoutError单独处理,可重试一次(避免因瞬时抖动误判) - 记录
error.name和error.message,比只存状态码更有诊断价值
监控脚本长期运行时,浏览器内存泄漏怎么防?
Puppeteer 实例不释放会导致内存持续增长,尤其在高频轮询场景下。关键控制点不在 JS 代码里,而在启动参数和生命周期管理上。
- 必须设置
args: ['--disable-dev-shm-usage', '--no-sandbox'],否则 Docker 或无特权环境易崩溃 - 避免复用
browser实例超过 1 小时;建议每 30 分钟browser.close()+ 重建,或用puppeteer.launch({ headless: 'new' })(Chromium 117+ 推荐) - 每个
page用完立即page.close(),别依赖 GC;若需保留上下文,至少page.unroute('*')清理所有page.route()拦截 - 禁用日志输出:
ignoreHTTPSErrors: true和defaultViewport: null减少开销
最容易被忽略的是 page.on('request') 和 page.on('response') 监听器——它们会一直持有闭包引用,必须在 page.close() 前手动 page.removeAllListeners('response'),否则内存无法回收。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











