使用 Promise.all 通过 Puppeteer 实现某种多线程

Ars*_*son 5 javascript multithreading async-await puppeteer

我想咨询一下可能的思路。

编写抓取机器人或在网站上执行某些活动的机器人(使用 Puppeteer),我经常需要“某种”多线程功能,以便能够同时访问多个页面并对它们执行某些操作,最好是同时进行时间也是如此。

为此,我按照以下模式使用 Promise.all():

const runInParallel = async(len) => {

    // create an array with a number of elements corresponding to required number of functions
    // to be performed at the same time 
 
    // these can also be URLs if I happen to know them beforehand 

    const iterations = [...Array(len).keys()]; 

    // create an array of promises that run in parallel 
    return await Promise.all(
        iterations.map(async i => {
            try {
                // use puppeteer to access a page, get data or perform certain actions 
                await scrape(); 
            } catch (e) {
                // handle error 
            } finally {
                // close page and browser
            }
        })
    ); 
}
Run Code Online (Sandbox Code Playgroud)

通常,上面的内容被包装在另一个循环中,其中每次迭代在开始下一次迭代之前等待所有要解决/拒绝的承诺,这样我可以同时访问多个页面,等待所有操作完成对所有这些进行处理,然后进入下一个迭代,重复该过程。

我想知道这种方法有什么缺点,以及是否有更好的替代方案来同时访问多个页面以抓取数据或对它们执行某些操作。

sas*_*hee 2

这种方法有效,并且它确实实现了真正的多线程,而不仅仅是“某种程度”。Puppeteer 在单独的进程中启动 Chromium,并且它们都同时运行。

不过要注意内存问题。我尝试了类似的策略,发现启动 2-3 个浏览器会消耗我机器中的所有内存,并且一切都会停止。您可能想要限制并行执行的抓取作业数量。这是我写的一篇文章如何解决这个问题

您还可以通过仅使用 1 个浏览器实例但不同的页面来优化此工作流程。这样,scrape调用可以打开一个新选项卡,进行抓取,然后关闭它,并且多个抓取作业可以共享同一个浏览器。