シグナル¶
Scrapyは、特定のイベントが発生したときに通知するためにシグナルを広範囲に使用します。 Scrapyプロジェクトでこれらのシグナルの一部をキャッチして(たとえば 拡張機能 で)、追加のタスクを実行したり、Scrapyを拡張してすぐに使用できない機能を追加したりできます。
シグナルはいくつかの引数を提供しますが、それらをキャッチするハンドラーはそれらのすべてを受け入れる必要はありません。シグナル・ディスパッチ・メカニズムはハンドラーが受け取る引数のみを配信します。
あなたは シグナルAPI を介してシグナルに接続(または独自に送信)できます。
シグナルをキャッチして何らかのアクションを実行する方法を示す簡単な例を次に示します:
from scrapy import signals
from scrapy import Spider
class DmozSpider(Spider):
name = "dmoz"
allowed_domains = ["dmoz.org"]
start_urls = [
"http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
"http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/",
]
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(DmozSpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
return spider
def spider_closed(self, spider):
spider.logger.info('Spider closed: %s', spider.name)
def parse(self, response):
pass
シグナル・ハンドラーの遅延(deferred)¶
一部のシグナルはハンドラーから Deferred
オブジェクトを返すことをサポートしており、Scrapy をブロックしない非同期コードを実行できます。 シグナルハンドラが Deferred
を返した場合、Scrapy はその Deferred
が起動するのを待ちます。
例を見てみましょう:
class SignalSpider(scrapy.Spider):
name = 'signals'
start_urls = ['http://quotes.toscrape.com/page/1/']
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(SignalSpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.item_scraped, signal=signals.item_scraped)
return spider
def item_scraped(self, item):
# Send the scraped item to the server
d = treq.post(
'http://example.com/post',
json.dumps(item).encode('ascii'),
headers={b'Content-Type': [b'application/json']}
)
# The next item will be scraped only after
# deferred (d) is fired
return d
def parse(self, response):
for quote in response.css('div.quote'):
yield {
'text': quote.css('span.text::text').get(),
'author': quote.css('small.author::text').get(),
'tags': quote.css('div.tags a.tag::text').getall(),
}
どのシグナルが Deferred
をサポートするかについては、以下の 組み込みシグナル・リファレンス を参照してください。
組み込みシグナル・リファレンス¶
Scrapy組み込みシグナルとその意味のリストを以下に示します。
エンジン・シグナル群¶
engine_started¶
- scrapy.signals.engine_started()¶
Scrapyエンジンがクロールを開始すると送信されます。
このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしています。
注釈
このシグナルは、スパイダーの起動方法に応じて、 spider_opened
シグナルの 後に 起動される場合があります。 そのため、 spider_opened
の前にこのシグナルが発生することに依存しないでください。
アイテム・シグナル群¶
注釈
最大 CONCURRENT_ITEMS
数のアイテムが並行して処理されるため、多くの遅延(deferred)は DeferredList
を使用して同時に起動されます。 したがって、以下のバッチは DeferredList
が起動するのを待ってから、スクレイピングされたアイテムの次のバッチに対してそれぞれのアイテム・シグナル・ハンドラーを実行します。
item_scraped¶
- scrapy.signals.item_scraped(item, response, spider)¶
すべての アイテム・パイプライン ステージを(ドロップされることなく)通過した後、アイテムがスクレイプされたときに送信されます。
このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしています。
- パラメータ
item (item object) -- スクレイプされたアイテム
spider (
Spider
object) -- アイテムをスクレイプしたスパイダーresponse (
Response
object) -- アイテムがスクレイピングされたレスポンス
item_dropped¶
- scrapy.signals.item_dropped(item, response, exception, spider)¶
あるステージで
DropItem
例外が発生したときに、アイテムが アイテム・パイプライン からドロップされた後に送信されます。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしています。
- パラメータ
item (item object) -- アイテム・パイプライン からドロップされたアイテム
spider (
Spider
object) -- アイテムをスクレイプしたスパイダーresponse (
Response
object) -- アイテムがドロップされたレスポンスexception (
DropItem
exception) -- アイテムがドロップされる原因となった例外(DropItem
のサブクラスでなければなりません)
item_error¶
- scrapy.signals.item_error(item, response, spider, failure)¶
DropItem
例外を除き、 アイテム・パイプライン がエラーを生成した(つまり、例外を発生させた)ときに送信されます。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしています。
- パラメータ
item (item object) -- アイテム・パイプライン でエラーの原因となったアイテム
response (
Response
object) -- 例外が発生したときに処理されていたレスポンスspider (
Spider
object) -- 例外を発生させたスパイダーfailure (twisted.python.failure.Failure) -- 例外が発生した
スパイダー・シグナル群¶
spider_closed¶
- scrapy.signals.spider_closed(spider, reason)¶
スパイダーが閉じられた後に送信されます。 これは、
spider_opened
で予約しているスパイダーごとのリソースを解放するために使用できます。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしています。
- パラメータ
spider_opened¶
spider_idle¶
- scrapy.signals.spider_idle(spider)¶
スパイダーがアイドル状態になったときに送信されます。つまり、スパイダーはそれ以降何もしない事を意味します:
リクエストがダウンロード待ち
リクエストがスケジュールされた
アイテムがアイテム・パイプラインで処理中
このシグナルのすべてのハンドラーが終了した後もアイドル状態が続く場合、エンジンはスパイダーを閉じ始めます。スパイダーのクローズが完了すると、
spider_closed
シグナルが送信されます。あなたは
DontCloseSpider
例外を発生させて、スパイダーが閉じられないようにすることができます。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしていません。
- パラメータ
spider (
Spider
object) -- アイドルに移行したスパイダー
注釈
あなたの spider_idle
ハンドラーでいくつかのリクエストをスケジュールすると、スパイダーが閉じられるのを防ぐことができるという保証はありませんが、できる場合もあります。これは、スケジュールされたすべてのリクエストがスケジューラによって拒否された場合(たとえば、重複のためにフィルター処理された場合)、スパイダーがアイドル状態のままになる可能性があるためです。
spider_error¶
- scrapy.signals.spider_error(failure, response, spider)¶
スパイダー・コールバックがエラーを生成する(つまり、例外を発生させる)ときに送信されます。
このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしていません。
- パラメータ
failure (twisted.python.failure.Failure) -- 例外が発生した
response (
Response
object) -- 例外が発生したときに処理されていたレスポンスspider (
Spider
object) -- 例外を発生させたスパイダー
リクエスト・シグナル群¶
request_scheduled¶
request_dropped¶
request_reached_downloader¶
request_left_downloader¶
bytes_received¶
バージョン 2.2 で追加.
- scrapy.signals.bytes_received(data, request, spider)¶
特定のリクエストに対してバイトのグループが受信されたときに、HTTP 1.1 および S3 ダウンロード・ハンドラーによって送信されます。 このシグナルは、同じリクエストに対して複数回発生する可能性があり、そのたびに部分的なデータが生成されます。 たとえば、25 kb のレスポンスのシナリオとしては、2 つの信号が 10 kb のデータで発信され、最後の信号が 5 kb のデータで発信されます。
このシグナルのハンドラは
StopDownload
例外を発生させることで進行中のレスポンスのダウンロードを停止できます. 追加情報と例については、レスポンスのダウンロードの停止 トピックを参照してください。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしていません。
headers_received¶
バージョン 2.5 で追加.
- scrapy.signals.headers_received(headers, request, spider)¶
追加のコンテンツをダウンロードする前に、特定のリクエストに対してレスポンス・ヘッダーが使用可能な場合に、HTTP 1.1 および S3 ダウンロード・ハンドラーによって送信されます。
このシグナルのハンドラは
StopDownload
例外を発生させることで進行中のレスポンスのダウンロードを停止できます. 追加情報と例については、レスポンスのダウンロードの停止 トピックを参照してください。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしていません。
レスポンス・シグナル群¶
response_received¶
- scrapy.signals.response_received(response, request, spider)¶
エンジンがダウンローダーから新しい
Response
を受信すると送信されます。このシグナルは、ハンドラーから遅延オブジェクト(deferred)を返すことをサポートしていません。
注釈
ダウンローダー・ミドルウェア が Response
オブジェクトを変更し、特定の request
属性を設定する場合、request
引数はダウンローダに届いた元のリクエストを含まない可能性があります。