私は puppeteer を使用していくつかのページをスクレイピングしていますが、ノードアプリの本番環境でこれを管理する方法に興味があります。 1日に最大500,000ページをスクレイピングしますが、これらのスクレイプジョブはランダムな間隔で発生するため、1つのキューでは処理できません。
私が疑問に思っているのは、ブラウザを開いてページに移動し、各ジョブの間にブラウザを閉じる方が良いですか?私はそれがはるかに遅いと思いますが、おそらくメモリをより良く処理しますか?
または、アプリの起動時に1つのグローバルブラウザを開き、ページに移動して、完了したらそのページをダンプする方法があります(たとえば、クロムですべてのタブを閉じますが、クロムを閉じません)必要なときに新しいページを再度開きますか?この方法は高速に思えますが、潜在的に多くのメモリを使い果たす可能性があります。
特に実稼働環境でこのライブラリを使用したことがないため、注意すべき点があるかどうかはわかりません。
1日あたり500,000ページをスクレイピングしている場合(0.1728秒ごとに約1ページ)、各ページの新しいブラウザセッションを開くのではなく、既存のブラウザセッションで新しいページを開くことをお勧めします。
次の方法を使用して、 Page を開閉できます。
const page = await browser.newPage();
await page.close();
プロジェクトに1つの Browser を使用することに決めた場合、エラー処理手順を実装して、プログラムがクラッシュした場合に新しい Page 、 Browser 、または BrowserContext 。
おそらく、独立したブラウザで複数のChromiumインスタンスのプールを作成する必要があります。その利点は、1つのブラウザーがクラッシュした場合、他のすべてのジョブが実行を継続できることです。 1つのブラウザ(複数ページ)の利点は、わずかなメモリと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);
})();
_
別のタスクを実行する必要がある場合は、関数を直接キューに入れることもできます。通常、cluster.close()
を介して完了したらクラスターを閉じますが、クラスターを開いたままにしておくこともできます。 repository にリクエストが入ったときにデータを取得するクラスターの別の例を見つけます。