Как создать веб-краулер на Python с помощью Scrapy

Что вы узнаете
- Кратко о Scrapy и зачем он нужен
- Как установить и запустить простого паука
- Как извлекать текст, атрибуты и сохранять в JSON/CSV
- Когда Scrapy не подходит и какие есть альтернативы
- Практический чеклист, методология и меры безопасности
Что такое Scrapy
Scrapy — это фреймворк на Python для парсинга и создания пауков (spiders). Определение в одну строку: Scrapy предоставляет удобные инструменты для обхода страниц, выбора элементов и экспорта данных.
Важно: Scrapy работает на стороне сервера и по умолчанию не выполняет JavaScript. Для сайтов с динамической отрисовкой нужна альтернатива.
Установка Scrapy
Рекомендуется использовать виртуальное окружение, чтобы не менять системные пакеты. Ниже — команды для Unix-подобных систем (Linux, macOS) из исходного материала.
mkdir crawler
cd crawler
virtualenv venv
. venv/bin/activate
Если вы на Windows с стандартным venv:
python -m venv venv
venv\Scripts\activateУстановите Scrapy:
pip install scrapyПроверьте установку:
scrapy
# prints
Scrapy 1.4.0 - no active project
Usage:
scrapy [options] [args]
Available commands:
bench Run quick benchmark test
fetch Fetch a URL using the Scrapy downloader
genspider Generate new spider using pre-defined templates
runspider Run a self-contained spider (without creating a project)
... Совет: используйте pip-tools или Poetry для фиксации зависимостей в проекте.
Создание простого паука
Пример берёт страницу Википедии о батареях. Основные элементы паука:
- name — идентификатор паука
- start_urls — список начальных URL
- parse(self, response) — метод обработки ответа
Исходный код:
import scrapy
class spider1(scrapy.Spider):
name = 'Wikipedia'
start_urls = ['https://en.wikipedia.org/wiki/Battery_(electricity)']
def parse(self, response):
pass
Запустите для теста:
scrapy runspider spider1.py
# prints
2017-11-23 09:09:21 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot)
2017-11-23 09:09:21 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True}
2017-11-23 09:09:21 [scrapy.middleware] INFO: Enabled extensions:
['scrapy.extensions.memusage.MemoryUsage',
'scrapy.extensions.logstats.LogStats',
... Отключение лишних логов
Чтобы лог не забивал консоль, настраиваем уровень логирования:
import logging
logging.getLogger('scrapy').setLevel(logging.WARNING) Это полезно при отладке вывода, когда нужны только явные ошибки и предупреждения.
Как работать с DOM и Chrome Inspector
Вся страница — набор HTML-элементов в структуре DOM. Инструменты разработчика в Chrome помогают быстро находить селекторы:
- Откройте страницу в Chrome
- Наведите мышь на элемент
- Правый клик → Inspect
Панель Elements покажет дерево элементов и поможет сформировать CSS- или XPath-селектор.
Примечание: иногда полезнее строить XPath, если структура сложная или классы динамические.
Извлечение заголовка страницы
Чтобы получить текст заголовка (h1#firstHeading) используйте CSS-селектор с ::text:
...
def parse(self, response):
print response.css('h1#firstHeading::text').extract()
... response.css() возвращает селекторы; добавление ::text и .extract() даёт текстовый контент.
Пример вывода:
[u'Battery (electricity)']Извлечение первого абзаца с описанием
В Chrome вы видите путь:
div#mw-content-text>div>pЧтобы взять первый элемент p:
response.css('div#mw-content-text>div>p')[0] Добавляем ::text и собираем строки в одну:
response.css('div#mw-content-text>div>p')[0].css('::text') Итоговая версия:
def parse(self, response):
print ''.join(response.css('div#mw-content-text>div>p')[0].css('::text').extract()) Это вернёт первый абзац текста страницы.
Сбор структурированных данных в JSON
Scrapy удобно отдаёт элементы через yield — слова-ключи превращаются в записи JSON/CSV при запуске.
Пример: собрать все абзацы в JSON:
...
def parse(self, response):
for e in response.css('div#mw-content-text>div>p'):
yield { 'para' : ''.join(e.css('::text').extract()).strip() }
... Запуск с записью в файл:
scrapy runspider spider3.py -o joe.json Пример вывода (сокращённо):
[
{"para": "An electric battery is a device consisting of ..."},
{"para": "Primary (single-use or \"disposable\") batteries are used once ..."},
...
]Совет: для больших объёмов данных используйте конвейер (Item Pipeline) и подключайте базу данных или облачное хранилище.
Парсинг нескольких элементов в одной записи
Пример с IMDb (boxoffice): извлекаем название, уикенд, суммарно и изображение.
...
def parse(self, response):
for e in response.css('div#boxoffice>table>tbody>tr'):
yield {
'title': ''.join(e.css('td.titleColumn>a::text').extract()).strip(),
'weekend': ''.join(e.css('td.ratingColumn')[0].css('::text').extract()).strip(),
'gross': ''.join(e.css('td.ratingColumn')[1].css('span.secondaryInfo::text').extract()).strip(),
'weeks': ''.join(e.css('td.weeksColumn::text').extract()).strip(),
'image': e.css('td.posterColumn img::attr(src)').extract_first(),
}
... Результат можно экспортировать в JSON или CSV при запуске.
Когда Scrapy не подходит
- Сайты с тяжелым JavaScript, которые динамически рендерят контент. Тогда используйте Selenium, Playwright или headless браузер.
- CAPTCHA, строгие защиты и анти-бот механизмы — потребуются прокси, анти-капча или ручная интеграция, но учтите юридические риски.
- Интерактивные действия (файлы, сложные формы, WebSocket) — иногда проще автоматизировать браузер.
Альтернативные инструменты:
- Selenium / Playwright — имитация реального браузера, выполняют JS
- Requests + BeautifulSoup — лёгкие сценарии без обхода ссылок
- Puppeteer (Node.js) — управление Chrome/Chromium
Практическая методология для одного задания (mini-methodology)
- Определите цель парсинга: какие поля и в каком формате нужны.
- Откройте страницу в браузере и найдите элементы через Inspector.
- Подберите CSS или XPath селекторы и протестируйте их в консоли.
- Напишите паука с аккуратной обработкой ошибок и таймаутами.
- Уважайте robots.txt и Terms of Service сайта.
- Логируйте скорости и ошибки; добавьте повторные попытки и лимиты.
- Экспортируйте в требуемый формат и валидируйте данные.
Чеклист разработчика
- Виртуальное окружение настроено
- Scrapy установлен и запускается
- Селекторы протестированы в Inspector
- Лимит запросов (CONCURRENT_REQUESTS) настроен
- DOWNLOAD_DELAY установлен для вежливости
- User-Agent настроен корректно
- Обработка ошибок/повторных попыток реализована
- Данные сохраняются в нужном формате
- Логи записываются и мониторятся
Рекомендация: задайте DOWNLOAD_DELAY в настройках проекта и используйте AutoThrottle для адаптивной нагрузки.
Шпаргалка по CSS и XPath (cheat sheet)
- CSS по классу: .className
- CSS по id: #elementId
- Дочерний элемент: parent > child
- Любой потомок: ancestor descendant
- Атрибут: a::attr(href) или img::attr(src)
- Текст: ::text
- Первый элемент списка: selector[0]
XPath примеры:
- //div[@id=’mw-content-text’]//p[1] — первый p под div с id
- //table//tr — все строки таблицы
Риски и смягчение
- Юридические вопросы: проверьте Terms of Service и robots.txt. Если есть сомнения — запросите разрешение.
- Блокировка IP: используйте ротацию прокси, но не для обхода законных запретов.
- Перегрузка сервера: ставьте задержки и используйте AutoThrottle.
- Потеря данных: валидируйте экспорт и храните контрольные суммы.
Критерии приёмки
- Паук собирает 95% целевых полей без ошибок при трёх прогонах
- Лимит запросов не превышает политики сайта
- Экспорт в требуемом формате (JSON/CSV) корректен и валиден
- Логи ошибок содержат удобные трассировки для отладки
Пример работы с пагинацией
Типично пагинация реализуется через ссылки “Next”. В parse() найдите ссылку и вызовите response.follow:
for item in response.css('div.listing'):
yield parse_item(item)
next_page = response.css('a.next::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)Решение задач с авторизацией
Если нужен вход в аккаунт:
- Используйте FormRequest для отправки форм логина
- Храните куки через сессии Scrapy
- Для JavaScript-логина — используйте headless браузер
Визуальная логика принятия решения
Ниже — простое дерево выбора между Scrapy и браузерной автоматизацией (Mermaid):
flowchart TD
A[Нужен парсинг] --> B{Контент рендерится JS?}
B -- Нет --> C[Используйте Scrapy]
B -- Да --> D{Можно ли получить API?}
D -- Да --> E[Запросы к API]
D -- Нет --> F[Используйте Playwright/Selenium](Скопируйте блок Mermaid в инструмент, который поддерживает рендеринг.)
Короткое резюме
Scrapy — мощный инструмент для структурированного парсинга: он лёгкий для старта и расширяемый для промышленных задач. Для динамических или защищённых сайтов рассматривайте браузерные решения.
Важно: уважайте правила сайтов и законы о защите данных при сборе и хранении информации.
Короткий список дальнейших шагов:
- Попрактикуйтесь на простых страницах (википедия, блоги)
- Освойте Item Pipelines для сохранения данных
- Изучите middleware и настройки скорости
Похожие материалы
Починить ассоциации .lnk в Windows 7
Исправить проблемы Instagram: обходы и инструменты
Как заменить аккумулятор ноутбука
Звук зарядки MacBook: включить, отключить, изменить
Невидимые символы в документах: как смотреть и исправлять