我想观察许多产生大量数据的网站。所有这些都使用pupeeter库。 我的想法是在5分钟内运行100个观察100个页面的容器,并重复操作直到上一个容器结束。我将其放入Docker SWARM中,设置了100个副本,并且所有这些都确保在5分钟后恢复观察过程。 SWARM在这里是一个不错的解决方案...它启动了正在观察队列中是否有观察对象的容器。
一个这样的容器需要150-170 MB RAM。如果我们添加所有内容,结果将太多。
一个单独的想法是将所有内容放入一个for循环中。
async function run(url) {
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
var d = Date(Date.now());
console.log("start" + d)
const page = await browser.newPage();
await page.goto("https://webpage.com/" + url, {
waitUntil: 'networkidle2'
});
await page.waitFor(-- - 5 minutes in ms-- - );
const html = await page.content();
await browser.close();
var d = Date(Date.now());
console.log("END" + d)
}
execute_query(function() {
for (var i = 0, len = 100; i < len; i++) {
run(webpage[i]);
}
})
不幸的是,RAM也在这里很快问世。可以优化此代码吗?也许我使用的图书馆有误?
答案 0 :(得分:1)
与其使用大量的Docker容器,不如使用一组浏览器(甚至页面),可能更适合。这样,由于Docker而不会产生内存开销,并且仅运行一个Node.js脚本。
您可能想检查一下库puppeteer-cluster(免责声明:我是作者),库正是这样做的。它可以并行启动浏览器(或页面)并监视结果。
代码示例
这里是一个例子。它并行启动具有100个浏览器的集群,然后定义任务,该任务访问URL并等待5分钟(在执行我想做的其他事情之前)。之后,URL被排队。最后,您要等到任务完成后才能再次关闭集群。
const { Cluster } = require('puppeteer-cluster');
(async () => {
// use 100 browsers
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_BROWSER,
maxConcurrency: 100,
});
// specify what should be done in each browser
await cluster.task(async ({ page, data: url }) => {
await page.goto(url);
// do something...
// wait for 5min
await new Promise(resolve => setTimeout(resolve, 5 * 60 * 1000));
// do more...
});
// queue 100 URLs
for (let i = 0; i < 100; i += 1) {
cluster.queue('http://...');
}
await cluster.idle();
await cluster.close();
})();
在repository中查看更多示例。您还可以将单个任务以及更复杂的对象排队。我本人没有并行运行100个浏览器,但是根据我的经验,Chrome确实能够很好地处理大量浏览器(或页面)。您也可以尝试使用其他concurrency option(通过页面而不是浏览器进行并行化)来进一步降低所需的内存。请记住,即使对于100个浏览器,您仍然需要大量内存。