Настраиваем паука для сбора данных: как работает фреймворк Scrapy
В Точке мы обучаем наших AI-ассистентов, а для этого нужно много данных. В статье расскажу, как быстро собрать информацию практически с любого сайта при помощи фреймворка Scrapy.
233 открытий2К показов

В Точке мы обучаем наших AI-ассистентов, а для этого нужно много данных. В статье расскажу, как быстро собрать информацию практически с любого сайта при помощи фреймворка Scrapy.
Зачем компании собирают данные
Сегодня в интернете более 1 миллиарда сайтов. На великом и ужасном реддите каждый час появляется более 50 000 новых публикаций. На Github уже опубликовано более 300 млн публичных репозиториев. Всё это — открытые данные, которые можно использовать и, главное — собирать. Разумеется, перед этим проверить условия использования сайта, потому что некоторые из них могут запрещать сбор данных.
Зачем это нужно компаниям:
- Анализ рынка: для ритейла это возможность изучить клиентов и конкурентов.
- Мониторинг сайтов вендоров ПО: некоторые компании выкладывают уязвимости в своих продуктах и делятся возможными решениями.
- Создание продукта: собранные данные можно обогатить, прикрутить красивый интерфейс, умный поиск и предложить пользователю новое приложение, типа 2GIS.
- Развитие LLM: например, Google в 2024 году заключил контракт с Reddit на сбор данных. Open AI тоже часто говорят о том, что обучают свою модель на открытых источниках, а в ближайшее время хотят подключить ещё и транскрибации с YouTube.
Как вы поняли, в интернете очень много данных. И если мы хотим их собрать, то нам нужен подходящий инструмент.
Что такое Scrapy
Это высокоуровневый фреймворк на Python для краулинга и скреппинга сайтов. На GitHub у него больше 53 тысяч звёздочек, 10,6 тысяч форков и много глазиков. А ещё он занимает первое место по тегам #crawling и #scraping.
Есть много причин, почему Scrapy так популярен:
- Это фреймворк с готовой архитектурой — там много инструментов, доступных из коробки, которые можно настроить и использовать.
- Он асинхронный — чаще возникает задача замедлить его, чем ускорить.
- У него простые настройки — нужно всего раз подумать над архитектурой, а добавление новых источников будет занимать минимум времени.
- Scrapy удобно дебажить в любой момент, начиная от загрузки страницы и заканчивая сохранением данных в базе.
- Есть продуманные селекторы, доступны CSS, Xpath. Их можно комбинировать или выбрать что-то одно.
- Большое комьюнити и обновляемая документация. Ответы на большинство вопросов можно легко найти в сети.
Scrapy точно подойдёт вам, если во всех ваших источниках одинаковый формат данных и вы можете унифицировать их обработку и сохранение. Но всё-таки его нельзя назвать универсальным инструментом.
Scrapy будет не лучшим выбором, если:
- Нужно собрать малый объем данных или собрать их нужно всего один раз.
- Вам нужно отдать просто сырые html или json, а не парсить и преобразовывать данные.
- Среди источников нет общей структуры данных.
Во всех этих случаях мы можем использовать Scrapy, но, скорее всего, он будет излишним.
Как работает Scrapy
После того, как вы установили Scrapy в виртуальное окружение ( '' pip instal scrapy' ) и создали новый проект ( ' scrapy startprogect scraper '' ), вам необходимо написать своего первого «паука».
В Scrapy используется класс spider — он определяет, как мы будем извлекать данные из сайтов. Допустим, нам нужно собрать информацию с одностраничного сайта. Создаём класс TestSpider, наследуемся от scrapy.Spider, добавляем атрибут name с уникальным именем и start_urls, где укажем страницы, с которых нужно начать поиск. После этого переопределим метод parse.
Parse является дефолтным для обработки ответов. Если вы сделаете request и не укажете функцию, которая должна его обработать, то ответ от запроса придёт в метод parse. Поэтому его, как минимум, нужно переопределить и назначить логику.
Допустим, нас интересует информация о компании — название и описание. Можем создать объект данных с двумя элементами — title и content, и с помощью двух xpath селекторов забрать со страницы заголовок и описание.
В конце передаём этот объект данных для последующей обработки в ядро. Это всё, что нужно, чтобы начать парсинг на Scrapy.
Обработка данных в Scrapy
Дальше в ход вступает PipeLine. Он отвечает за обработку данных, валидацию или сохранение. В Scrapy есть пайплайны, готовые из коробки, но вы также можете написать их самостоятельно.
В ValidatePipeline мы проверяем объект данных на наличие title, а в SavePipeline — сохраняем объект в качестве json.
Здесь я просто показал, как можно создать пайплайн самостоятельно. Но имейте в виду, что это не очень отказоустойчивый код, поэтому в проде так делать не стоит.
Зачем нужен Middleware
Middleware очень похож на PipeLine, только он обрабатывает не объекты данных, а запросы и ответы от сайта.
В Scrapy есть несколько разных middleware:
- scheduler middleware: помещает запросы в очередь и извлекает их для обработки.
- spider middleware: управляет данными между пауком и ядром.
- downloader middleware: управляет данными между ядром и загрузчиком.
Получается такая схема работы компонентов Scrapy:
Запрос: Spider → Spider Middleware → Engine → Scheduler Middleware → Scheduler → Engine → Downloader Middleware → Downloader → Server (сайт)
Ответ: Server → Downloader → Downloader Middleware → Engine → Spider Middleware → Spider → Item Pipeline → Storage (хранилище данных)
Скорее всего, в первую очередь вы будете настраивать downloader middleware, поэтому разберём его подробнее.
Ниже продемонстрировал два примера, как можно написать свой Middleware. В RandomProxyMiddleware мы обрабатываем все запросы, которые будет отсылать наш паук с помощью метода process_request (добавляем рандомную прокси к каждому реквесту), а в CheckCaptchaMiddleware — обрабатываем все ответы с помощью метода process_response (проверяем ответ от сайта, ищем в нём слово captcha).
Итак, мы написали Pipeline и Middlewares. Дальше нужно указать, как мы будем их использовать. Для этого запишите их в файле settings.py, где находятся настройки проекта.
Начнём с пайплайнов. Цифра справа — это порядковый номер выполнения. То есть первым будет ValidatePipeLine, а вторым сработает SavePipeline. Обычно цифры указываются от 0 до 1000. И в случае с пайплайнами чем ниже цифра, тем раньше сработает пайплайн.
В случае с middleware картина такая же, но логика немного иная.
Каждый middleware может обрабатывать как request, так и response. При этом middleware стоит посередине между ядром, который отправляет запросы, и загрузчиком. Если ваша middleware обрабатывает запросы, то сработает первой та, что указана с меньшей цифрой, потому что она ближе к ядру. А если middleware обрабатывает ответы, то первой будет та, у которой цифра больше, потому что она дальше от ядра и ближе к загрузчику.
Об этот нюанс часто спотыкаются новички, хотя, скорее всего, он прописан в документации.
Пример, как использовать Scrapy
Рассмотрим, как с помощью одного селектора собрать сайт любой вложенности и архитектуры.
Для начала создаём класс паука, наследуемся от scrapy.Spider, указываем name, start_urls и атрибут allowed_domains — он необязательный, но в данном случае без него не обойтись. В нём мы укажем список хостов, на которые разрешаем ходить нашему пауку, чтобы он не начал собирать другие сайты.
Дальше переопределяем метод parse и, когда к нам приходит ответ от сайта, находим все ссылки. И это и есть тот единственный xpath селектор, который поможет обойти весь сайт и собрать страницы.
Все ссылки помещаем в переменную url в качестве списка, а потом этот список передаём в функцию follow_all объекта response.
Чтобы дописать сохранение, просто передаём объект response вглубь ядра Scrapy, где напишем какой-то нехитрый пайплайн и будем сохранять html-страницы. Так можно собрать абсолютно любой сайт, просто подставьте ссылку на него в start_urls.
Важный нюанс: под капотом follow_all сделает запросы к сайту по всем ссылкам, которые мы нашли на странице. И поскольку в follow all мы не указываем определённый метод в параметре callback, то все ответы придут сюда же в метод parse (потому что он дефолтный в Scrapy). Эта логика будет повторяться на каждой странице.
Ещё в Scrapy есть внутренний фильтр, поэтому если паук соберёт дубликаты, то автоматически зафильтрует их и не будет проходить по ссылкам дважды.
Немного итогов
Scrapy — это большой, сложный, но очень хороший фреймворк, как Django в веб-разработке. Он предлагает большой выбор готовых инструментов для сбора и обработки данных, а также, поддерживает асинхронное выполнение задач, что ускоряет процесс парсинга.
Scrapy может показаться трудным для новичков, но у него есть богатая документация и примеры, поэтому при желании в нём нетрудно разобраться.
233 открытий2К показов