jer*_*ink 7 node.js web-scraping puppeteer
我正在使用puppeteer抓取一些页面,但是我很好奇如何在生产中为节点应用程序管理此页面。我一天最多要抓取500,000页,但是这些抓取作业将以随机的间隔发生,因此我无法耕种一个队列。
我想知道的是,打开浏览器,转到页面,然后在每个作业之间关闭浏览器会更好吗?我以为会慢很多,但也许可以更好地处理内存?
还是在应用启动时打开一个全局浏览器,然后转到页面,并用某种方法转储该页面(例如,关闭chrome中的所有标签,而不关闭chrome),然后在需要时重新打开一个新页面?这样看来会更快,但可能会消耗大量内存。
我从来没有使用过这个库,尤其是在生产环境中,所以我不确定是否需要注意。
您可能希望使用独立的浏览器创建多个Chromium实例的池。这样做的好处是,当一个浏览器崩溃时,所有其他作业都可以继续运行。一个浏览器(具有多个页面)的优势是内存和CPU优势较小,并且cookie在页面之间共享。
puppteer-cluster库(免责声明:我是作者)为您创建了一个浏览器或页面池。它负责您的创建,错误处理,浏览器重启等工作。因此,您只需将作业/ URL排入队列,库就可以处理其他所有事情。
const { Cluster } = require('puppeteer-cluster');
(async () => {
const cluster = await Cluster.launch({
concurrency: Cluster.CONCURRENCY_BROWSER, // use one browser per worker
maxConcurrency: 4, // cluster with four workers
});
// Define a task to be executed for your data (put your "crawling code" in here)
await cluster.task(async ({ page, data: url }) => {
await page.goto(url);
// ...
});
// Queue URLs when the cluster is created
cluster.queue('http://www.google.com/');
cluster.queue('http://www.wikipedia.org/');
// Or queue URLs anytime later
setTimeout(() => {
cluster.queue('http://...');
}, 1000);
})();
Run Code Online (Sandbox Code Playgroud)
如果您有其他任务要做,您还可以直接将函数排队。通常,您通过完成后会关闭集群cluster.close(),但是您可以随意让它保持打开状态。您找到了另一个示例,该示例是在存储库中有请求时获取数据的集群。
Other performance related articles are,
This is another example using puppeteer and generic-pool libraries.
const puppeteer = require('puppeteer');
const genericPool = require("generic-pool");
async function createChromePool() {
const factory = {
create: function() {
//open an instance of the Chrome headless browser - Heroku buildpack requires these args
return puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox', '--ignore-certificate-errors'] });
},
destroy: function(client) {
//close the browser
client.close();
}
};
const opts = { max: 1, acquireTimeoutMillis: 120000, priorityRange: 3};
global.chromepool = genericPool.createPool(factory, opts);
global.chromepool.on('factoryCreateError', function(err){
debug(err);
});
global.chromepool.on('factoryDestroyError', function(err){
debug(err);
});
}
async function destroyChromePool() {
// Only call this once in your application -- at the point you want to shutdown and stop using this pool.
global.chromepool.drain().then(function() {
global.chromepool.clear();
});
}
Run Code Online (Sandbox Code Playgroud)
如果每天要抓取500,000页(每0.1728秒大约一页),那么我建议您在现有的浏览器会话中打开一个新页面,而不是为每个页面打开一个新的浏览器会话。
您可以使用以下方法打开和关闭页面:
const page = await browser.newPage();
await page.close();
Run Code Online (Sandbox Code Playgroud)
如果您决定为项目使用一个浏览器,那么我将确保实施错误处理过程,以确保如果程序崩溃,则在创建新的Page,Browser或BrowserContext时停机时间最少。
| 归档时间: |
|
| 查看次数: |
5423 次 |
| 最近记录: |