7


4

次の文はWgetのマニュアルで私の目を引いた

wget --spider --force-html -i bookmarks.html

Wgetが本物のWebスパイダーの機能に近づくには、この機能にもっと多くの作業が必要です。

私は以下のコード行をwgetのspiderオプションに関連したものにしています。

src / ftp.c 780:/ *もし我々がスパイダーモードにいるのなら、本当に何も取り出さないでください。 784:if(opt.spider)889:if(!(cmd)

src / http.c 64:#include "spider.h" 2405:/ *スパイダーモードになっていなければ予備のHEADリクエストをスキップし、2407:if(!opt.spider 2428:if(opt.spider) ただし、スパイダーモードが2570の場合:*スパイダーモード。 * / 2571:それ以外の場合(opt.spider)2661:if(opt.spider)

src / res.c 543:int saved_sp_val = opt.spider; 548:opt.spider = false; 551:opt.spider = saved_sp_val;

src / spider.c 1:/ *スパイダーモードで訪問したURLを追跡します。 37:#include "spider.h" 49:spider_cleanup(void)

src / spider.h 1:/ * spider.cの宣言

src / recur.c 52:#include "spider.h" 279:if(opt.spider)366:|| opt.spider / * opt.recursiveは暗黙的にtrue * / 370:(そうでなければ -  spiderのために不要であるか、または-Rによって拒否されます)375:(opt.spider? "--spider":378 :( opt.delete_after || opt.spider 440:if(opt.spider)

src / options.h 62:ブールスパイダー。 / * Wgetはスパイダーモードになっていますか? * /

src / init.c 238:{"クモ"、

src / main.c 56:#include "spider.h" 238:{"spider"、0、OPT_BOOLEAN、 "spider"、-1}、435:--spiderは何もダウンロードしません。\ n ")、1045 :if(opt.recursive

抽象的ではなく、コードの違いを見たいのですが。 私はコード例が大好きです。

  • WebスパイダーはWgetのスパイダーとコードの違いは何ですか?

4 Answer


33


本物のクモはたくさんの仕事です

WWW全体のためにクモを書くことはかなりの作業です - あなたは以下のような多くの「細部」に注意しなければなりません:

  • 各スパイダコンピュータは、接続帯域幅を効率的に使用するために、数千台のサーバから並列にデータを受信する必要があります。 (非同期ソケット入出力)

  • あなたはWWW上の膨大な量の情報をカバーするために並列にクモになるいくつかのコンピュータを必要とします(クラスタリング;作業の分割)

  • あなたはクモの巣しているウェブサイトに丁寧である必要があります: robots.txtファイルを尊重しなさい。 あまりにも多くの情報をあまり速く取得しないでください:これはサーバに過負荷をかけます。 **本当に必要のないファイルを取得しないでください(例: ISOディスクイメージ。ソフトウェアダウンロードのためのtgzパッケージ…​)。

  • あなたはクッキー/セッションIDを扱う必要があります。多くのサイトはクライアントセッションを識別するためにURLにユニークなセッションIDを付けます。 サイトにアクセスするたびに、新しいセッションIDとページの新しい仮想世界(同じコンテンツを持つ)が表示されます。 そのような問題のために、初期の検索エンジンは動的コンテンツを無視しました。 現代の検索エンジンは、問題とは何か、そしてそれらにどのように対処するのかを学びました。

  • 面倒なデータを検出して無視する必要があります。一見無限の量のデータを提供する接続、または完了するのが遅すぎる接続です。

  • リンクをたどる以外に、 sitemapsを解析してページのURLを取得することもできます。

  • あなたはどの情報があなたにとって重要であり、他のページより頻繁に更新されるように頻繁に変更されるかを評価したいと思うかもしれません。 注:WWW全体のクモには大量のデータが送られてきます。 HTTP HEADリクエストを使用して、ページが変更されたかどうかを推測することができます。

  • 受信以外にも、情報を処理して保存します。 グーグルは各単語についてそれを含むページをリストするインデックスを構築する。 接続するために、別々のストレージコンピュータとインフラストラクチャが必要になる場合があります。 伝統的なリレーショナルデータベースは、WWW全体を格納/索引付けするためのデータ量とパフォーマンス要件に追いついていません。

これは大変な作業です。 しかし、あなたの目標が全WWWを読むよりも控えめであれば、あなたはその部分のいくつかを飛ばすかもしれません。 ウィキなどのコピーをダウンロードしたいだけの場合 あなたはwgetの仕様に降りる。

注:それほど手間がかからないと思われる場合は、グーグルが優れたスパイダーを構築するために(基本的なLinuxカーネルの上に)ほとんどのコンピューティングホイールを再発明した方法についてお読みになることをお勧めします。 たとえあなたがたくさんの角を切ったとしても、それは多くの仕事です。

3つの点についてもう少し技術的なコメントを付け加えさせてください。

パラレル接続/非同期ソケット通信

並列プロセスまたはスレッドで複数のスパイダープログラムを実行できます。 しかし、あなたはあなたのネットワーク接続をうまく利用するために約5000-10000のパラレル接続を必要とします。 そして、この量の並列プロセス/スレッドは、あまりにも多くのオーバーヘッドを生み出します。

より良い解決策は非同期入出力です。ノンブロッキングモードでソケットを開き、epollを使用するか、データを受信した接続だけを処理するためにselectを使用して、単一スレッドで約1000の並列接続を処理します。 Linuxカーネル2.4以降、Linuxはスケーラビリティを非常によくサポートしています(メモリマップファイルも検討することをお勧めします)。これ以降のバージョンでは継続的に改善されています。

注:非同期入出力を使用すると、「高速言語」を使用するよりもはるかに役に立ちます。C言語で書かれた1000個のプロセスを実行するよりも、Perlで書かれた1000個の接続に対してepoll駆動のプロセスを書く方が得策です。 うまくいけば、perlで書かれたプロセスで100Mbの接続を飽和させることができます。

*元の回答から:*このアプローチの欠点は、HTTP仕様を非同期形式で自分で実装する必要があることです(これを行う再利用可能なライブラリはわかりません)。 最新のHTTP / 1.1プロトコルよりも単純なHTTP / 1.0プロトコルを使用する方がはるかに簡単です。 とにかく普通のブラウザではHTTP / 1.1の利点からあなたはおそらく恩恵を受けないでしょう、それでこれはいくらかの開発コストを節約するのに良い場所かもしれません。

  • 5年後の編集:*今日、この仕事を手助けするために利用できるフリー/オープンソース技術がたくさんあります。 私は個人的には node.jsの非同期のhttp://nodejs.org/api/http.html[httpの実装]が好きです。上記の元の段落に記載されている作業。 もちろん、今日ではあなたがあなたのクモに必要な他のコンポーネントのためにすぐに利用可能なたくさんのモジュールもあります。 ただし、サードパーティ製モジュールの品質はかなり異なる場合があります。 あなたが使うものは何でもチェックアウトしなければなりません。 * [Aging info:] *最近、node.jsを使用してクモを書いたところ、リンクおよびデータ抽出のためのHTML処理用のnpmモジュールの信頼性が不十分であることがわかりました。 この仕事のために、私はこの処理を別のプログラミング言語で書かれたプロセスに「アウトソーシング」しました。 しかし、状況は急速に変化しており、このコメントを読むまでに、この問題はすでに過去のものとなっているかもしれません…​

作業を複数のサーバーに分割する

1台のコンピュータがWWW全体を駆逐することはできません。 作業を複数のサーバーに分散し、それらの間で情報を交換する必要があります。 私は各サーバーに特定の「ドメイン名の範囲」を割り当てることをお勧めします。スパイダーコンピュータを参照してドメイン名の中央データベースを保管してください。

受信したWebページからURLをまとめて抽出します。ドメイン名に従って並べ替えます。重複したものを削除し、責任のあるスパイダーコンピュータに送信します。 そのコンピュータで、すでに取得されているURLのインデックスを保持し、残りのURLを取得します。

各スパイダーコンピュータで取得されるのを待っているURLのキューを保持している場合、パフォーマンスのボトルネックはありません。 しかし、これを実装するのはかなりたくさんのプログラミングです。

規格を読む

いくつかの規格(HTTP / 1.x、Robots.txt、Cookie)について言及しました。 それらを読んで実装するために時間をかけてください。 あなたが知っているサイトの例に従うだけなら、あなたは間違いをし(あなたのサンプルに関連しない標準の部分を忘れる)、そしてこれらの追加機能を使うそれらのサイトのためにトラブルを引き起こすでしょう。

HTTP / 1.1標準文書を読むのは面倒です。 誰かが本当にその細部を必要とし、今それを使用するのでしかし、すべての細部がそれに追加されました。


4


私は、コメントの元の作者が何を参照しているのか正確にはわかりませんが、(少なくともあなたが示したものによっては)実行の単一スレッドのみを使用するように思われるので

http://crawler.archive.org/[heritrix]のような「本物の」クモは、クロール速度を最適化するために多くの並列処理とトリックを使用しながら、同時にクロールしているWebサイトにも親切です。 これは通常、1秒間に1程度の割合でヒットを1つのサイトに制限し、同時に複数のWebサイトをクロールすることを意味します。

繰り返しますが、これはすべて、私がクモについて一般的に知っていること、およびあなたがここに投稿したことに基づいた単なる推測です。


2


残念ながら、より有名な「本物の」Webスパイダーの多くはクローズドソースであり、実際にはクローズドバイナリです。 しかし、wgetにはないいくつかの基本的なテクニックがあります。

  • 並列処理一度に複数のページを取得しなくてもWeb全体についていくことができないでしょう。

  • 優先順位付けあるページは他のページよりもクモにとって重要です

  • レート制限できるだけ早くページをプルダウンし続けると、すぐに禁止されます。

  • ローカルファイルシステム以外のものに保存する。 Webは十分に大きいので、1つのディレクトリツリーに収まりません。

  • プロセス全体を再起動せずに定期的にページを再チェックする。実際には、本物のクモを使うと、更新のために「重要な」ページを頻繁に再確認したいと思うでしょう。

サイトマップなど、使用できる他のさまざまな入力もあります。 要するに、wgetはWeb全体を網羅するようには設計されていません。また、小さなサブルーチンが間違っているのではなく、使用されている全体的な手法全体の問題であるためタスクのために。


1


私はインターネットをスパイダーする方法の詳細に入るつもりはない、私はwgetのコメントはまだ深刻な挑戦である1つのウェブサイトをスパイダーすることに関すると思う。

  • スパイダーとして、URLがdate = 1/1/1900から1/2/1900のように変化したからといって、再帰的なクロールを行わないでください。

  • URL Rewriteを整理することがさらに大きな課題となります(Googleや他のユーザーがこれをどのように処理しているのか、私にはわかりません)。 十分にクロールすることは非常に大きな課題ですが、それほど多くはありません。 そして、ランダムなパラメータとコンテンツのランダムな変更を使用してURL Rewriteを自動的に認識する方法はありますか。

  • 少なくともある程度までFlash / Javascriptを解析する必要があります。

  • あなたは_base_タグのようないくつかのクレイジーなHTTPの問題を考慮する必要があります。 ほとんどのWebサイトがXHTMLではなく、ブラウザの構文が非常に柔軟であることを考えると、HTMLの解析でさえも容易ではありません。

これらのうちどれだけがwgetで実装または考慮されているのかわかりませんが、このタスクの課題を理解するためにhttrackを見てみるとよいでしょう。

私はあなたにいくつかのコード例を挙げたいのですが、これは大きなタスクであり、まともなクモはサードパーティのライブラリなしで約5000 locになります。

それらのうちのいくつかは既に@ yaakov-belchによって説明されているので私はそれらを再びタイプするつもりはない