Scrapy: Как настроить пользовательские параметры для Spider?

Что такое пользовательские параметры Spider и зачем они нужны?

Пользовательские параметры Scrapy Spider — это способ динамически конфигурировать поведение вашего паука (spider) во время запуска. Они позволяют изменять настройки, такие как API-ключи, лимиты запросов, прокси и другие переменные, без необходимости изменения исходного кода паука. Это делает ваш код более гибким, переиспользуемым и упрощает управление конфигурацией в различных окружениях (разработка, тестирование, продакшн).

Зачем они нужны?

  • Гибкость: Возможность адаптировать паука под разные задачи, просто меняя параметры запуска.
  • Конфигурация окружения: Использование различных API-ключей или прокси для разных окружений.
  • Тестирование: Легкое изменение параметров для тестирования различных сценариев.
  • Избежание изменений кода: Нет необходимости переписывать код при изменении конфигурационных параметров.

Стандартные способы настройки Scrapy Spider (краткий обзор)

В Scrapy есть несколько стандартных способов настройки Spider:

  1. settings.py: Основной файл конфигурации проекта, где можно задать общие настройки (USERAGENT, CONCURRENTREQUESTS и т.д.).
  2. Аргументы командной строки: Передача настроек при запуске паука.
  3. Spider.custom_settings: Переопределение настроек для конкретного паука.

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

Передача пользовательских параметров при запуске Spider

Использование -a аргумента для передачи параметров через командную строку

Самый простой и распространенный способ передачи пользовательских параметров — использование аргумента -a при запуске паука через командную строку.

Пример:

scrapy crawl my_spider -a api_key=your_api_key -a max_items=100

В этом примере мы передаем два параметра: api_key со значением your_api_key и max_items со значением 100.

Примеры передачи различных типов данных (строки, числа, списки)

Аргумент -a всегда передает значения как строки. Если вам нужно передать числа или списки, необходимо преобразовать их внутри паука.

  • Строка: scrapy crawl my_spider -a query="обувь nike"
  • Число: scrapy crawl my_spider -a max_price=200
  • Список (как строка JSON): scrapy crawl my_spider -a categories='["мужская", "женская", "детская"]'
import scrapy
import json

class MySpider(scrapy.Spider):
    name = "my_spider"
    start_urls = ["http://example.com"]

    def __init__(self, api_key: str = None, max_items: int = 10, categories: str = '[]', **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        self.max_items = int(max_items) # Преобразование в число
        self.categories = json.loads(categories) # Преобразование в список

    def parse(self, response):
        # Используем параметры
        print(f"API Key: {self.api_key}")
        print(f"Max Items: {self.max_items}")
        print(f"Categories: {self.categories}")
        yield {"title": response.css("title::text").get()}

Особенности работы с settings.py и приоритет параметров

Важно понимать, что параметры, переданные через командную строку, имеют более высокий приоритет, чем значения, заданные в settings.py. Это означает, что если вы определите параметр в settings.py и передадите его через -a, значение из командной строки будет использовано.

# settings.py
API_KEY = "default_api_key"
scrapy crawl my_spider -a api_key=your_api_key
# Будет использован api_key=your_api_key

Доступ к пользовательским параметрам внутри Spider

Через атрибут self.settings

Хотя параметры передаются через -a, внутри паука они доступны через атрибут self.settings. Однако, это не рекомендуется для пользовательских параметров, т.к. они могут смешаться с общими настройками Scrapy.

Через метод __init__ и передача параметров как аргументов

Наиболее чистый и рекомендуемый способ доступа к параметрам — передавать их как аргументы в метод __init__ паука. Это делает код более читаемым и явным.

import scrapy

class MySpider(scrapy.Spider):
    name = "my_spider"
    start_urls = ["http://example.com"]

    def __init__(self, api_key: str = None, max_items: int = 10, **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        self.max_items = int(max_items)

    def parse(self, response):
        # Используем параметры
        print(f"API Key: {self.api_key}")
        print(f"Max Items: {self.max_items}")
        yield {"title": response.css("title::text").get()}
Реклама

Примеры использования параметров для конфигурации логики Spider

Параметры можно использовать для управления различными аспектами логики паука:

  • Лимит количества обрабатываемых страниц: max_items.
  • Использование API ключа: api_key.
  • Выбор категорий товаров для парсинга: categories.
  • Настройка задержки между запросами: delay.
import scrapy
import time

class MySpider(scrapy.Spider):
    name = "my_spider"
    start_urls = ["http://example.com"]

    def __init__(self, api_key: str = None, delay: float = 0.5, **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        self.delay = float(delay)

    def parse(self, response):
        # Используем параметры
        print(f"API Key: {self.api_key}")
        time.sleep(self.delay) # Задержка между запросами
        yield {"title": response.css("title::text").get()}

Обработка параметров по умолчанию и валидация

Установка значений по умолчанию для параметров

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

    def __init__(self, api_key: str = "", max_items: int = 10, **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        self.max_items = int(max_items)

Проверка типов данных и допустимых значений параметров

Важно проверять типы данных и допустимые значения параметров, чтобы избежать ошибок во время работы паука. Можно использовать try-except блоки или библиотеки валидации, такие как cerberus или voluptuous.

    def __init__(self, api_key: str = None, max_items: int = 10, **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        try:
            self.max_items = int(max_items)
            if self.max_items <= 0:
                raise ValueError("max_items должен быть больше 0")
        except ValueError as e:
            raise ValueError(f"Некорректное значение max_items: {e}")

Использование argparse для более сложной обработки (опционально)

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

Продвинутые техники работы с параметрами

Использование параметров для динамической настройки Pipeline

Параметры можно использовать для динамической настройки pipeline обработки данных. Например, можно включить/выключить определенные pipeline компоненты в зависимости от значения параметра.

# settings.py
ITEM_PIPELINES = {
    'my_project.pipelines.FilterWordsPipeline': 300,
    'my_project.pipelines.SaveToDatabasePipeline': 400,
}

class MySpider(scrapy.Spider):
    name = "my_spider"

    def __init__(self, enable_db_pipeline: bool = True, **kwargs):
        super().__init__(**kwargs)
        self.enable_db_pipeline = enable_db_pipeline

        if not self.enable_db_pipeline:
            self.settings['ITEM_PIPELINES'].pop('my_project.pipelines.SaveToDatabasePipeline', None)

Передача параметров через Scheduler Middleware (если применимо)

В редких случаях, когда требуется передавать параметры на уровень планировщика запросов (Scheduler Middleware), можно использовать request.meta. Однако, это более сложная и менее распространенная практика.

Практические примеры: настройка лимитов, API ключей и прокси

  • Лимиты запросов: Передача параметра max_requests и ограничение количества запросов в методе parse.
  • API ключи: Передача параметра api_key и использование его в заголовках запросов или URL.
  • Прокси: Передача параметра proxy и настройка прокси для каждого запроса через request.meta['proxy'].
import scrapy

class MySpider(scrapy.Spider):
    name = "my_spider"
    start_urls = ["http://example.com"]

    def __init__(self, api_key: str = None, proxy: str = None, **kwargs):
        super().__init__(**kwargs)
        self.api_key = api_key
        self.proxy = proxy

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url, callback=self.parse, meta={'proxy': self.proxy})

    def parse(self, response):
        # Используем параметры
        print(f"API Key: {self.api_key}")
        print(f"Proxy: {self.proxy}")
        yield {"title": response.css("title::text").get()}

Добавить комментарий