如何使用 user-data-dir 但用于多个 puppeteer 窗口

DUM*_*SER 3 javascript automation google-chrome node.js puppeteer

所以我想做的是用我的谷歌个人资料打开 puppeteer 窗口,但我想要的是多次执行它,我的意思是 2-4 个窗口但具有相同的个人资料 - 这可能吗?当我这样做时,我收到此错误:

(node:17460) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
[45844:13176:0410/181437.893:ERROR:cache_util_win.cc(20)] Unable to move the cache: Access is denied. (0x5)
Run Code Online (Sandbox Code Playgroud)
(node:17460) UnhandledPromiseRejectionWarning: Error: Failed to launch the browser process!
[45844:13176:0410/181437.893:ERROR:cache_util_win.cc(20)] Unable to move the cache: Access is denied. (0x5)
Run Code Online (Sandbox Code Playgroud)

the*_*ton 7

注意:注释中已经指出,但示例中存在语法错误。启动应该如下所示:

const browser = await puppeteer.launch({
  headless: false,
  args: ['--user-data-dir=C:\\Users\\USER\\AppData\\Local\\Google\\Chrome\\User Data']
});
Run Code Online (Sandbox Code Playgroud)

该错误是由于您同时启动多个浏览器实例,因此配置文件目录将被锁定,并且无法移动以供 puppeteer 重用。

您应该避免同时使用相同的用户数据目录启动 chromium 实例。

可能的解决方案

  • 使打开的窗口按顺序排列,如果您只有几个窗口,这会很有用。例如:
const firstFn = async () => await puppeteer.launch() ...
const secondFn = async () => await puppeteer.launch() ...

(async () => {
  await firstFn()
  await secondFn()
})();
Run Code Online (Sandbox Code Playgroud)
  • 将 user-data-dir 创建为 等副本User Data1User Data2 User Data3以避免 puppeteer 复制它们时发生冲突。这可以使用 Node 的模块即时完成fs,甚至可以手动完成(如果您不需要大量实例)。
  • 考虑重用 Chromium 实例(如果您的用例允许),browser.wsEndpoint如果puppeteer.connect您需要使用相同的用户数据目录打开数千个页面,这可能是一个解决方案。
    注意:这对于性能来说是最好的,因为只会启动一个浏览器,然后您可以根据需要在循环for..of或常规循环中打开任意数量的页面(单独使用可能会导致副作用),例如:forforEach
const puppeteer = require('puppeteer')
const urlArray = ['https://example.com', 'https://google.com']

async function fn() {
  const browser = await puppeteer.launch({
    headless: false,
    args: ['--user-data-dir=C:\\Users\\USER\\AppData\\Local\\Google\\Chrome\\User Data']
  })
  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) // it can be wrapped in a retry function to handle flakyness

      // doing cool things with the DOM
      await page.screenshot({ path: `${url.replace('https://', '')}.png` })
      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()
Run Code Online (Sandbox Code Playgroud)