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

how to use user-data-dir but for multiple puppeteer windows

所以我想做的是用我的 google 个人资料打开 puppeteer window,但我想做的是多次,我的意思是 2-4 windows 但具有相同的配置文件 - 这可能吗?我在执行此操作时遇到此错误:

(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)
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    headless:false,
    '--user-data-dir=C:\Users\USER\AppData\Local\Google\Chrome\User Data',
  );
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({ path: 'example.png' });
        
  await browser.close();
})();

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

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

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

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

可能的解决方案

  • 使打开的 windows 顺序,如果你只有几个,会很有用。例如:
const firstFn = async () => await puppeteer.launch() ...
const secondFn = async () => await puppeteer.launch() ...

(async () => {
  await firstFn()
  await secondFn()
})();
  • 创建用户数据目录的副本,如 User Data1User Data2 User Data3 等,以避免在 puppeteer 复制它们时发生冲突。这可以使用 Node 的 fs 模块即时完成,甚至可以手动完成(如果您不需要很多实例)。
  • 考虑使用 browser.wsEndpoint and puppeteer.connect 重用 Chromium 实例(如果您的用例允许),如果您需要打开数千个具有相同用户数据目录的页面,这可能是一个解决方案。
    注意: 这是性能最好的,因为只会启动一个浏览器,然后您可以在 for..of 或常规 for 循环中打开尽可能多的页面你想要的(单独使用 forEach can cause side effects),例如:
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()