【问题标题】:Multiple separate browser with one tab each - simultaneous interaction with elements on pages (puppeteer headless)多个单独的浏览器,每个浏览器都有一个选项卡 - 与页面上的元素同时交互(木偶无头)
【发布时间】:2020-06-09 09:14:01
【问题描述】:

在 ubuntu 服务器上使用 Node.js、Chrome 和 puppeteer 作为 headless,我正在抓取几个不同的网站。偶尔的任务之一是与加载的页面进行交互(单击链接以打开另一个页面,然后可能再次单击以接受条款等)。

我可以很好地完成这一切,但我试图了解如果我同时打开多个页面并尝试同时与不同加载的页面交互(重叠时间),它将如何工作。

为了形象化这一点,我在想用户将如何做同样的工作。他们必须打开多个浏览器窗口,打开页面并在它们之间切换才能查看,然后单击链接。

但是使用 puppeteer,我们有单独的浏览器对象,我们不需要看到窗口或页面就知道点击哪里。我们可以通过浏览器对象遍历它,然后在不看(无头)的情况下单击所需的元素。

我想我应该能够同时处理多个页面,只要我有可用的 CPU 和内存来处理它们。

有没有人有过 puppeteer 同时与多个网站交互的经验?有什么需要注意的吗?

【问题讨论】:

  • 我试图同时用 puppeteer 抓取页面,但我很快就耗尽了内存。我用˙forEach`打开了很多网址,它立即杀死了我的电脑????。然后我每次尝试大量 10 个 url,这都不好:很多尝试导致超时。所以现在我依次浏览了 3000 多个网址,但仍然存在一些问题,例如:stackoverflow.com/questions/62220867/…。如果你的 ubuntu 服务器背后有一个庞大的硬件,你可能会成功。
  • 我正在考虑下次使用puppeteer-cluster
  • 谢谢@theDavidBarton,我会研究 puppeteer-cluster。我看到 puppeteer-cluster 的作者发布了一个答案。我也会在那里回复。

标签: javascript node.js google-chrome web-scraping puppeteer


【解决方案1】:

这是图书馆puppeteer-cluster(我是作者)正在解决的问题。它允许您构建一个页面池(或浏览器)以在其中使用和运行任务。

您可以在the repository(以及stackoverflow)中找到几个通用代码示例。让我通过一个示例来解决您运行不同任务的特定用例。

代码示例

以下代码创建了两个任务:

  • crawl:打开页面并提取 URL 以启动第二个任务
  • screenshot:对提取的 URL 进行截图

通过将crawl 任务与 URL 进行排队来启动该过程。

const { Cluster } = require('puppeteer-cluster');

(async () => {
    const cluster = await Cluster.launch({ // use four pages in parallel
        concurrency: Cluster.CONCURRENCY_PAGE,
        maxConcurrency: 4,
    });

    // We define two tasks
    const crawl = async ({ page, data: url }) => {
        await page.goto(url);
        const extractedURL = /* ... */; // extract an URL (or multiple) from the document somehow
        cluster.queue(extractedURL, screenshot);
    };

    const screenshot = async ({ page, data: url }) => {
        await page.goto(url);
        await page.screenshot();
    };

    // Crawl some pages
    cluster.queue('https://www.google.com/', crawl);
    cluster.queue('https://github.com/', crawl);

    // Wait until everything is done and close the cluster
    await cluster.idle();
    await cluster.close();
})();

这是一个最小的例子。我省略了错误处理、监控和设置选项。

【讨论】:

  • 感谢@Thomas-dondorf。这看起来像一个非常有用的库。感谢您在创建和发布它时所花费的时间和精力。我将添加它并对其进行测试并报告。
【解决方案2】:

我通常可以在 4GB 的服务器上运行 5 个左右的浏览器,如果您只是从队列中弹出 url,这非常简单:

const puppeteer = require('puppeteer');

let queue = [
  'http://www.amazon.com',
  'http://www.google.com',
  'http://www.fabebook.com',
  'http://www.reddit.com',
]

const doQueue = async () => {
  const browser = await puppeteer.launch()
  const page = await browser.newPage()
  let url
  while(url = queue.shift()){
    await page.goto(url)
    console.log(await page.title())
  }
  await browser.close()
}

[1,2,3].map(() => doQueue())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-09
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 2016-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多