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

Render部署Puppeteer服务遇Target.createTarget错误的解决办法

在Render平台部署带Puppeteer的Node.js服务器时遇到ProtocolError问题

我在Render平台部署配置了Puppeteer的Node.js服务器,已经编写了适配Puppeteer的Dockerfile,但部署后出现ProtocolError: Protocol error (Target.createTarget): Target closed错误,即使增大所有超时参数也无法解决。以下是相关代码、Dockerfile及错误日志,求解决方案:

相关代码

async function getResults(lnk) {
  const results = [];
  const timeFrames = [1, 5, 15];

  
  const browser = await puppeteer.launch({
    headless: 'new',
    args: [
      "--disable-setuid-sandbox",
      "--no-sandbox",
      "--single-process",
      "--no-zygote",
    ],
    protocolTimeout: 240000,// 60秒

    executablePath:
      process.env.NODE_ENV === "production"
        ? process.env.PUPPETEER_EXECUTABLE_PATH
        : puppeteer.executablePath(),
  });
  const page = await browser.newPage();
  // await page.setDefaultNavigationTimeout(0);

  for (const i of timeFrames) {
    const page = await browser.newPage();
    const url = `${lnk}?timeFrame=${i * 60}`;
    console.log(`获取中: ${url}`);

    await page.goto(url, { waitUntil: ["domcontentloaded"],timeout: 100000  });
    await page.waitForSelector("section.forecast-box-graph .title",{timeout: 10000});
    // await page.waitForSelector('h1.main-title.js-main-title');


    const status = await page.$eval(
      "section.forecast-box-graph .title",
      (el) => el.textContent
    );
    const Bank_Name = await page.$eval("h1.main-title.js-main-title", (el) =>
      el.textContent.trim()
    );
    results.push(status);

    await page.close();
  }

  await browser.close();
  results.push(lnk.split("/").pop().split("-").join(" "));

  return results;
}

async function scrape() {
  while(true){
    for (const lnk of Link_Lst) {
      const results = await getResults(lnk);
      console.log("获取结果:",results);
      if(results.includes("Strong Sell")){
        console.log("触发");
        if (Sell_) {
              sendAlertToTG(`警报:银行 ${results.slice(-1)} - "强力卖出"`);
              Sell_ = false;
            }
      }
      if(results.includes("Strong Buy")){
        if (Buy_) {
              sendAlertToTG(`警报:银行 ${results.slice(-1)} - "强力买入"`);
              Buy_ = false;
            }    
          }
  

    }
  
    console.log("\n\n等待___10___秒");
    waitBeforeNextIteration(10000);
  
  }
}
function waitBeforeNextIteration(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
scrape();

Dockerfile

FROM ghcr.io/puppeteer/puppeteer:20.1.2


ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm ci
COPY . .
CMD [ "node", "index.js" ]

错误日志

[21:40:0508/181117.410689:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:18 PM  [21:46:0508/181118.422748:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:18 PM  [21:46:0508/181118.423699:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:18 PM  [21:40:0508/181118.455193:ERROR:bus.cc(399)] 无法连接到总线:无法解析服务器地址:未知地址类型(有效类型示例为 "tcp" 和 UNIX 下的 "unix")
May 8 09:11:18 PM  [21:40:0508/181118.455257:ERROR:bus.cc(399)] 无法连接到总线:无法解析服务器地址:未知地址类型(有效类型示例为 "tcp" 和 UNIX 下的 "unix")
May 8 09:11:18 PM  [21:21:0508/181118.604874:ERROR:system_network_context_manager.cc(765)] 单进程模式下无法使用 V8 代理解析器。
May 8 09:11:19 PM  [21:40:0508/181119.040595:ERROR:bus.cc(399)] 无法连接到总线:无法解析服务器地址:未知地址类型(有效类型示例为 "tcp" 和 UNIX 下的 "unix")
May 8 09:11:19 PM  [21:40:0508/181119.041267:ERROR:bus.cc(399)] 无法连接到总线:无法解析服务器地址:未知地址类型(有效类型示例为 "tcp" 和 UNIX 下的 "unix")
May 8 09:11:19 PM  [21:21:0508/181119.042829:ERROR:system_network_context_manager.cc(765)] 单进程模式下无法使用 V8 代理解析器。
May 8 09:11:19 PM  
May 8 09:11:19 PM  DevTools 监听 ws://127.0.0.1:36065/devtools/browser/534507b8-8bff-4967-907a-a39d4897f259
May 8 09:11:21 PM  [21:93:0508/181121.222028:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:21 PM  [21:93:0508/181121.222132:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:21 PM  [21:93:0508/181121.222220:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:21 PM  [21:93:0508/181121.222285:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:21 PM  [21:93:0508/181121.222372:ERROR:bus.cc(399)] 无法连接到总线:无法连接到套接字 /run/dbus/system_bus_socket: 没有该文件或目录
May 8 09:11:22 PM  [0508/181122.090203:ERROR:file_io_posix.cc(144)] 打开 /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq: 没有该文件或目录 (2)
May 8 09:11:22 PM  [0508/181122.090313:ERROR:file_io_posix.cc(144)] 打开 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq: 没有该文件或目录 (2)
May 8 09:11:22 PM  /usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:61
May 8 09:11:22 PM          _Callback_error.set(this, new Errors_js_1.ProtocolError());
May 8 09:11:22 PM                                    ^
May 8 09:11:22 PM  
May 8 09:11:22 PM  ProtocolError: Protocol error (Target.createTarget): Target closed
May 8 09:11:22 PM      at new Callback (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:61:35)
May 8 09:11:22 PM      at CallbackRegistry.create (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:106:26)
May 8 09:11:22 PM      at Connection._rawSend (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:216:26)
May 8 09:11:22 PM      at Connection.send (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Connection.js:210:21)
May 8 09:11:22 PM      at CDPBrowser._createPageInContext (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Browser.js:273:94)
May 8 09:11:22 PM      at CDPBrowserContext.newPage (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Browser.js:541:78)
May 8 09:11:22 PM      at CDPBrowser.newPage (/usr/src/app/node_modules/puppeteer-core/lib/cjs/puppeteer/common/Browser.js:267:78)
May 8 09:11:22 PM      at getResults (/usr/src/app/index.js:79:32)
May 8 09:11:22 PM      at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
May 8 09:11:22 PM      at async scrape (/usr/src/app/index.js:174:23)
May 8 09:11:22 PM  
May 8 09:11:22 PM  Node.js v18.16.0
解决方案

1. 移除单进程模式参数

错误日志明确提示单进程模式下无法使用 V8 代理解析器,当前启动参数里的--single-process和--no-zygote在Render容器环境中会导致Chrome启动异常或连接中断。修改Puppeteer启动配置:

const browser = await puppeteer.launch({
  headless: 'new',
  args: [
    "--disable-setuid-sandbox",
    "--no-sandbox",
    "--disable-dev-shm-usage", // 解决容器共享内存不足问题
    "--disable-gpu", // 禁用GPU加速,容器环境无需
    "--window-size=1920,1080" // 固定窗口大小,避免布局异常
  ],
  protocolTimeout: 240000,
  executablePath:
    process.env.NODE_ENV === "production"
      ? process.env.PUPPETEER_EXECUTABLE_PATH
      : puppeteer.executablePath(),
});

2. 修复代码中页面重复创建问题

getResults函数中先创建了一个未使用的page,循环内又重复创建同名变量,虽不直接引发错误,但会浪费资源。可改为循环复用单个页面,或删除多余创建:

async function getResults(lnk) {
  const results = [];
  const timeFrames = [1, 5, 15];

  const browser = await puppeteer.launch({/* 修改后的配置 */});
  // 删除多余的页面创建:const page = await browser.newPage();

  for (const i of timeFrames) {
    const page = await browser.newPage();
    const url = `${lnk}?timeFrame=${i * 60}`;
    console.log(`获取中: ${url}`);

    await page.goto(url, { waitUntil: "networkidle2", timeout: 100000 }); // 改用networkidle2等待页面加载完成
    await page.waitForSelector("section.forecast-box-graph .title", { timeout: 30000 }); // 延长超时时间

    const status = await page.$eval(
      "section.forecast-box-graph .title",
      (el) => el.textContent
    );
    const Bank_Name = await page.$eval("h1.main-title.js-main-title", (el) =>
      el.textContent.trim()
    );
    results.push(status);

    await page.close();
  }

  await browser.close();
  results.push(lnk.split("/").pop().split("-").join(" "));

  return results;
}

3. 调整Dockerfile用户权限

Render容器环境默认可能禁止root用户运行Chrome,修改Dockerfile切换到非root用户:

FROM ghcr.io/puppeteer/puppeteer:20.1.2

ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
    PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm ci
COPY . .

# 切换到puppeteer用户运行
USER puppeteer

CMD [ "node", "index.js" ]

4. 增加错误捕获机制

添加try-catch块避免单个链接错误导致整个循环崩溃,同时输出详细错误信息:

async function getResults(lnk) {
  const results = [];
  const timeFrames = [1, 5, 15];
  let browser;

  try {
    browser = await puppeteer.launch({/* 修改后的配置 */});

    for (const i of timeFrames) {
      let page;
      try {
        page = await browser.newPage();
        const url = `${lnk}?timeFrame=${i * 60}`;
        console.log(`获取中: ${url}`);

        await page.goto(url, { waitUntil: "networkidle2", timeout: 100000 });
        await page.waitForSelector("section.forecast-box-graph .title", { timeout: 30000 });

        const status = await page.$eval(
          "section.forecast-box-graph .title",
          (el) => el.textContent
        );
        const Bank_Name = await page.$eval("h1.main-title.js-main-title", (el) =>
          el.textContent.trim()
        );
        results.push(status);
      } catch (pageErr) {
        console.error(`处理链接 ${lnk} 时间帧 ${i} 时出错:`, pageErr);
        results.push(`获取失败: ${pageErr.message}`);
      } finally {
        if (page) await page.close();
      }
    }
  } catch (browserErr) {
    console.error(`启动浏览器处理链接 ${lnk} 时出错:`, browserErr);
  } finally {
    if (browser) await browser.close();
  }

  results.push(lnk.split("/").pop().split("-").join(" "));
  return results;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:28:09