Сигналы

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 из своих обработчиков, что позволяет запускать асинхронный код, который не блокирует 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 начинает сканировать.

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Примечание

Данный сигнал может быть запущен после сигнала spider_opened, в зависимости от того, как был запущен паук. Таким образом, не полагается на срабатывание этого сигнала до spider_opened.

engine_stopped

scrapy.signals.engine_stopped()

Отправляется, когда двигатель Scrapy остановлен (например, когда процесс сканирования завершён).

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Сигналы элементов

Примечание

Поскольку при макс. CONCURRENT_ITEMS элементы обрабатываются параллельно, многие отложенные запросы запускаются вместе с использованием DeferredList. Следовательно, следующая партия ожидает срабатывания DeferredList, а затем запускает соответствующий обработчик сигнала элемента для следующей партии очищенных элементов.

item_scraped

scrapy.signals.item_scraped(item, response, spider)

Отправляется, когда элемент был очищен, после того, как он прошел все этапы Элемент конвейера (без отбрасывания).

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Параметры
  • item (item object) – сканируемый элемент

  • spider (Spider object) – паук, сканирующий элемент

  • response (Response object) – ответ, откуда элемент был отсканирован

item_dropped

scrapy.signals.item_dropped(item, response, exception, spider)

Отправляется после того, как элемент был удалён из Элемент конвейера, когда на каком-то этапе возникла исключительная ситуация DropItem.

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Параметры
  • item (item object) – сброшеный элемент с Элемент конвейера

  • spider (Spider object) – паук, сканирующий элемент

  • response (Response object) – ответ, откуда был сброшен элемент

  • exception (DropItem exception) – исключение (которое должно быть подклассом DropItem), из-за которого элемент был отброшен

item_error

scrapy.signals.item_error(item, response, spider, failure)

Отправляется, когда Элемент конвейера генерирует ошибку (т. е. Вызывает исключение), за исключением исключения DropItem.

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Параметры
  • item (item object) – элемент, вызвавший ошибку в Элемент конвейера

  • response (Response object) – ответ обрабатывается при возникновении исключения

  • spider (Spider object) – паук, вызвавший исключение

  • failure (twisted.python.failure.Failure) – возникло исключение

Сигналы паука

spider_closed

scrapy.signals.spider_closed(spider, reason)

Отправлено после закрытия паука. Это можно использовать для освобождения ресурсов каждого паука, зарезервированных на spider_opened.

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Параметры
  • spider (Spider object) – паук, который был закрыт

  • reason (str) – строка, описывающая причину закрытия паука. Если он был закрыт из-за того, что паук завершил сканирование, причина в 'finished'. В противном случае, если паук был закрыт вручную путём вызова метода движка close_spider, то причина заключается в том, что было передано в аргументе reason этого метода (который по умолчанию имеет значение 'cancelled'). Если двигатель был выключен (например, нажатием Ctrl-C, чтобы остановить его), причиной будет 'shutdown'.

spider_opened

scrapy.signals.spider_opened(spider)

Отправляется после того, как паук открыт для сканирования. Обычно это используется для резервирования ресурсов для каждого паука, но может использоваться для любой задачи, которая должна быть выполнена при открытии паука.

Данный сигнал поддерживает возврат отложенных сообщений от своих обработчиков.

Параметры

spider (Spider object) – паук, который был открыт

spider_idle

scrapy.signals.spider_idle(spider)

Отправляется, когда паук бездействует, что означает, что паук больше не работает:

  • запросы, ожидающие загрузки

  • запросы запланированы

  • элементы, обрабатываемые в конвейере элементов

Если состояние холостого хода сохраняется после того, как все обработчики этого сигнала завершили работу, двигатель начинает закрывать паука. После того, как паук завершил закрытие, отправляется сигнал spider_closed.

Вы можете вызвать исключение DontCloseSpider, чтобы предотвратить закрытие паука.

В качестве альтернативы вы можете вызвать исключение CloseSpider, чтобы указать причину закрытия паука. Обработчик простоя — идеальное место для размещения некоторого кода, который вычисляет окончательные результаты пауков и соответствующим образом обновляет окончательную причину закрытия (например, устанавливая для него значение too_few_results вместо „finished“).

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры

spider (Spider object) – бездействующий паук

Примечание

Планирование некоторых запросов в обработчике spider_idle не даёт гарантию того, что он может предотвратить закрытие паука, хотя иногда и может. Это связано с тем, что паук может по-прежнему оставаться в режиме ожидания, если все запланированные запросы отклоняются планировщиком (например, отфильтрованы из-за дублирования).

spider_error

scrapy.signals.spider_error(failure, response, spider)

Отправляется, когда обратный вызов паука вызывает ошибку (т. е. вызывает исключение).

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • failure (twisted.python.failure.Failure) – возникло исключение

  • response (Response object) – ответ обрабатывается при возникновении исключения

  • spider (Spider object) – паук, вызвавший исключение

Сигналы запроса

request_scheduled

scrapy.signals.request_scheduled(request, spider)

Отправляется, когда двигатель планирует Request для загрузки позже.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • request (Request object) – запрос, который дошёл до планировщика

  • spider (Spider object) – паук, выполнивший запрос

request_dropped

scrapy.signals.request_dropped(request, spider)

Отправляется, когда Request, запланированный механизмом для загрузки позже, отклоняется планировщиком.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • request (Request object) – запрос, который дошёл до планировщика

  • spider (Spider object) – паук, выполнивший запрос

request_reached_downloader

scrapy.signals.request_reached_downloader(request, spider)

Отправляется, когда Request достигает загрузчика.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • request (Request object) – запрос, который дошёл до загрузчика

  • spider (Spider object) – паук, выполнивший запрос

request_left_downloader

scrapy.signals.request_left_downloader(request, spider)

Добавлено в версии 2.0.

Отправляется, когда Request покидает загрузчик, даже в случае сбоя.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • request (Request object) – запрос, который дошел до загрузчика

  • spider (Spider object) – паук, выполнивший запрос

bytes_received

Добавлено в версии 2.2.

scrapy.signals.bytes_received(data, request, spider)

Отправляется обработчиками загрузки HTTP 1.1 и S3 при получении группы байтов для определенного запроса. Данный сигнал может запускаться несколько раз для одного и того же запроса, каждый раз с частичными данными. Например, возможный сценарий для ответа размером 25 кбайт будет состоять из двух сигналов, запущенных с 10 кбайт данных, и последнего с 5 кбайт данных.

Обработчики этого сигнала могут остановить загрузку ответа во время его выполнения, вызвав исключение StopDownload. Пожалуйста, обратитесь к теме Остановка загрузки ответа за дополнительной информацией и примерами.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • data (bytes object) – данные, полученные обработчиком загрузки

  • request (Request object) – запрос, сгенерировавший загрузку

  • spider (Spider object) – паук, связанный с ответом

headers_received

Добавлено в версии 2.5.

scrapy.signals.headers_received(headers, body_length, request, spider)

Отправляется обработчиками загрузки HTTP 1.1 и S3, когда заголовки ответа доступны для данного запроса, перед загрузкой любого дополнительного содержимого.

Обработчики этого сигнала могут остановить загрузку ответа во время его выполнения, вызвав исключение StopDownload. Пожалуйста, обратитесь к теме Остановка загрузки ответа за дополнительной информацией и примерами.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • headers (scrapy.http.headers.Headers object) – заголовки, полученные обработчиком загрузки

  • body_length (int) – ожидаемый размер тела ответа в байтах

  • request (Request object) – запрос, сгенерировавший загрузку

  • spider (Spider object) – паук, связанный с ответом

Ответные сигналы

response_received

scrapy.signals.response_received(response, request, spider)

Отправляется, когда двигатель получает новый Response от загрузчика.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • response (Response object) – получен ответ

  • request (Request object) – запрос, на который был получен ответ

  • spider (Spider object) – паук, для которого предназначен ответ

Примечание

Аргумент request может не содержать исходный запрос, который достиг загрузчика, если Промежуточное ПО загрузчика изменяет объект Response и устанавливает определённый атрибут request.

response_downloaded

scrapy.signals.response_downloaded(response, request, spider)

Отправлено загрузчиком сразу после загрузки HTTPResponse.

Данный сигнал не поддерживает возврат отложенных сообщений от его обработчиков.

Параметры
  • response (Response object) – ответ загружен

  • request (Request object) – запрос, на который был получен ответ

  • spider (Spider object) – паук, для которого предназначен ответ