Pythonスクレイプフレームワークティーチング(5):分散クローラー

データの重複排除

データが重複している場合、保存できません

from scrapy.exceptions import DropItem 
class DuplicatesPipeline(object): 
  def __init__(self): 
    self.ids_seen = set() 
  def process_item(self, item, spider): 
    if item['id'] in self.ids_seen: 
      raise DropItem("Duplicate item found: %s" % item) 
    else:
      self.ids_seen.add(item['id']) 
    return item

Pythonクローラー、データ分析、Webサイト開発、その他のケースチュートリアルビデオはオンラインで無料で視聴できます

https://space.bilibili.com/523606542 

Python学習交換グループ:1039645993

分散コレクション

Scrapy_redis:Scrapy用のRedisベースのコンポーネント。

Githubアドレス:https//github.com/rmax/scrapy-redis  Scrapy_redisは、scrapyに基づいて、ますます強力な機能を実装します。これらの機能は、重複排除、クローラーの永続性、簡単な
配布で具体化されます。

では、scrapy_redisはどのようにデータをスクレイピングするのに役立ちますか?

スタンドアロンクローラー

デフォルトでは、Scrapyは分散をサポートしていません。分散を実現するには、RedisベースのScrapy-Redisコンポーネントを使用する必要があります。

通常のScrapyスタンドアロンクローラー:

 

Scrapyはスケジューリングキューを共有しません。つまり、Scrapyは分散をサポートしていません。配布をサポートするには、Scrapyに共有スケジューリングキューをサポートさせる必要があります。これは、共有スケジューリングおよび重複排除機能に変換されます。

分散クローラー

分散統治法:分割統治

クローラーコードを複数のコンピューターに展開して、クローラータスクを一緒に完了します。

Redisサーバーを使用して、すべてのリクエストを一元的に処理します。主に、リクエストの重複排除とスケジューリングを担当します。このように、コンピューター側のすべてのクローラーはクロールキューを共有し、各コンピューター側が受信したすべての要求が他のクローラーによってアクセスされることはありません。これにより、クローラーの効率が向上します。

リクエストを受け取ったら、リクエストがRedisで重複排除されているかどうかを確認します。重複排除されている場合は、他のスパイダーが重複排除していることを証明します。そうでない場合は、ディスパッチキューに追加し、他のユーザーが取得するのを待ちます。

Scrapyは一般的なクローラーフレームワークですが、分散型をサポートしていません。Scrapy-redisは、Scrapy分散型クロールをより便利に実装するために、いくつかのredisベースのコンポーネントを提供します。

インストールは次のとおりです。pipinstallscrapy-redisScrapy-redis

次の4つのコンポーネント(コンポーネント)を提供します:( 4つのコンポーネントは、これらの4つのモジュールをそれに応じて変更する必要があることを意味します)

  • スケジューラー
  • 複製フィルター(重複排除)
  • アイテムパイプライン
  • ベーススパイダー(爬虫類)

スケジューラー(スケジューラー)
ScrapyはPythonの元のcollection.deque(双方向キュー)を変換して独自のScrapyキューを形成しますが、Scrapyの複数のスパイダーはクロールするキューを共有できません。Scrapyキュー、つまりScrapy自体は分散されたクローラーをサポートしていません。 scarpy- redisの解決策は、このScrapyキューをredisデータベース(redisキューとも呼ばれる)に置き換えることです。これにより、複数のスパイダーが同じデータベースから読み取ることができるため、共有クロールキューが実現されます。

Redisはさまざまなデータ構造をサポートしています。これらのデータ構造は次のような要件を簡単に実現できます。

  • リストにはlpush()、lpop()、rpush()、rpop()があり、これらのメソッドは先入れ先出しまたは先入れ先出しのクロールキューを実現できます。
  • コレクション要素は順序付けられておらず、非反復的であり、ランダムな並べ替えと非反復的なクロールキューを実装すると便利です。
  • Scrapyのリクエストには優先度制御があり、Redisのコレクションにもスコアがあります。この関数を使用して、優先度スケジューリングを使用してクロールキューを実装できます。

Scrapyは、クロールされるキューの優先度に従って、次のような辞書構造を構築します。

{ 
  优先级0 : 队列0 
  优先级1 : 队列1 
  优先级2 : 队列2 
}

次に、リクエストの優先度に従って、どのキューに入るかが決定され、デキューするときに、低い優先度に従ってデキューされます。Scrapyの元のスケジューラーはScrapy自身のキューのみを処理でき、Redisのキューを処理できないため、元のスケジューラーは使用できなくなり、Scrapy-Redisのスケジューラーコンポーネントを使用する必要があります。

重複
排除フィルター(重複排除 Scrapyには、Pythonのコレクションタイプを使用する重複排除モジュールが付属しています。このコレクションは、リクエストのハッシュ値である各リクエストのフィンガープリントを記録します。フィンガープリントの計算では、hashlibのsha1()メソッドを使用します。計算されるフィールドには、要求されたメソッド、URL、本文、およびヘッダーが含まれます。これらの文字列にわずかな違いがある限り、計算されるフィンガープリントは異なります。つまり、計算の結果は、要求フィンガープリントである暗号化された文字列になります。暗号化された文字列を通じて、各リクエストは一意です。つまり、フィンガープリントは一意です。また、フィンガープリントは文字列です。リクエストオブジェクト全体を判断するよりも文字列を判断する方が簡単です。したがって、指紋は判断と重複排除の基礎として使用されます。

Scrapy-Redisが分散クローラーの重複排除機能を実現するには、フィンガープリントコレクションも更新する必要がありますが、各クローラーが独自のフィンガープリントコレクションを維持することはできません。Redisコレクションのデータ構造タイプを使用すると、分散クローラーの指紋識別を簡単に実現できます。つまり、各ホストはリクエストのフィンガープリントを取得し、Redisのコレクションと比較します。フィンガープリントが存在する場合、それは重複していることを意味し、リクエストを送信しません。 Redis、リクエストを送信し、Redisコレクションにフィンガープリントを追加します。このようにして、分散クローラーの指紋コレクションの共有が実現されます。

アイテムパイプライン
エンジンは、クロールされたアイテム(スパイダーによって返される)をアイテムパイプラインに送信し、scrapy-redisアイテムパイプラインは、クロールされたアイテムをredisアイテムキューに格納します。アイテムパイプラインを変更した後、キーに基づいてアイテムキューからアイテムを抽出し、アイテムプロセスクラスターを実装すると便利です。

Base Spider
は、scrapyの元のSpiderクラスを使用しなくなりました。書き直されたRedisSpiderは、SpiderとRedisMixinの2つのクラスを継承します。RedisMixinは、redisからURLを読み取るために使用されるクラスです。RedisSpiderを継承するSpiderを生成し、setup_redis関数を呼び出すと、この関数はredisデータベースに接続し、シグナル(シグナル)を設定します。

スパイダーがアイドル状態のとき、シグナルはspider_idle関数を呼び出します。この関数は、schedule_next_request関数を呼び出して、スパイダーが常に生きていることを確認し、DontCloseSpider例外をスローします。

アイテムのシグナルがキャッチされると、item_scraped関数が呼び出され、この関数はschedule_next_request関数を呼び出して次のリクエストを取得します。

おすすめ

転載: blog.csdn.net/m0_48405781/article/details/114982668