Гид по технологиям

Веб-краулер на Python с Scrapy

6 min read Программирование Обновлено 30 Dec 2025
Веб-краулер на Python с Scrapy
Веб-краулер на Python с Scrapy

Фото ноутбука с кодом для краулера и открытой страницей в браузере

Веб-краулеры (web crawlers, spiders) — программы для автоматического чтения информации с веб-страниц. Их можно применять для получения котировок, спортивных результатов, текстов из социальных сетей или цен с торговых площадок. Python и библиотека Scrapy упрощают создание таких программ: Scrapy быстрый, расширяемый и умеет переходить по страницам и извлекать данные.

Ниже — подробная инструкция с практическими примерами, рекомендациями по отладке и безопасной эксплуатации, а также набором вспомогательных материалов: чек-листы, критерии приёмки, мини-SOP, сценарии тестирования и дерево решений для выбора стратегии сбора.

Установка Scrapy

Scrapy — это библиотека Python для веб-скрейпинга и создания пауков. Рекомендуется устанавливать её в виртуальное окружение, чтобы не трогать глобальные системные зависимости.

Создание виртуального окружения и установка Scrapy (Linux/macOS):

mkdir crawler
cd crawler
python3 -m venv venv
. venv/bin/activate
pip install --upgrade pip
pip install scrapy

Windows (PowerShell):

mkdir crawler
cd crawler
python -m venv venv
venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install scrapy

Проверка установки:

scrapy
# ожидаемый вывод (сокращённый):
# Scrapy X.Y.Z - 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)

Совет: используйте последнюю стабильную версию Python 3 и поддерживаемую версию Scrapy. На машинах CI обычно достаточно виртуального окружения и установки зависимостей через requirements.txt.

Как устроен паук Scrapy

Класс паука наследуется от scrapy.Spider и описывает: имя паука, список стартовых URL и метод parse для обработки ответа.

Пример простого паука (Python 3):

import logging
logging.getLogger('scrapy').setLevel(logging.WARNING)

import scrapy

class WikipediaSpider(scrapy.Spider):
    name = 'wikipedia'
    start_urls = ['https://en.wikipedia.org/wiki/Battery_(electricity)']

    def parse(self, response):
        # Здесь мы пока ничего не возвращаем
        print('Страница загружена:', response.url)

Запуск самодостаточного файла:

scrapy runspider spider1.py

Важно: в реальном проекте принято создавать проект Scrapy (scrapy startproject myproject) и держать пауков в папке spiders. Для быстрых экспериментов удобно использовать runspider.

Отключение лишних логов

Если вывод логов мешает, можно повысить уровень логирования для модуля scrapy:

import logging
logging.getLogger('scrapy').setLevel(logging.WARNING)

Это простой способ видеть только предупреждения и ошибки.

Использование инспектора браузера для поиска селекторов

Веб-страница — это документ HTML, представленный деревом DOM. Инструменты разработчика в Chrome и других браузерах позволяют быстро найти нужный элемент:

  • Откройте страницу в браузере
  • Наведите курсор на элемент
  • Правый клик → Inspect

Во вкладке Elements вы увидите DOM-дерево. Выбирайте селекторы (CSS или XPath) по структуре элементов.

Короткое определение: CSS-селектор — строка, которая описывает путь к элементам в дереве DOM (напр., div#mw-content-text > div > p).

Извлечение заголовка страницы

Чтобы получить заголовок статьи Wikipedia, используйте CSS-селектор для заголовка h1 с идентификатором firstHeading.

def parse(self, response):
    title = response.css('h1#firstHeading::text').get()
    print('Заголовок:', title)

Разъяснение: response.css() возвращает объект селектора, ::text выбирает текстовое содержимое, .get() возвращает первое совпадение как строку. Аналогично есть .getall() (или в старых версиях .extract()) для списка совпадений.

Извлечение первого абзаца

Селектор для первого абзаца в основной части статьи:

div#mw-content-text > div > p

Пример кода, который собирает первый абзац в одну строку:

def parse(self, response):
    first_p = response.css('div#mw-content-text>div>p').get()  # вернёт HTML первого 

# если нужно только текст внутри: first_p_text = ''.join(response.css('div#mw-content-text>div>p')[0].css('::text').getall()).strip() print(first_p_text)

Пояснение: иногда текст разбивается на несколько текстовых узлов (ссылки, сноски), поэтому удобно собрать список .getall() и соединить через ‘’.

Сбор данных в JSON

Scrapy умеет возвращать словари (yield {…}), которые затем можно автоматически экспортировать в JSON, CSV или другие форматы при запуске.

Пример: извлекаем все абзацы и возвращаем как JSON-объекты:

def parse(self, response):
    for e in response.css('div#mw-content-text>div>p'):
        text = ''.join(e.css('::text').getall()).strip()
        if text:
            yield {'para': text}

Запуск и экспорт в файл:

scrapy runspider spider3.py -o output.json

Формат JSON будет представлять собой массив объектов с полем para.

Извлечение нескольких полей и атрибутов

На странице IMDb таблица бокс-офиса может выглядеть как набор строк. Пример извлечения title, weekend, gross, weeks, image:

def parse(self, response):
    for e in response.css('div#boxoffice>table>tbody>tr'):
        yield {
            'title': ''.join(e.css('td.titleColumn>a::text').getall()).strip(),
            'weekend': ''.join(e.css('td.ratingColumn').getall()[0].css('::text')).strip() if e.css('td.ratingColumn') else None,
            'gross': ''.join(e.css('td.ratingColumn')[1].css('span.secondaryInfo::text').getall()).strip() if len(e.css('td.ratingColumn'))>1 else None,
            'weeks': ''.join(e.css('td.weeksColumn::text').getall()).strip(),
            'image': e.css('td.posterColumn img::attr(src)').get(),
        }

Пояснение: для атрибутов картинок используйте ::attr(src); если нужно первое совпадение — .get().

Частые проблемы и способы их решения

  • Динамический контент (JS): Scrapy по умолчанию не исполняет JavaScript. Решения: 1) искать API, 2) использовать headless-браузер (Playwright, Selenium) и интегрировать результаты в Scrapy, 3) смотреть сетевые запросы в DevTools.
  • Защита от ботов: капчи, проверка заголовков, rate limiting. Смягчайте нагрузку: добавьте задержки, случайные user-agent, обработку ошибок.
  • Изменяющаяся разметка: пишите устойчивые селекторы, тестируйте на разных версиях страницы.

Important: всегда уважайте robots.txt и условия использования сайтов. Некоторые сайты запрещают автоматический сбор данных — убедитесь, что вы имеете права на скрейпинг.

Альтернативные подходы

  • requests + BeautifulSoup — для простых страниц без JS.
  • Selenium/Playwright — для сложных страниц с рендерингом в браузере.
  • API — если сайт предоставляет публичный API, его использование предпочтительнее.

Мини-методология разработки паука (шаблон)

  1. Исследуйте страницу в браузере, найдите нужные селекторы.
  2. Попробуйте извлечь данные в interactive shell (scrapy shell ‘URL’).
  3. Напишите минимальный spider с yield-структурой.
  4. Локально запускайте и проверяйте экспорт в JSON/CSV.
  5. Добавьте обработку ошибок, retries и логирование.
  6. Напишите тесты (unit/integration) для основных селекторов.
  7. Запустите в контролируемой среде и мониторьте.

Дерево решений: как выбрать стратегию сбора

flowchart TD
    A[Нужно извлечь данные?] --> B{Страница статична?}
    B -- Да --> C[requests + BeautifulSoup]
    B -- Нет --> D{Есть публичный API?}
    D -- Да --> E[Использовать API]
    D -- Нет --> F[Selenium/Playwright или Scrapy+headless]
    C --> G[Простой парсер]
    E --> G
    F --> G

Контрольные списки по ролям

Разработчик:

  • выбрать селекторы и протестировать в scrapy shell
  • написать spider и обработку ошибок
  • оформить экспорт

Data Engineer:

  • убедиться, что формат данных стабильный
  • настроить хранение (S3, базу данных)
  • настроить периодичность и мониторинг

QA:

  • создать тесты на ключевые селекторы
  • проверить поведение при пустых и частично заполненных страницах

Юрист/Compliance:

  • проверить robots.txt и условия использования
  • оценить наличие персональных данных и требования GDPR/локального законодательства

Критерии приёмки

  • Скрипт успешно запускается и завершает обход стартовых URL
  • Данные экспортируются в ожидаемый формат (JSON schema)
  • Нет повторяющихся записей (если это важно)
  • Лимит запросов и задержки настроены, чтобы не создавать чрезмерную нагрузку
  • Обработка ошибок и повторных попыток настроена

Сценарии тестирования и примеры приемочных тестов

  1. Тест: стартовая страница недоступна → ожидание повторной попытки и корректный лог.
  2. Тест: селектор не найден → spider пропускает запись и логирует предупреждение.
  3. Тест: динамический контент → проверка fallback-стратегии (поиск API или headless-браузер).
  4. Тест: корректность JSON-схемы для выборки полей.

Безопасность и приватность

  • Собирайте только необходимые данные. Не сохраняйте лишние персональные данные.
  • Для данных, содержащих персональные сведения, согласуйте правовую основу (согласие, законный интерес и т.п.).
  • Ограничивайте хранение персональных данных и защищайте хранилище (шифрование, доступ по ролям).

Notes: если вы планируете массовый сбор данных по пользователям из ЕС, проконсультируйтесь с юристом по GDPR.

SOP для запуска паука (короткая инструкция)

  1. Активировать виртуальное окружение.
  2. Обновить зависимости: pip install -r requirements.txt.
  3. Запустить паука: scrapy crawl wikipedia -o output.json.
  4. Проверить размер и целостность output.json.
  5. Если всё успешно — загрузить файл в хранилище и отметить задачу завершённой.

План отката (rollback)

  • Если паук начал генерировать некорректные данные, остановить расписание.
  • Откатить изменения к последней рабочей версии паука в системе контроля версий.
  • Проверить журналы и при необходимости восстановить удалённые/повреждённые данные из бэкапа.

Советы по устойчивости и масштабированию

  • Используйте middleware для ротации user-agent и прокси.
  • Добавьте AutoThrottle для контроля скорости запросов.
  • Горизонтальное масштабирование: запуск множества ведомых процессов с контролем за уникальными URL (очередь задач в Redis/БД).

Совместимость и миграция

  • Проверьте поддержку Python 3.x для выбранной версии Scrapy.
  • При миграции со старых версий Scrapy замените .extract() на .getall()/.get() там, где это уместно.

Когда Scrapy не лучший выбор

  • Если вам нужно рендерить сложный JavaScript и поддержка headless-браузера критична, возможно, лучше использовать Playwright или Selenium напрямую.
  • Для очень простых одностраничных задач проще requests + BeautifulSoup.

Заключение

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

Краткий план дальнейших шагов:

  • протестируйте селекторы в scrapy shell;
  • напишите адаптивный парсер с обработкой ошибок;
  • определите политику хранения и соответствие требованиям конфиденциальности;
  • автоматизируйте и мониторьте работу паука.

Summary:

  • Scrapy упрощает парсинг HTML и экспорт в JSON/CSV.
  • Учитывайте robots.txt и правила сайтов.
  • Для динамических страниц используйте headless-браузеры или ищите API.
  • Пишите тесты и план отката до запуска в продакшен.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Гладкие линии в Adobe Illustrator
Дизайн

Гладкие линии в Adobe Illustrator

Музыкальные символы в Word и Excel — как вставить
Документы

Музыкальные символы в Word и Excel — как вставить

Обрезка изображений в Adobe Illustrator
Дизайн

Обрезка изображений в Adobe Illustrator

Как сделать треугольник в Adobe Illustrator
Дизайн

Как сделать треугольник в Adobe Illustrator

Паутину в Adobe Illustrator: быстрый метод
Иллюстрация

Паутину в Adobe Illustrator: быстрый метод

Масштабирование обводок в Illustrator
Design

Масштабирование обводок в Illustrator