Playwright 应同时监听 page.on("console") 和 page.on("pageerror"):前者捕获 console.error 等主动日志,后者捕获未捕获异常(含完整 Error 实例);监听须在 page.new_page() 后立即注册,否则易漏首屏报错。

监听 page 的 console 事件就能捕获报错
Playwright 的 page 对象原生支持监听浏览器控制台输出,不需要注入脚本或 hook console.error。关键在于用 page.on("console", callback),然后在回调里判断 msg.type() 是否为 "error" 或 "warning"。
注意:这个监听只对页面加载后、事件绑定之后产生的 console 输出有效;页面初始加载时的报错(比如 HTML 解析失败、脚本 early error)不会触发该事件。
-
page.on("console", ...)必须在page.goto()之前或之后立即注册,越早越好 -
msg.text()返回完整字符串,包含堆栈(如果有),但不带颜色/格式 - 若需区分 JS 错误和普通
console.error()调用,得结合msg.type()和msg.location()判断
如何区分真实 JS 运行时错误和普通 console.error
浏览器控制台里 console.error("msg") 和 throw new Error() 都会触发 console 事件,但类型不同:throw 产生的错误会先触发 page.on("pageerror"),再触发一次 console(type = "error");而纯 console.error() 只触发 console 事件。
- 真正要抓“未捕获异常”,优先监听
page.on("pageerror", ...),它返回的是Error实例,含message、stack -
page.on("console")更适合捕获主动打点的错误日志、第三方 SDK 输出等 - 两者建议同时启用,避免漏掉任何一类错误信号
常见漏掉的坑:异步上下文与作用域失效
如果你在 async with async_playwright() as p: 内部启动浏览器、上下文、页面,但把 page.on("console") 注册写在 goto() 之后、且没 await 等待页面就绪,可能错过首屏 JS 报错。
- 务必在
page = await context.new_page()后立刻注册监听,不要等到await page.goto(...)完成 - 如果页面有大量动态加载(如 React/Vue SPA),首次
console事件可能出现在domcontentloaded之后、load之前,别依赖wait_for_load_state才开始监听 - 在
page.route()或page.add_init_script()中修改全局console行为,会干扰原生监听逻辑,不推荐
一个最小可运行示例
from playwright.async_api import async_playwright
<p>async def main():
async with async_playwright() as p:
browser = await p.chromium.launch()
context = await browser.new_context()
page = await context.new_page()</p><pre class="brush:python;toolbar:false;"> # ✅ 立即注册监听
page.on("console", lambda msg: print(f"[CONSOLE {msg.type()}] {msg.text()}"))
page.on("pageerror", lambda err: print(f"[PAGEERROR] {err}"))
await page.goto("https://example.com")
await page.evaluate('console.error("test error"); throw new Error("unhandled");')
await page.wait_for_timeout(1000)
asyncio.run(main())
运行后你会看到两行输出:[CONSOLE error] 和 [PAGEERROR] —— 前者来自 console.error,后者来自 throw。如果只靠 console 监听,会漏掉没有显式 console 调用的崩溃场景。
真实项目中,pageerror 的堆栈往往比 console 的更可靠;但很多前端监控体系只打 console.error,所以两个都得留着,不能只选一个。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











