Scrapy – это мощный фреймворк для веб-скрапинга на Python, позволяющий эффективно извлекать данные из веб-сайтов. Одним из ключевых компонентов Scrapy, обеспечивающих гибкость и расширяемость, являются middleware. Middleware позволяют вмешиваться в процесс обработки запросов и ответов, модифицируя их по мере необходимости.
Обзор и Основные Принципы Scrapy Middleware
Что такое Scrapy Middleware и зачем они нужны?
Scrapy Middleware – это компоненты, которые обрабатывают запросы (requests) и ответы (responses) между движком Scrapy и пауками (spiders). Они позволяют выполнять различные задачи, такие как:
-
Модификация заголовков запросов (User-Agent, Referer и др.).
-
Обработка прокси-серверов для обхода блокировок.
-
Повторные попытки неудачных запросов.
-
Кэширование ответов.
-
Выполнение пользовательской логики обработки ошибок.
Middleware добавляют уровень абстракции, позволяя изменять поведение Scrapy без изменения логики самих пауков.
Типы Middleware: Download и Spider, их различия и области применения
Существует два основных типа middleware в Scrapy:
-
Download Middleware: Обрабатывают запросы, отправляемые движком Scrapy на серверы, и ответы, получаемые от серверов. Они работают на уровне загрузки данных. Пример:
RetryMiddleware,HttpProxyMiddleware. -
Spider Middleware: Обрабатывают запросы, генерируемые пауками, и элементы (items), извлеченные пауками. Они работают на уровне логики пауков. Пример:
DepthMiddleware.
| Тип Middleware | Обрабатываемые Данные | Область Применения | Примеры |
|---|---|---|---|
| Download Middleware | Requests, Responses | Управление загрузкой, прокси, User-Agent, retry. | HttpProxyMiddleware, UserAgentMiddleware, RetryMiddleware |
| Spider Middleware | Requests, Items | Обработка данных, управление глубиной обхода, фильтрация результатов. | DepthMiddleware, OffsiteMiddleware |
Настройка и Использование Стандартных Download Middleware
Настройка User-Agent с помощью Download Middleware
User-Agent – это строка, идентифицирующая браузер пользователя при отправке HTTP-запроса. Изменение User-Agent может помочь избежать блокировок со стороны веб-серверов.
Для настройки User-Agent необходимо:
-
Отключить стандартный
UserAgentMiddleware(если он включен). -
Включить собственный middleware, который будет устанавливать случайный User-Agent из списка.
Пример:
# middlewares.py
import random
class RandomUserAgentMiddleware:
def __init__(self, user_agent_list):
self.user_agent_list = user_agent_list
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.getlist('USER_AGENT_LIST'))
def process_request(self, request, spider):
request.headers['User-Agent'] = random.choice(self.user_agent_list)
# settings.py
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.RandomUserAgentMiddleware': 400,
'scrapy.downloadermiddlewares.user_agent.UserAgentMiddleware': None,
}
USER_AGENT_LIST = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15',
]
Использование прокси-серверов: настройка и ротация прокси
Использование прокси-серверов позволяет скрыть IP-адрес и избежать блокировок. Для работы с прокси необходимо использовать HttpProxyMiddleware.
-
Убедитесь, что
HttpProxyMiddlewareвключен вDOWNLOADER_MIDDLEWARES. -
Создайте middleware для ротации прокси.
Пример:
# middlewares.py
import random
class RandomProxyMiddleware:
def __init__(self, proxy_list):
self.proxy_list = proxy_list
@classmethod
def from_crawler(cls, crawler):
return cls(crawler.settings.getlist('PROXY_LIST'))
def process_request(self, request, spider):
request.meta['proxy'] = random.choice(self.proxy_list)
# settings.py
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.RandomProxyMiddleware': 750,
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': None,
}
PROXY_LIST = [
'http://user1:pass1@proxy1.com:3128',
'http://user2:pass2@proxy2.com:8080',
]
Создание Собственного Spider Middleware: Практические Примеры
Структура и методы создания собственного Spider Middleware
Spider middleware позволяют вмешиваться в процесс обработки запросов, генерируемых пауками, и элементов, извлеченных пауками. Они должны содержать методы process_spider_input, process_spider_output, process_spider_exception, process_start_requests.
class MySpiderMiddleware:
def process_spider_input(self, response, spider):
# Обработка ответа, полученного пауком
return None
def process_spider_output(self, response, result, spider):
# Обработка элементов, извлеченных пауком
for i in result:
yield i
def process_spider_exception(self, response, exception, spider):
# Обработка исключений, возникших в пауке
pass
def process_start_requests(self, start_requests, spider):
# Обработка начальных запросов паука
for r in start_requests:
yield r
Примеры: модификация запросов и обработка ответов в Spider Middleware
Пример 1: Модификация запросов
class AddCustomHeaderMiddleware:
def process_start_requests(self, start_requests, spider):
for request in start_requests:
request.headers['X-Custom-Header'] = 'MyValue'
yield request
Пример 2: Обработка ответов
class FilterItemsMiddleware:
def process_spider_output(self, response, result, spider):
for item in result:
if item['price'] > 100:
yield item
Порядок Выполнения Middleware и Управление Конфигурацией
Порядок выполнения Download и Spider Middleware: приоритеты и настройка
Middleware выполняются в порядке, определенном их приоритетами (порядковым номером). Чем меньше число, тем выше приоритет. Download middleware выполняются в следующем порядке:
-
process_request– от меньшего приоритета к большему. -
process_response– от большего приоритета к меньшему. -
process_exception– от большего приоритета к меньшему.
Spider middleware выполняются аналогично.
Пример:
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.Middleware1': 100,
'myproject.middlewares.Middleware2': 200,
}
В данном примере Middleware1 будет выполняться раньше, чем Middleware2 в методе process_request, и наоборот в методах process_response и process_exception.
Отключение и включение Middleware в проекте Scrapy
Middleware можно включать и отключать в settings.py.
Для включения middleware достаточно добавить его в DOWNLOADER_MIDDLEWARES или SPIDER_MIDDLEWARES и указать приоритет.
Для отключения middleware можно установить его приоритет в None:
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.MyMiddleware': None,
}
Продвинутые Темы и Лучшие Практики
Обработка ошибок и логирование в Middleware
Важно правильно обрабатывать ошибки в middleware, чтобы не прерывать процесс скрапинга. Для этого используйте блоки try...except и логирование.
import logging
class ErrorHandlingMiddleware:
def process_request(self, request, spider):
try:
# Какая-то логика
pass
except Exception as e:
logging.error(f'Error processing request {request.url}: {e}')
# Можно вернуть Response или Request для повторной обработки
return
Тестирование и отладка Scrapy Middleware
Для тестирования middleware можно использовать юнит-тесты.
-
Создайте тестовый проект Scrapy.
-
Напишите тесты для middleware, используя
unittestилиpytest. -
Проверьте, что middleware работает корректно в различных сценариях.
Для отладки используйте логирование и дебаггер Python (например, pdb).
Заключение и Дальнейшее Развитие
Scrapy middleware – мощный инструмент для расширения функциональности Scrapy. Правильная настройка и использование middleware позволяет эффективно решать задачи, связанные с веб-скрапингом, такие как обход блокировок, обработка ошибок и модификация данных. Для дальнейшего развития рекомендуется изучить документацию Scrapy и экспериментировать с различными типами middleware.