You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Rust的headless_chrome crate检测JavaScript错误

解决headless_chrome捕获JS错误/console.assert的问题

原代码的问题在于console.assert(false)不会触发DebuggerPaused事件——这个事件仅在调试器断点触发或未捕获异常导致暂停时才会触发,而console.assert只是在控制台输出一条错误日志,不会主动暂停调试器。

下面提供两种可行的捕获方式:

方式一:捕获console错误(包括console.assert)

通过监听Log.entryAdded事件,可以捕获所有控制台输出的日志,包括console.assert产生的错误:

use headless_chrome::{protocol::cdp::{Log::Event::EntryAdded as LogEntryAdded, types::Event}, Browser, LaunchOptions};
use std::{error::Error, sync::Arc};

fn main() -> Result<(), Box<dyn Error>> {
    let browser = Browser::new(
        LaunchOptions::default_builder()
            .window_size(Some((2000, 2000)))
            .build()
            .expect("Could not find chrome-executable"),
    )?;
    let tab = browser.new_tab()?;
    tab.enable_log().unwrap(); // 必须启用Log域

    // 监听Log.entryAdded事件
    let _events = tab.add_event_listener(Arc::new(move |event: &Event| {
        if let Event::LogEntryAdded(added_event) = event {
            let entry = &added_event.entry;
            // 筛选Error级别的日志,console.assert属于此类
            if entry.level == "error" {
                dbg!("捕获到console错误:", entry.message);
                if entry.message.contains("Assertion failed") {
                    println!("检测到console.assert失败");
                }
            }
        }
    }))?;

    // 执行console.assert
    let _remote_object = tab.evaluate("console.assert(false, '自定义断言消息');", true).unwrap();

    std::thread::sleep(std::time::Duration::from_secs(1));

    Ok(())
}

方式二:捕获未捕获的JS异常

如果需要捕获主动抛出的JS异常(比如throw new Error()),可以监听Debugger.exceptionThrown事件,并设置调试器在异常时暂停:

use headless_chrome::{protocol::cdp::{Debugger::Event::ExceptionThrown, types::Event}, Browser, LaunchOptions};
use std::{error::Error, sync::Arc};

fn main() -> Result<(), Box<dyn Error>> {
    let browser = Browser::new(
        LaunchOptions::default_builder()
            .window_size(Some((2000, 2000)))
            .build()
            .expect("Could not find chrome-executable"),
    )?;
    let tab = browser.new_tab()?;
    tab.enable_debugger().unwrap(); // 启用Debugger域

    // 设置调试器在未捕获异常时暂停
    tab.debugger_set_pause_on_exceptions(Some(true)).unwrap();

    // 监听异常抛出事件
    let _events = tab.add_event_listener(Arc::new(move |event: &Event| {
        if let Event::DebuggerExceptionThrown(thrown_event) = event {
            dbg!("捕获到JS异常:", thrown_event.exception_details);
        }
    }))?;

    // 执行抛出异常的JS代码
    let _remote_object = tab.evaluate("throw new Error('测试异常');", true).unwrap();

    std::thread::sleep(std::time::Duration::from_secs(1));

    Ok(())
}

关键说明

  • 不同的CDP事件对应不同的场景:Log.entryAdded负责控制台日志,Debugger.exceptionThrown负责未捕获的JS异常。
  • 使用前必须启用对应的域(enable_log()或enable_debugger()),否则无法收到事件。
  • console.assert本质是输出错误日志,不属于未捕获异常,所以只能通过Log.entryAdded捕获。

内容的提问来源于stack exchange,提问作者Max888

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:42:38