Puppeteer:浏览器断开连接后,Chromium 实例在后台保持事件状态

标签 puppeteer chromium

我的环境

  • puppeteer 版本:3.1.0
  • 平台/操作系统版本:Windows 10
  • Node.js 版本:12.16.1

  • 我的问题是:

    我有一个 for...of使用 puppeteer 循环访问 3000 多个 url。我用 puppeteer.connectwsEndpoint所以我可以重用一个浏览器实例。每次访问后我都会断开连接并关闭选项卡。
  • 前 100 个网址 page.goto立即打开网址,
  • 100 以上 page.goto每个 url 使用 2-3 次重试,
  • 300 以上 page.goto每个 url 使用 5-8 次重试,
  • 超过 500 我得到 TimeoutError: Navigation timeout of 30000 ms exceeded每时每刻。

  • 我检查了 Windows 任务管理器,发现有数百个 Chromium 实例在后台运行,每个实例使用 80-90MB 的内存和 1-2% 的 CPU。

    问题

    如何终止我已经与 browser.disconnect 断开连接的 Chromium 实例真的?

    示例脚本

    const puppeteer = require('puppeteer')
    const urlArray = require('./urls.json') // contains 3000+ urls in an array
    
    
    async function fn() {
      const browser = await puppeteer.launch({ headless: true })
      const browserWSEndpoint = await browser.wsEndpoint()
    
      for (const url of urlArray) {
        try {
          const browser2 = await puppeteer.connect({ browserWSEndpoint })
          const page = await browser2.newPage()
          await page.goto(url) // in my original code it's also wrapped in a retry function
    
          // doing cool things with the DOM
    
          await page.goto('about:blank') // because of you: https://github.com/puppeteer/puppeteer/issues/1490
          await page.close()
          await browser2.disconnect()
        } catch (e) {
          console.error(e)
        }
      }
      await browser.close()
    }
    fn()
    

    错误

    通常的 puppeteer 超时错误。
    TimeoutError: Navigation timeout of 30000 ms exceeded
        at C:\[...]\node_modules\puppeteer\lib\LifecycleWatcher.js:100:111
      -- ASYNC --
        at Frame.<anonymous> (C:\[...]\node_modules\puppeteer\lib\helper.js:94:19)
        at Page.goto (C:\[...]\node_modules\puppeteer\lib\Page.js:476:53)
        at Page.<anonymous> (C:\[...]\node_modules\puppeteer\lib\helper.js:95:27)
        at example (C:\[...]\example.js:13:18)
        at processTicksAndRejections (internal/process/task_queues.js:97:5) {
      name: 'TimeoutError'
    }
    
    

    最佳答案

    最后我能够通过添加 --single-process 来达到预期的结果。和 --no-zygote启动时的参数(+ --no-sandbox 是必需的)。

    正在运行的 Chromium 进程的数量不再呈指数增长,但只有两个实例保持事件状态:其中一个是第一个位置的通常空选项卡,第二个被 puppeteer.connect({ browserWSEndpoint }) 正确重用。 .

    [...]
      const browser = await puppeteer.launch({
        headless: true,
        args: ['--single-process', '--no-zygote', '--no-sandbox']
      })
      const browserWSEndpoint = await browser.wsEndpoint()
    [...]
    
  • --single-process :在与浏览器相同的进程中运行渲染器和插件[source]
  • --no-zygote :禁止使用 zygote 进程来 fork 子进程。相反,子进程将被直接 fork 和执行。请注意, --no-sandbox 也应与此标志一起使用,因为沙箱需要 zygote 才能工作。 [source]
  • 关于Puppeteer:浏览器断开连接后,Chromium 实例在后台保持事件状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62220867/

    相关文章:

    javascript - 使用 puppeteer 或 playwright,有没有办法更新最初在启动方法中传递的参数?

    javascript - Puppeteer:搜索不区分大小写的内部文本

    javascript - puppeteer 师/Node.js : Can I run a script non-stop 24/7?

    google-chrome - Chromium 使用错误的 (?) srcset 和大小

    javascript - Chromium 78 嵌套 iframe 中的指针事件失误

    javascript - 如何将 "hook in"伪装成正在运行的 Chrome 实例/选项卡

    Puppeteer:我怎样才能等到列表关闭?如何等到元素从 DOM 中消失?

    c# - Cef - 上传文件而不显示 OpenFileDialog

    ubuntu - 如何轻松创建 ChromeOS 和 Ubuntu 之间双启动的快捷方式?

    http - 'trk: scheme' 是什么?