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

Puppeteer无法捕获的Target Closed Error问题求助

Puppeteer 频繁出现 TargetCloseError 且无法捕获导致应用崩溃

问题现象

每10到50次请求就会触发以下错误,且错误无法被try/catch捕获,直接导致应用崩溃:

TargetCloseError: Protocol error (Network.getCookies): Target closed
at CallbackRegistry.clear (/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:153:36)
at CDPSessionImpl._onClosed (/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:468:70)
at Connection.onMessage (/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:265:25)
at WebSocket.<anonymous> (/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/NodeWebSocketTransport.js:62:32)
at callListener (/app/node_modules/ws/lib/event-target.js:290:14)
at WebSocket.onMessage (/app/node_modules/ws/lib/event-target.js:209:9)
at WebSocket.emit (node:events:513:28)
at Receiver.receiverOnMessage (/app/node_modules/ws/lib/websocket.js:1184:20)
at Receiver.emit (node:events:513:28)
at Receiver.dataMessage (/app/node_modules/ws/lib/receiver.js:541:14)
at Receiver.getData (/app/node_modules/ws/lib/receiver.js:459:17)
at Receiver.startLoop (/app/node_modules/ws/lib/receiver.js:158:22)
at Receiver._write (/app/node_modules/ws/lib/receiver.js:84:10)
at writeOrBuffer (node:internal/streams/writable:392:12)
at _write (node:internal/streams/writable:333:10)
at Writable.write (node:internal/streams/writable:337:10) 

现有代码

所有涉及Puppeteer的操作均已使用await,代码如下:

let browser = null;
try {
    browser = await puppeteer.launch({
        headless: "new",
        args: [
            `--user-agent=${userAgent}`,
            '--no-sandbox'
        ]
    });
    browser.on('disconnected', () => browserDisconnected = true)
    const page = await browser.newPage();

    await useProxy(page, proxyUrl);
    await page.goto(url);
    await setTimeout(pageLoadTimeout);
    await page.waitForSelector("#Title");

    const renderedContent = await page.content();
    const $ = cheerio.load(renderedContent);

    const title = $("#Title").html();

    output = { title: title };
} catch (error) {
    console.log(error);
    output =  { error: true, error: error.message };
} finally {
    try {
        if(browser !== null) {
            await browser.close();
        }
    } catch(error) {
        console.log("ERROR CLOSING BROWSER:");
        console.log(error);
    }
    return output;
}   

运行环境

Google App Engine 中使用 --platform=linux/amd64 node:18 的 Docker 容器

解决方案

1. 全局捕获未处理异常

该错误属于未处理的Promise拒绝或未捕获异常,需通过Node.js全局事件监听捕获:

// 捕获未处理的Promise拒绝
process.on('unhandledRejection', (reason, promise) => {
  console.error('未处理的Promise拒绝:', reason);
  // 可在此处执行紧急清理,比如关闭存活的浏览器实例
});

// 捕获未捕获的同步异常
process.on('uncaughtException', (error) => {
  console.error('未捕获的异常:', error);
  // 异常后进程可能处于不稳定状态,建议重启
  process.exit(1);
});

2. 监听Puppeteer实例的错误事件

错误可能来自Browser或Page的内部事件,需主动监听提前处理:

// 创建浏览器后添加
browser.on('error', (error) => {
  console.error('浏览器实例错误:', error);
  browserDisconnected = true;
});

// 创建页面后添加
page.on('error', (error) => {
  console.error('页面崩溃错误:', error);
  browserDisconnected = true;
});

page.on('pageerror', (error) => {
  console.error('页面内JS错误:', error);
});

3. 修复代码错误并增强校验

  • 错误的setTimeout使用:await setTimeout(pageLoadTimeout) 不会等待超时,需替换为Puppeteer提供的waitForTimeout:
    await page.waitForTimeout(pageLoadTimeout);
    
  • 增加状态校验:在每个Puppeteer操作前检查浏览器连接状态,提前终止流程:
    if (browserDisconnected) throw new Error('浏览器已断开连接');
    await page.goto(url);
    

4. 优化Puppeteer启动参数

针对Docker环境添加稳定性参数,解决资源不足或进程通信问题:

browser = await puppeteer.launch({
    headless: "new",
    args: [
        `--user-agent=${userAgent}`,
        '--no-sandbox',
        '--disable-setuid-sandbox',
        '--disable-dev-shm-usage', // 解决Docker共享内存不足
        '--disable-gpu',
        '--disable-software-rasterizer',
        '--no-zygote',
        '--single-process' // 减少进程间通信异常
    ],
    timeout: 30000 // 增加启动超时时间
});

5. 检查代理稳定性

代理连接不稳定可能导致页面目标断开,可给代理操作添加重试逻辑:

// 给useProxy添加重试封装
async function useProxyWithRetry(page, proxyUrl, retries = 2) {
  try {
    await useProxy(page, proxyUrl);
  } catch (error) {
    if (retries > 0) {
      return useProxyWithRetry(page, proxyUrl, retries - 1);
    }
    throw error;
  }
}

// 替换原调用
await useProxyWithRetry(page, proxyUrl);

6. 考虑使用浏览器池

频繁启动关闭浏览器会增加连接异常概率,可使用puppeteer-cluster复用浏览器实例,提升稳定性和性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 04:42:02