Расширения

Платформа расширений предоставляет механизм для вставки ваших собственных пользовательских функций в Scrapy.

Расширения — это просто обычные классы.

Настройки расширения

Расширения используют Scrapy настройки для управления своими настройками, как и любой другой код Scrapy.

Для расширений принято указывать перед настройками свое собственное имя, чтобы избежать конфликтов с существующими (и будущими) расширениями. Например, гипотетическое расширение для обработки Google Sitemaps будет использовать такие параметры, как GOOGLESITEMAP_ENABLED, GOOGLESITEMAP_DEPTH и т. д.

Загрузка и активация расширений

Расширения загружаются и активируются при запуске путём создания одного экземпляра класса расширения для каждого запущенного паука. Весь код инициализации расширения должен выполняться в методе класса __init__.

Чтобы сделать расширение доступным, добавить его в параметр EXTENSIONS в настройках Scrapy. В EXTENSIONS каждое расширение представлено строкой: полный путь Python к имени класса расширения. Например:

EXTENSIONS = {
    'scrapy.extensions.corestats.CoreStats': 500,
    'scrapy.extensions.telnet.TelnetConsole': 500,
}

Как видите, параметр EXTENSIONS — это определение, где ключи — это пути расширения, а их значения — это порядки, которые определяют порядок загрузки расширения. Параметр EXTENSIONS объединяется с параметром EXTENSIONS_BASE, определенным в Scrapy (и не предназначен для переопределения), а затем сортируется по порядку, чтобы получить окончательный отсортированный список включённых расширений.

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

Доступные, включенные и отключенные расширения

Не все доступные расширения будут включены. Некоторые из них обычно зависят от конкретной настройки. Например, расширение HTTP Cache доступно по умолчанию, но отключено, если не задан параметр HTTPCACHE_ENABLED.

Отключение расширения

Чтобы отключить расширение, которое включено по умолчанию (т. е. те, которые включены в настройку EXTENSIONS_BASE), вы должны установить его порядок на None. Например:

EXTENSIONS = {
    'scrapy.extensions.corestats.CoreStats': None,
}

Написание собственного расширения

Каждое расширение — это класс Python. Основной точкой входа для расширения Scrapy (сюда также входят промежуточное ПО и конвейеры) является метод класса from_crawler, который получает экземпляр Crawler. С помощью объекта Crawler вы можете получить доступ к настройкам, сигналам, статистике, а также контролировать поведение сканирования.

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

Наконец, если метод from_crawler вызывает исключение NotConfigured, расширение будет отключено. В противном случае расширение будет включено.

Пример расширения

Здесь мы реализуем простое расширение, чтобы проиллюстрировать концепции, описанные в предыдущем разделе. Это расширение будет регистрировать сообщение каждый раз:

  • паук открыт

  • паук закрыт

  • сканирует определённое количество элементоа

Расширение будет включено с помощью параметра MYEXT_ENABLED, а количество элементов будет указано с помощью параметра MYEXT_ITEMCOUNT.

Вот код такого расширения:

import logging
from scrapy import signals
from scrapy.exceptions import NotConfigured

logger = logging.getLogger(__name__)

class SpiderOpenCloseLogging:

    def __init__(self, item_count):
        self.item_count = item_count
        self.items_scraped = 0

    @classmethod
    def from_crawler(cls, crawler):
        # first check if the extension should be enabled and raise
        # NotConfigured otherwise
        if not crawler.settings.getbool('MYEXT_ENABLED'):
            raise NotConfigured

        # get the number of items from settings
        item_count = crawler.settings.getint('MYEXT_ITEMCOUNT', 1000)

        # instantiate the extension object
        ext = cls(item_count)

        # connect the extension object to signals
        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
        crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped)

        # return the extension object
        return ext

    def spider_opened(self, spider):
        logger.info("opened spider %s", spider.name)

    def spider_closed(self, spider):
        logger.info("closed spider %s", spider.name)

    def item_scraped(self, item, spider):
        self.items_scraped += 1
        if self.items_scraped % self.item_count == 0:
            logger.info("scraped %d items", self.items_scraped)

Справочник по встроенным расширениям

Расширения общего назначения

Расширение Log Stats

class scrapy.extensions.logstats.LogStats

Регистрировать базовую статистику, такую как просмотренные страницы и извлеченные элементы.

Расширение Статистика Ядра (Core Stats)

class scrapy.extensions.corestats.CoreStats

Включает сбор основной статистики, если сбор статистики включён (см. Сбор статистики).

Расширение консоли Telnet

class scrapy.extensions.telnet.TelnetConsole

Предоставляет консоль telnet для доступа к интерпретатору Python внутри текущего запущенного процесса Scrapy, что может быть очень полезно для отладки.

Консоль telnet должна быть включена параметром TELNETCONSOLE_ENABLED, и сервер будет прослушивать порт, указанный в TELNETCONSOLE_PORT.

Расширение использования памяти

class scrapy.extensions.memusage.MemoryUsage

Примечание

Это расширение не работает в Windows.

Контролирует память, используемую процессом Scrapy, который запускает паук и:

  1. отправляет уведомление по электронной почте, когда оно превышает определенное значение

  2. закрывает паук, когда он превышает определенное значение

Уведомления по электронной почте могут запускаться при достижении определённого значения предупреждения (MEMUSAGE_WARNING_MB) и при достижении максимального значения (MEMUSAGE_LIMIT_MB), что также приведёт к закрытию паука и завершению процесса Scrapy.

Это расширение включено параметром MEMUSAGE_ENABLED и может быть настроено со следующими параметрами:

Расширение отладчика памяти

class scrapy.extensions.memdebug.MemoryDebugger

Расширение для отладки использования памяти. Оно собирает информацию о:

Чтобы включить это расширение, включает параметр MEMDEBUG_ENABLED. Информация будет храниться в статистике.

Закрыть расширение паука

class scrapy.extensions.closespider.CloseSpider

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

Условия закрытия паука можно настроить с помощью следующих настроек:

Примечание

Когда выполняется определенное условие закрытия, запросы, которые в настоящее время находятся в очереди загрузчика (до запросов CONCURRENT_REQUESTS), все ещё обрабатываются.

CLOSESPIDER_TIMEOUT

По умолчанию: 0

Целое число, указывающее количество секунд. Если паук остаётся открытым дольше указанного количества секунд, он автоматически закрывается по причине closespider_timeout. Если ноль (или не установлен), пауки не будут закрыты по таймауту.

CLOSESPIDER_ITEMCOUNT

По умолчанию: 0

Целое число, определяющее количество элементов. Если паук сканирует больше, чем это количество, и данные элементы будут переданы конвейером элементов, паук будет закрыт с причиной closespider_itemcount. Если ноль (или не установлен), пауки не будут закрыты по количеству переданных элементов.

CLOSESPIDER_PAGECOUNT

По умолчанию: 0

Целое число, указывающее максимальное количество ответов на сканирование. Если паук проползет больше, паук закроется с причиной closespider_pagecount. Если ноль (или не установлен), пауки не будут закрыты по количеству просканированных ответов.

CLOSESPIDER_ERRORCOUNT

По умолчанию: 0

Целое число, указывающее максимальное количество ошибок, которые необходимо получить перед закрытием паука. Если паук выдаст больше ошибок, он будет закрыт с причиной closespider_errorcount. Если ноль (или не установлен), пауки не будут закрыты по количеству ошибок.

Расширение StatsMailer

class scrapy.extensions.statsmailer.StatsMailer

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

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

Отладка расширений

Расширение дампов трассировки стека

class scrapy.extensions.debug.StackTraceDump

Выводит информацию о запущенном процессе при получении сигнала SIGQUIT или SIGUSR2. Выгруженная информация следующая:

  1. статус двигателя (с использованием scrapy.utils.engine.get_engine_status())

  2. живые ссылки (см. Отладка утечек памяти с помощью trackref)

  3. трассировка стека всех потоков

После того, как трассировка стека и состояние ядра сброшены, процесс Scrapy продолжает работать в обычном режиме.

Это расширение работает только на POSIX-совместимых платформах (т. е. не в Windows), поскольку сигналы SIGQUIT и SIGUSR2 недоступны в Windows.

Есть как минимум два способа отправить Scrapy сигнал SIGQUIT:

  1. Нажав Ctrl- во время работы процесса Scrapy (только для Linux?)

  2. Выполнив эту команду (при условии, что <pid> — это идентификатор процесса Scrapy):

    kill -QUIT <pid>
    

Расширение отладчика

class scrapy.extensions.debug.Debugger

Вызывает отладчик Python внутри запущенного процесса Scrapy при получении сигнала SIGUSR2. После выхода из отладчика процесс Scrapy продолжает нормально работать.

Для получения дополнительной информации см. Отладку в Python.

Это расширение работает только на POSIX-совместимых платформах (т.е. не в Windows).