Java マルチスレッド クローラーと分散クローラー アーキテクチャの調査

Java マルチスレッド クローラーと分散クローラー アーキテクチャの調査

これは Java クローラー シリーズの 5 番目です。前回の記事では、Java クローラー サーバーがブロックされましたが、慌てずにサーバーを変更しましょう。主に IP ブロッキングとそれに対応する方法に焦点を当てて、クローラー対策戦略とクローラー対策方法について簡単に説明しました。これまでのいくつかの記事では、クローラーに関連するほぼすべての基本的な知識をカバーしました。この記事では、クローラーのアーキテクチャについて説明します。

[[279402]]

前の章では、クローラー プログラムはすべてシングル スレッドでした。クローラー プログラムをデバッグすると、シングル スレッド クローラーでは問題は発生しません。ただし、シングルスレッド クローラーを使用してオンライン環境で Web ページを収集する場合、シングルスレッドによって 2 つの致命的な問題が発生します。

  • 収集効率は非常に低く、各スレッドはシリアルです。次の実行アクションは、前のアクションが完了するまで待機してから実行する必要があります。
  • サーバーのCPUの使用率は高くありません。考えてみてください。当社のサーバーはすべて 8 コア、16G、32G を搭載しています。スレッドを 1 つだけ実行するのは無駄ではないでしょうか?

オンライン環境は、結果が正しく抽出できる限り、収集効率を気にしないローカルテストのようなものであってはなりません。時は金なりと言われるこの時代では、ゆっくりとデータを収集する時間を与えることは不可能なので、シングルスレッドのクローラー プログラムは機能しません。収集効率を改善し、コンピュータの使用率を高めるには、シングルスレッド モードをマルチスレッド モードに変更する必要があります。

マルチスレッド クローラー プログラムの設計は、シングルスレッド クローラー プログラムの設計よりもはるかに複雑です。ただし、高い同時実行性の下でデータ セキュリティを確保する必要のある他のビジネスとは異なり、マルチスレッド クローラーでは各ページが独立したエンティティと見なすことができるため、データ セキュリティに対する要件はそれほど高くありません。マルチスレッド クローラーをうまく機能させるには、2 つのことを適切に行う必要があります。1 つ目は、収集する URL の統一されたメンテナンスであり、2 つ目は URL の重複排除です。これら2点について簡単にお話ししましょう。

収集するURLを維持する

マルチスレッド クローラー プログラムは、各スレッドが収集する独自の URL を維持するシングルスレッド プログラムのようにはなりません。この場合、各スレッドによって収集される Web ページは同じになります。これはマルチスレッドのコレクションではありませんが、ページを複数回収集しています。このため、収集する URL を統一的に管理する必要があります。各スレッドは、統合 URL メンテナンスから収集された URL を受け取り、収集タスクを完了します。ページ上で新しい URL リンクが見つかった場合、そのリンクは統合 URL によって管理されるコンテナーに追加されます。統合 URL メンテナンスに適したコンテナーをいくつか次に示します。

  • LinkedBlockingQueueなどのJDKのセキュアキュー
  • RedisやMongodbなどの高性能NoSQL
  • MQ メッセージ ミドルウェア

URL重複排除

URL 重複排除も、マルチスレッド収集における重要なステップです。重複を排除しないと、重複した URL が大量に収集され、収集効率が向上しません。たとえば、ページ分けされたニュース リストの場合、最初のページを収集するとページ 2、3、4、5 へのリンクが取得され、2 番目のページを収集するとページ 1、3、4、5 へのリンクが取得されます。収集する URL キューにはリスト ページ リンクが大量に存在し、収集が繰り返され、無限ループに陥る可能性があるため、URL の重複排除が必要になります。 URL の重複を排除する方法は多数あります。よく使用される方法をいくつか紹介します。

  • Redis、MongoDBなどの重複排除用データベースにURLを保存する
  • ハッシュセットなどのハッシュテーブルにURLを入れて重複を削除します。
  • 重複を削除するには、MD5 の後に URL をハッシュ テーブルに保存します。上記の方法と比較して、スペースを節約できます
  • 重複を削除するには、Bloom Filter を使用します。この方法は多くのスペースを節約できますが、それほど正確ではありません。

マルチスレッド クローラーに関する 2 つの重要な知識ポイントは誰もが知っています。以下に、シンプルなマルチスレッド クローラー アーキテクチャ図を示します。

マルチスレッド クローラー アーキテクチャ図

上記では、主にマルチスレッド クローラーのアーキテクチャ設計について学習しました。次に、Java マルチスレッド クローラーを試してみましょう。 Java マルチスレッド クローラーを練習するために、Hupu News のコレクションを例に挙げます。 Java マルチスレッド クローラーは、収集する URL を維持し、重複する URL を削除するように設計されています。ここではデモンストレーションのみなので、JDK の組み込みコンテナーを使用して完了させます。収集する URL を維持するためのコンテナとして LinkedBlockingQueue を使用し、重複する URL を削除するためのコンテナとして HashSet を使用します。以下は、Java マルチスレッド クローラーのコア コードです。詳細なコードは GitHub にアップロードされており、そのアドレスは記事の最後にあります。

  1. /**
  2. * マルチスレッドクローラー
  3. */
  4. パブリッククラスThreadCrawlerはRunnableを実装します{
  5. // 収集された記事の数
  6. プライベート最終AtomicLong pageCount = new AtomicLong(0);
  7. // リストページリンクの正規表現
  8. 公共 静的最終文字列 URL_LIST = "https://voice.hupu.com/nba" ;
  9. 保護されたロガー logger = LoggerFactory.getLogger(getClass());
  10. // 収集するキュー
  11. LinkedBlockingQueue<文字列> タスクキュー;
  12. // 収集されたリンクのリスト
  13. HashSet<String> が訪問されました。
  14. //スレッドプール
  15. カウント可能なスレッドプール スレッドプール;
  16. /**
  17. *
  18. * @param url 開始ページ
  19. * @param threadNum スレッド数
  20. * @throws 中断例外
  21. */
  22. パブリックThreadCrawler(String url, int threadNum)はInterruptedExceptionをスローします{
  23. this.taskQueue = 新しい LinkedBlockingQueue<>();
  24. this.threadPool = 新しい CountableThreadPool(threadNum);
  25. this.visited = 新しい HashSet<>();
  26. // 収集するキューに開始ページを追加します
  27. タスクキューにURLを書き込みます。
  28. }
  29.  
  30. @オーバーライド
  31. パブリックボイド実行(){
  32. logger.info( "スパイダーが起動しました!" );
  33. while (!Thread.currentThread().isInterrupted()) {
  34. // キューから収集するURLを取得します
  35. 最終的な文字列リクエスト = taskQueue.poll();
  36. // リクエストが空で、現在のスレッドに実行中のスレッドがない場合
  37. リクエストがnull場合
  38. (threadPool.getThreadAlive() == 0)の場合{
  39. 壊す;
  40. }
  41. }それ以外{
  42. //コレクションタスクを実行する
  43. スレッドプール.execute (新しいRunnable() {
  44. @オーバーライド
  45. パブリックボイド実行(){
  46. 試す {
  47. リクエストを処理します。
  48. } キャッチ (例外 e) {
  49. logger.error( "プロセスリクエスト " + リクエスト + "エラー" , e);
  50. ついに
  51. // コレクションページ +1
  52. ページカウントを増加して取得します。
  53. }
  54. }
  55. });
  56. }
  57. }
  58. スレッドプールをシャットダウンします。
  59. logger.info( "スパイダーが閉じました! {} ページがダウンロードされました。" , pageCount.get());
  60. }
  61.  
  62. /**
  63. * 収集リクエストの処理
  64. * @param URL
  65. */
  66. 保護されたvoid processRequest(文字列url) {
  67. // リストページかどうかを判定する
  68. url.matches(URL_LIST) の場合
  69. // リストページから詳細ページリンクを解析し、収集するURLキューに追加します
  70. タスクキューを処理します(url);
  71. }それ以外{
  72. // Webページを解析する
  73. processPage(url);
  74. }
  75. }
  76. /**
  77. * リンク集の処理
  78. * リストページを処理し、URLをキューに追加します
  79. *
  80. * @param URL
  81. */
  82. 保護されたvoid processTaskQueue(文字列url) {
  83. 試す {
  84. ドキュメント doc = Jsoup.connect (url).get();
  85. //詳細ページリンク
  86. 要素 elements = doc。 ( " div.news-list > ul > li > div.list-hd > h4 > a "を選択);
  87. elements.stream().forEach((要素 -> {
  88. 文字列リクエスト = element.attr( "href" );
  89. // リンクがキューまたは収集されたセット内に存在するかどうかを確認します。そうでない場合は、キューに追加します。
  90. if (!visited. contains (request) && !taskQueue. contains (request)) {
  91. 試す {
  92. タスクキューにリクエストを書き込みます。
  93. } キャッチ (InterruptedException e) {
  94. e.printStackTrace();
  95. }
  96. }
  97. }));
  98. // リストページリンク
  99. 要素 list_urls = doc.select ( "div.voice-paging > a" );
  100. list_urls.stream().forEach((要素 -> {
  101. 文字列リクエスト = element.absUrl( "href" );
  102. // 抽出するリストリンクの要件が満たされているかどうかを判定する
  103. リクエストがURL_LISTと一致する場合
  104. // リンクがキューまたは収集されたセット内に存在するかどうかを確認します。そうでない場合は、キューに追加します。
  105. if (!visited. contains (request) && !taskQueue. contains (request)) {
  106. 試す {
  107. タスクキューにリクエストを書き込みます。
  108. } キャッチ (InterruptedException e) {
  109. e.printStackTrace();
  110. }
  111. }
  112. }
  113. }));
  114.  
  115. } キャッチ (例外 e) {
  116. e.printStackTrace();
  117. }
  118. }
  119. /**
  120. * ページを解析する
  121. *
  122. * @param URL
  123. */
  124. 保護されたvoid processPage(文字列url) {
  125. 試す {
  126. ドキュメント doc = Jsoup.connect (url).get();
  127. 文字列タイトル = doc。 ( 「body > div.hp-wrap > div.voice-main > div.artical-title > h1」 )を選択します最初に().ownText();
  128.  
  129. システム。 out .println(Thread.currentThread().getName() + " in " + new Date () + " 収集されたHupuニュース " + title);
  130. // 収集したURLを収集セット保存する
  131. 訪問しました。追加(url);
  132.  
  133. } キャッチ (IOException e) {
  134. e.printStackTrace();
  135. }
  136. }
  137.  
  138. 公共 静的void main(String[] args) {
  139.  
  140. 試す {
  141. 新しい ThreadCrawler( "https://voice.hupu.com/nba" 、 5).run();
  142. } キャッチ (InterruptedException e) {
  143. e.printStackTrace();
  144. }
  145. }
  146. }

効果を確認するために、5 つのスレッドを使用して Hupu ニュース リスト ページを収集します。プログラムを実行すると、次の結果が得られます。


マルチスレッドコレクションの結果

結果からわかるように、61 ページを収集するために 5 つのスレッドを開始し、合計 2 秒かかりました。効果は依然として良好であると言えます。 1 本のスレッドと比較して、ギャップがどのくらい大きいか確認してみましょう。スレッド数を 1 に設定してプログラムを再度開始すると、次の結果が得られます。

シングルスレッド実行結果

シングルスレッド クローラーが Hupu から 61 件のニュースを収集するのに 7 秒かかったことがわかります。これは、マルチスレッド クローラーのほぼ 4 倍の時間です。考えてみてください、これはたった 61 ページです。ページ数が増えるとギャップはどんどん大きくなるため、マルチスレッド クローラーの効率は依然として非常に高くなります。

分散クローラーアーキテクチャ

分散クローラー アーキテクチャは、大規模な収集プログラムのみが使用する必要があるアーキテクチャです。一般的に、単一マシンのマルチスレッドはビジネスニーズを解決できます。いずれにせよ、私は分散クローラー プロジェクトの経験がないので、これについては何も言うことはありません。しかし、技術者として、私たちは技術に対する熱意を持ち続ける必要があります。必要ではないですが、理解しておいても損はありません。私は多くの情報を調べ、以下の結論に達しました。

分散クローラー アーキテクチャは、考え方の面ではマルチスレッド クローラー アーキテクチャと同じです。シンプルな分散クローラー アーキテクチャにするには、マルチスレッドに基づいてわずかな改良を加えるだけで済みます。分散クローラー アーキテクチャではクローラーが異なるマシンに展開されるため、収集する URL と収集された URL をクローラー マシンのメモリに保存することはできません。 Redis や MongoDB などの特定のマシン上でそれらを管理する必要があります。各マシンは、LinkedBlockingQueue などのメモリ キューからリンクを取得するのではなく、そこからコレクション リンクを取得します。このようにして、シンプルな分散クローラー アーキテクチャが実現します。もちろん、ここには多くの詳細があります。分散アーキテクチャの経験がないので、どこから始めればよいのかわかりません。ご興味がございましたら、ぜひご連絡ください。

<<:  クラウドストレージの5つの利点

>>:  クラウド上のフィンテック

推薦する

APICloud は、エコシステムの力を活用して、企業のインターネット化のニーズを再構築します。

モバイルインターネット時代の技術革新は、効率性と利益を絶えず追求しながら、ますます統合化が進む傾向を...

QingCloud、エンタープライズレベルのフルスタッククラウドICTマトリックスを構築するために9つの主要ブランドを立ち上げ

エンタープライズレベルのフルスタッククラウドICTサービスプロバイダーであるQingCloud(qi...

evlgaming-3.5$/Kvm/512m メモリ/15g ハードディスク/300g トラフィック/フェニックス/カンザス

evlgaming は、カンザス州とフェニックスの 2 つのコンピューター ルームで VPS サービ...

Baidu SEO と Google SEO には違いがありますか?ザックは、検索エンジンは良いウェブサイトを好むと言った。

百度がネガティブなニュースに登場するたびに、多くの人がグーグルを懐かしみ、グーグルが来てくれたら最高...

extravm: 月額 3.5 ドル、KVM シリーズ、シンガポールの無制限の高セキュリティ VPS、OVH データ センター

OVHのシンガポールデータセンターでVPSを購入したいという方もいらっしゃいますが、残念ながら公式サ...

Baidu SEO ウェブサイトのトップ 10 の問題と解決策

(1)ウェブサイトリンク理由: ウェブサイトに外部リンクが不足しているか、外部リンクが徐々に減少して...

これらの4つの文章について考えれば、SEOに悩まされることはなくなるでしょう

百度はSEOを文書で認めたことはなく、検索最適化ガイドラインなどの公式文書を発表したのみだが、SEO...

ワールドカップ生中継権事件の裏側:視聴者は動画サイトへ移行

原題: 対立とチャンス: ワールドカップ「インターネット」イベント毎年のワールドカップは中国のインタ...

タオバオのコンバージョン率に影響を与える最も重要な5つの要因の簡単な分析

自分の店舗の核となる要素を変えることで、すぐにコンバージョン率が上がり、利益がAlipayに流れ続け...

台湾のVPS(台湾のクラウドサーバー)の一括推奨

台湾 VPS、台湾クラウドサーバー、台湾チキン、台湾 VPS 大帯域幅、台湾 VPS 年払い、台湾 ...

ウェブサイトの重さについて考える

ウェブサイトの重みの定義は何ですか?多くの SEO 担当者がウェブサイトの重みについて議論しています...

ファーウェイクラウド最高製品責任者の郭偉関氏:フルスタックのクラウドネイティブ技術が金融業界のイノベーションのボトルネック打破に貢献

9月16日、中軟国際ホールディングス株式会社主催の「中国生命保険技術応用サミットフォーラム2021」...

ウェブサイトの持続可能な開発で利益を上げる方法

インターネットの発展に伴い、インターネットを通じて富を創造できるという奇跡に魅了されて、インターネッ...

中国インターネット広告市場調査レポート

この記事では、iResearch が発表した「中国のインターネット広告市場に関する年次調査レポート」...

SAPと永泰生物科技が共同でデジタル運用管理プラットフォームを構築し、デジタルパワーでがんと闘う

本日、SAPと北京永泰生物製品有限公司(以下、「永泰生物」)は調印式を開催し、全面的な協力関係に合意...