web-dev-qa-db-ja.com

メモリとパフォーマンスのための操り人形師の管理

私は puppeteer を使用していくつかのページをスクレイピングしていますが、ノードアプリの本番環境でこれを管理する方法に興味があります。 1日に最大500,000ページをスクレイピングしますが、これらのスクレイプジョブはランダムな間隔で発生するため、1つのキューでは処理できません。

私が疑問に思っているのは、ブラウザを開いてページに移動し、各ジョブの間にブラウザを閉じる方が良いですか?私はそれがはるかに遅いと思いますが、おそらくメモリをより良く処理しますか?

または、アプリの起動時に1つのグローバルブラウザを開き、ページに移動して、完了したらそのページをダンプする方法があります(たとえば、クロムですべてのタブを閉じますが、クロムを閉じません)必要なときに新しいページを再度開きますか?この方法は高速に思えますが、潜在的に多くのメモリを使い果たす可能性があります。

特に実稼働環境でこのライブラリを使用したことがないため、注意すべき点があるかどうかはわかりません。

7
jeremywoertink

1日あたり500,000ページをスクレイピングしている場合(0.1728秒ごとに約1ページ)、各ページの新しいブラウザセッションを開くのではなく、既存のブラウザセッションで新しいページを開くことをお勧めします。

次の方法を使用して、 Page を開閉できます。

const page = await browser.newPage();
await page.close();

プロジェクトに1つの Browser を使用することに決めた場合、エラー処理手順を実装して、プログラムがクラッシュした場合に新しい PageBrowser 、または BrowserContext

5
Grant Miller

おそらく、独立したブラウザで複数の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 にリクエストが入ったときにデータを取得するクラスターの別の例を見つけます。

7
Thomas Dondorf