1

私は自分の個人的な使用のために C# で Web クローラーを作成しています。その主な目的は、クロールする Web ページから画像をダウンロードすることです。ダウンロードした画像以外には、Web ページからのデータは保存されません。

クローラーがアクセスしたすべての URL のリテラル文字列をリストに格納するロジックが用意されています。短いクロール セッションではこれで十分ですが、クローラーが何万もの URL で満たされたリストでルックアップを行っている長いセッションでは、これがボトルネックになり始めると思います。また、クロール待ちの URL のキューに重複する URL がないように、URL キューでルックアップも行っています。

私の質問は2つの部分に分かれています:

1) 現時点では、クロール セッション間でデータを保存していませんが、これで問題ありません。クローラーの実行中に、単純な文字列のリストよりも、既にアクセスした URL を保存するより良い方法はありますか?

2) 複数のセッションで使用するためにデータをディスクに永続的に保存することを開始する場合、この場合、訪問した URL をどのように保存することをお勧めしますか?

4

1 に答える 1

3

クローラーのクロール速度に大きく依存します。シングル スレッドのクローラーを使用している場合、平均して 1 秒あたり 1 ページよりも優れた処理を行うことはできません。したがって、 HashSetを使用して、アクセスした URL を保存できます。または、アクセスした URL に関する情報を保存する場合は、 を使用できますDictionary<string, UrlInfo>。ここで、UrlInfoは、アクセスした各 URL について保持したい情報を含む、定義したクラスです。

1 日あたり 86,400 秒で、HashSetorDictionaryはかなりの数日分のデータを保存します。

しかし、おそらく同じ画像を複数回ダウンロードしたくないでしょう。したがって、私が「オフライン」または「クロール - プロセス - クロール」モデルと呼んでいるものの方が適しているかもしれません。仕組みは次のとおりです。

クロールを開始すると、特定した数千のページにアクセスします。ページをダウンロードし、リンクを抽出して、それらのリンクをログ ファイルに書き込みます。画像が見つかったら、それらをダウンロードして保存します。アクセスするすべてのページもファイルに書き込まれます。

これらのページにアクセスし終わったら、クローラーを停止します。アクセスしたページと見つけたリンクの 2 つのリストがファイルに保存されました。

訪問したリンクを並べ替えて、以前に訪問したページのリストとマージします。そのファイルは、時間の経過とともにかなり大きくなる可能性があります。

抽出したリンクのリストを並べ替え、重複を削除します。次に、これらのリンクを、既にアクセスしたページのリストと照合します。これはマージで最も簡単です。リンクが既にアクセスされている場合は、破棄します。それ以外の場合は、次のクロール セッションで使用されるファイルに書き込みます。

これは単純なデータベースの場合は簡単ですが、データベースが非常に大きくなることに注意してください。データベースを使用すると、クロール-プロセス-クロールする必要はありません。代わりに、抽出した各リンクをデータベースに対してチェックし、すぐに保存または破棄することができます。

ただし、データベースにかなりの負荷がかかることを理解しておいてください。クロールに関する私の経験では、平均して、Web ページには 100 を超えるリンクが含まれています (<a href="...">つまり、画像は含まれません。シングル スレッドのクローラーで、少なくとも 1 秒間に 100 回、そのデータベースにアクセスすることになります。

遭遇するもう 1 つの問題は、見つけたすべての URL にアクセスできるわけではないということです。時間が経つにつれて、平均的な Web ページから抽出した 100 個のリンクのうち、10 個が今まで見たことのない新しいリンクであることがわかりました。つまり、読んだページごとに、まだ読んでいないページがさらに 10 ページ見つかります。最終的には、画像に誘導する可能性が低い URL を除外する何らかの方法が必要になります。

アクセスした URL を追跡するもう 1 つの方法は、ブルーム フィルターを使用することです。私はこれらを Web クローラーで非常に効果的に使用しました。

于 2013-04-23T14:01:15.733 に答える