500万のWebページをスクレイピングする最も効率的な(時間、コスト)方法は?


8

結果のデータをスクレイピングして解析し、データベースに保存する必要があるWebページのリストがあります。合計は約5,000,000です。

これにアプローチする最良の方法の私の現在の想定は、最大100のEC2インスタンスをデプロイし、各インスタンスに50,000ページを提供してスクレイピングし、それを実行したままにし、プロセスが完了したらデータベースをマージすることです。実行には約1日かかります(各ページの読み込み、解析、保存に600ミリ秒)。

限られた時間内に大量のページスクレイピングを行った経験がある人はいますか?私は以前(1.5m)に多数を行ったことがありますが、それは単一のマシンからのものであり、完了するまでに1週間ほどかかりました。

私の状況のボトルネックはページのダウンロードであり、解析は2ミリ秒しかかからないので、ページのダウンロードプロセスを合理化できるものが私が探しているものです。


Webページのリストを言うとき、これはプレーンなWebページですか、それともフォーラムなどのサイト全体ですか?また、
平準化

私はこの回答が私に関連している複数のインスタンスがあります。質問のために、簡単に視覚化できる任意の図を示し、Webページのタイプはさまざまですが、質問では、フォーラムが削られていると想定できます。もし良かったら。サイトがスクレイピングを許可するかどうかは問題ではありません(とにかく質問について)
sam

Webページのタイプに関するポイントを明確にするために:各Webページは他から独立しているため、任意の順序でスクレイピングでき、他のスクレイピングに依存することはありません。順方向、逆方向、無作為化することができ、それは問題ではありません。
sam

そうですか。EC2がダウンロードをどのように処理するかはわかりませんが、より経験豊富なSFユーザーにはアイデアがあるかもしれません。また、オフトピックが、これはあるMinecraftForumsからcitricsquid?それはかなり...ユニークな...名前です。
tombull89

I.あるmmhmm
SAM

回答:


7

ダウンロード時間(したがって帯域幅の使用量)が制限要因であるという仮定に基づいて、次のことを提案します。

まず、m1.largeインスタンスを選択します。I / Oパフォーマンス(帯域幅を含む)の3つの「レベル」のうち、m1.largeおよびm1.xlargeインスタンスはどちらも「高い」I / Oパフォーマンスを提供します。タスクはCPUバウンドではないため、これらの中で最も安価なものをお勧めします。

次に、インスタンスはどのサイトでもページを提供できるよりもはるかに速くダウンロードできます-特定のインスタンスで一度に1つのページをダウンロードせずに、タスクを同時に実行します-少なくとも20ページを同時に実行できるはずです(ただし、 、おそらく50〜100は問題なく実行できると思います)。(コメントからフォーラムからダウンロードする例を見てみましょう。これは、サーバーの生成に時間がかかる動的ページであり、他のユーザーがそのサイトの帯域幅を使用しているなどです)。インスタンスの帯域幅の制限に達するまで、並行性を増やし続けます。(もちろん、同じサイトに対して複数の同時リクエストを行わないでください)。

パフォーマンスを最大化しようとしている場合は、地理的に適切なゾーンでインスタンスを起動してレイテンシを最小限に抑えることを検討できます(ただし、すべてのURLを地理的に特定する必要があるため、実用的ではない場合があります)。

注意すべき点の1つは、インスタンスの帯域幅が可変であることです。場合によっては、より高いパフォーマンスが得られ、別の場合にはより低いパフォーマンスが得られます。小さいインスタンスでは、物理リンクがより多くのサーバーで共有され、それらのいずれかが使用可能な帯域幅を減少させる可能性があるため、パフォーマンスの変動はより大きくなります。EC2ネットワーク(同じアベイラビリティーゾーン)内のm1.largeインスタンス間では、理論上のギガビットスループットに近いはずです。

一般に、AWSでは、複数の小さなインスタンスではなく、大きなインスタンスを使用する方が効率的です(フェイルオーバーなど、複数のインスタンスが必要な場合を除いて)。

私はあなたの設定が何を必要とするのかわかりませんが、以前にこれを試みたとき(100万から200万のリンク、定期的に更新)、私のアプローチは、リンクが見つかったときに新しいリンクを追加し、プロセスを分岐するリンクのデータベースを維持することでしたページをこすって、解析します。URLが(ランダムに)取得され、データベースで進行中とマークされます。スクリプトはページをダウンロードし、成功した場合は、URLをデータベースにダウンロード済みとしてマークし、ページを解析した別のスクリプトにコンテンツを送信します。新しいリンク見つかったときにデータベースに追加されました。ここでのデータベースの利点は一元化でした。複数のスクリプトがデータベースに同時にクエリを実行でき、(トランザクションがアトミックである限り)各ページが一度だけダウンロードされることが保証されます。

いくつかの追加の注意点-一度に実行できるオンデマンドインスタンスの数には制限があります(20と思います)-これらの制限を超える予定がある場合は、AWSにアカウントの増加をリクエストする必要があります制限。スポットインスタンスを実行し、スポット価格が低いときに数値をスケールアップする方がはるかに経済的です(多分、すべてを整理しておくための1つのオンデマンドインスタンスと、残りのスポットインスタンス)。

時間の方がコストよりも優先度が高い場合、クラスターコンピューティングインスタンスは10 Gbpsの帯域幅を提供し、ダウンロード帯域幅が最大になります。

まとめ:(多くの小さなインスタンスの代わりに)いくつかの大きなインスタンスを試して、各インスタンスで複数の同時ダウンロードを実行します。帯域幅が制限されている場合はインスタンスを追加し、CPU /メモリが制限されている場合は大きなインスタンスに移動します。


4

私たちは同じようなことをしようとしました、そしてここに私の5セントがあります:

  1. 帯域幅の代金を払わずに、2〜3台の安価な非メーター制サーバーを入手します。

  2. asyncoreでpythonを使用します。Asyncoreは古い方法ですが、他の方法よりも速く機能することがわかりました。欠点は、DNSルックアップがブロックされていること、つまり「並列」ではないことです。asyncoreを使用して、1つのXEON 4コア、8 GB RAMを使用して、1MのURLを40分間スクレイピングすることができました。サーバーの負荷平均は4未満でした(4コアにとっては優れています)。

  3. asyncoreが気に入らない場合は、geventを試してください。DNSノンブロッキングも行います。geventを使用して、1Mは同じハードウェアで約50分間ダウンロードされました。サーバーの平均負荷は非常に大きかった。

grequests、curl、liburl / liburl2などの多くのPythonライブラリをテストしましたが、Twistedはテストしいません

  1. PHP + curl +いくつかのプロセスをテストしましたが、約1時間は機能しましたが、サーバーの平均負荷は巨大でした。

私の経験では、「非測定」とは通常、「気分が良ければ遮断する」という意味です。
ceejayoz

私の経験では、「非従量制」とは100 MBit程度に制限されることを意味します
Nick
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.