Архитектура Scrapy: путь запроса по конвейеру
Понять Scrapy — значит понять путь одного запроса через его компоненты.
В сердце Scrapy — движок (Engine), который дирижирует потоком данных между пауком, планировщиком (Scheduler), загрузчиком (Downloader) и пайплайнами (Item Pipeline). Понимание этого цикла объясняет, где что настраивать.
Scrapy кажется магией, пока не увидишь его архитектуру. На самом деле это конвейер с понятными станциями. Проследим путь данных по официальной схеме фреймворка.
┌─────────────────── ДВИЖОК (Engine) ───────────────────┐
│ дирижёр: гоняет данные по кругу │
v ^ ^ v
┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────┐
│ ПАУК │ items │ПЛАНИРОВ- │ req │ ЗАГРУЗЧИК │ resp │ ПАЙПЛАЙН │
│ (Spider)│ -----> │ ЩИК │ ----> │(Downloader)│ ---> │(Pipeline)│
│ parse() │ <----- │(очередь) │ <---- │ HTTP-запрос│ │ чистка/БД│
└─────────┘ req └─────────┘ resp └──────────┘ └──────────┘
1. паук отдаёт первый Request -> 2. планировщик ставит в очередь
3. загрузчик качает страницу -> 4. паук парсит ответ
5. данные идут в пайплайн -> 6. новые ссылки -> снова в очередьКто за что отвечает
| Компонент | Роль |
|---|---|
| Spider (паук) | Твой код: что качать и как парсить |
| Scheduler (планировщик) | Очередь запросов, дедупликация URL |
| Downloader (загрузчик) | Асинхронно скачивает страницы по HTTP |
| Item Pipeline | Чистит, валидирует и сохраняет данные (в БД, файл) |
| Middlewares | Хуки в потоке: заголовки, прокси, повторы, robots.txt |
Как работает под капотом
Цикл такой: движок берёт у паука первый Request и отдаёт планировщику. Планировщик кладёт его в очередь (и отбрасывает дубли URL). Загрузчик асинхронно качает страницу и возвращает Response. Движок передаёт ответ пауку — тот в parse выдаёт данные и новые запросы. Данные уходят в пайплайн (чистка, запись в базу), новые запросы — обратно в планировщик. Так колесо крутится, пока очередь не опустеет. Middleware — это точки врезки: например, RobotsTxtMiddleware проверяет robots.txt, а другой может подставлять прокси или User-Agent.
Попробуй сам ▶
# смоделируем планировщик Scrapy: очередь + дедупликация URL
from collections import deque
queue = deque(['/page1'])
seen = {'/page1'}
# что 'находит' паук на каждой странице
found = {'/page1': ['/page2', '/page1'],
'/page2': ['/page3', '/page2'],
'/page3': ['/page1']}
visited = []
while queue:
url = queue.popleft()
visited.append(url)
for link in found.get(url, []):
if link not in seen: # дедупликация!
seen.add(link)
queue.append(link)
print('Обойдено:', visited)
print('Дублей не было — каждый URL ровно один раз')Asyncio под капотом и роль движка
Ключ к производительности Scrapy — асинхронность. Исторически фреймворк построен на Twisted, а в современных версиях интегрирован и с asyncio. Смысл один: загрузчик не блокируется в ожидании ответа сервера. Пока летят и ждут сотни запросов, процессор не простаивает — он обрабатывает уже пришедшие ответы. Поэтому Scrapy на одном ядре обгоняет наивный последовательный скрипт в десятки раз, не прибегая к сложной ручной многопоточности.
Движок (Engine) в этой схеме — диспетчер, который никогда не «решает» сам, что парсить, а лишь передаёт объекты между компонентами по строгому протоколу. Именно поэтому каждую станцию конвейера можно настраивать и расширять независимо: подменить планировщик, добавить middleware для прокси, вставить пайплайн валидации — и остальное продолжит работать. Эта развязанность (loose coupling) — образец хорошей архитектуры: понимая, какой объект на каком этапе движется, ты точно знаешь, где вмешаться, чтобы изменить поведение краулера, не ломая всё остальное.
Частые ошибки
- Сохранять данные прямо в пауке. Запись в БД — задача пайплайна, а не
parse. - Не пользоваться дедупликацией. Планировщик сам отбрасывает повторы URL — не дублируй обход вручную.
- Лезть в middleware без нужды. Большинство задач решаются настройками; кастомный middleware — для особых случаев (прокси, ротация UA).
Best practices
- Держи паука тонким: только «что качать и как парсить». Логику сохранения вынеси в пайплайн.
- Чистку и валидацию данных делай в Item Pipeline — это его прямая задача.
- Используй middleware для сквозных задач: прокси, повторы, заголовки, соблюдение robots.txt.
Понимание архитектуры окупается ровно тогда, когда что-то идёт не так. Данные не сохраняются — смотри пайплайн. Сайт блокирует — смотри downloader middleware (заголовки, прокси). URL обходятся не те — смотри логику паука и правила следования по ссылкам. Краулер слишком быстрый — смотри настройки и AutoThrottle. Зная, какой компонент за что отвечает, ты диагностируешь проблему за минуты вместо часов наугад. Архитектурная карта — это, по сути, карта мест, где можно вмешаться.
Итог: Scrapy — это конвейер «паук → планировщик → загрузчик → пайплайн», которым дирижирует движок. Понимая роли, ты знаешь, где настраивать вежливость, где чистить данные, а где подключать прокси.