Разработка · 6 мин чтения

Топ ошибок при разработке парсера сайта и как их избежать

За пять лет пишу парсеры для интернет-магазинов, агрегаторов цен и B2B-каталогов и вижу одни и те же грабли раз за разом. Разработка парсера сайта на первый взгляд кажется задачей на вечер: открыл requests, распарсил HTML, сохранил в CSV. На практике из проектов, которые приходят ко мне на доработку после самостоятельной попытки, большинство спотыкается на одних и тех же ошибках - от неправильного выбора библиотеки до отсутствия обработки блокировок. Разберу главные промахи по пунктам и покажу, как их обойти на реальных кейсах.

Ошибки планирования перед началом сбора данных с сайта

Самая частая ошибка - сесть писать код раньше, чем открыть сайт руками и посмотреть, как он устроен. Проверяю три вещи в первый час: рендерится контент на сервере или подгружается через JS, есть ли пагинация или бесконечный скролл с подгрузкой по scroll-событию, и сколько всего страниц предстоит обойти.

Один из клиентов пришёл с задачей собирать каталог интернет-магазина на WooCommerce - 40 000 товаров, обновление цен раз в сутки. Предыдущий подрядчик написал парсер за вечер на requests, запустил в 20 потоков и через три дня получил блокировку по IP на уровне хостинга магазина. Никто не заложил ни ограничение скорости запросов, ни план на случай бана. Пришлось переписывать архитектуру с нуля: очередь задач, ротацию IP и логирование каждого ответа сервера.

Перед стартом фиксирую письменно: какие поля нужно вытащить, откуда брать пагинацию, что делать при 403/429 ответе, куда складывать результат. Без этого на середине проекта всплывают требования, из-за которых код переписывается по третьему разу.

Неправильный выбор инструмента для скрапинга сайта

Вторая по частоте ошибка - тянуть Selenium или Playwright туда, где хватило бы requests, или наоборот пытаться распарсить сайт на React через BeautifulSoup, получая пустой HTML без данных.

Инструмент Когда использовать Скорость Порог входа
requests + BeautifulSoup Статический HTML, контент есть в исходном коде страницы Высокая, десятки страниц в секунду Низкий
Scrapy Массовый обход тысяч страниц, нужна очередь, retry, экспорт Высокая при параллелизме Средний
Playwright / Selenium Контент рендерится через JS, есть бесконечный скролл или клики Низкая, секунды на страницу Средний-высокий

На практике для мониторинга цен на маркетплейсах и в интернет-магазинах хватает связки requests + lxml в 80% случаев - большинство карточек товара отдают HTML сразу, без JS. Playwright беру, когда фильтры и сортировка на сайте работают через AJAX-запросы, а искать эти запросы в DevTools дольше, чем просто открыть браузер программно.

Пример из кода - минимальная проверка перед стартом сбора, что сайт вообще разрешает обращаться к разделу:

import time
import random
from urllib.robotparser import RobotFileParser

rp = RobotFileParser()
rp.set_url("https://example.com/robots.txt")
rp.read()

if rp.can_fetch("*", "https://example.com/catalog"):
    time.sleep(random.uniform(1.5, 3.5))  # соблюдаем rate-limit
    # запрос к странице
else:
    print("Раздел закрыт для сбора по robots.txt")

Бесплатный материал

🎁 Полезный скрипт в подарок

Подпишитесь на Telegram - пришлю готовый скрипт по этой теме.

Без спама. Отписка в 1 клик.

Игнорирование rate-limit и robots.txt при парсинге

Сайты закрывают доступ ботам не из вредности - так они защищают сервер от перегрузки. Если гнать 50 параллельных запросов на сайт с обычным хостингом, для него это выглядит как нагрузочная атака, и блокировка прилетает заслуженно.

Рабочая схема, которую использую в проектах: читаю robots.txt и уважаю Disallow, ставлю случайную задержку между запросами 1-3 секунды вместо фиксированной (боты с равными интервалами вычисляются легко), ограничиваю число одновременных соединений к одному домену до 2-5. Для СДЭК и других сервисов с публичным API для расчёта доставки вообще не парсю HTML - беру официальный API, там нет смысла изобретать велосипед.

Есть отдельная категория задач - сбор открытых данных без авторизации с сайтов конкурентов для мониторинга цен. Это легальная и распространённая практика, если соблюдать rate-limit, не запрашивать закрытые разделы за логином и не собирать персональные данные посетителей. Как только в скрипте появляется логика для работы с личным кабинетом или карточками клиентов, это уже другая история с другими рисками, и я такие задачи обсуждаю отдельно.

Ошибки хранения и структуры данных после сбора информации

Парсер, который просто складывает всё в один CSV без ключей и дедупликации, живёт до первого повторного запуска - данные задваиваются, и через месяц в файле каша. Проектирую структуру заранее: уникальный идентификатор товара или записи (артикул, SKU, URL), дата сбора, статус изменения (новая запись, обновление цены, товар пропал из каталога).

Для объёмов до нескольких сотен тысяч строк беру SQLite - не нужен отдельный сервер, база - один файл, удобно бэкапить. Если данные нужно отдавать в CRM или на сайт в реальном времени, ставлю PostgreSQL и пишу отдельный сервис синхронизации. Для интеграции с T‑Bank или другим эквайрингом при автоматическом обновлении цен в WooCommerce важно, чтобы обновление шло не напрямую в базу магазина, а через API - иначе после следующего обновления плагина структура таблиц может измениться и импорт сломается молча.

Готовые шаблоны для выгрузки собранных данных в таблицы и CRM я собрал в библиотеке готовых скриптов - там есть варианты под разные форматы хранения, можно взять за основу и не писать структуру с нуля.

Проблемы с блокировками и ротацией IP при автоматическом сборе данных

Когда сайт начинает возвращать капчу или 403 через раз, первая реакция - воткнуть больше потоков и попробовать продавить. Это только ухудшает картину: сайт видит аномальный трафик и банит диапазон IP целиком.

Что реально работает: ротация IP через пул прокси вместо одного постоянного адреса, рандомизация отпечатка браузера (заголовки, User-Agent, порядок полей) вместо одного и того же набора на все запросы, экспоненциальная задержка при повторных попытках вместо мгновенного retry. Для проектов с ежедневным сбором данных с десятков тысяч страниц закладываю в бюджет ротацию прокси отдельной строкой - без неё стабильность сборщика держится неделю-две, а потом сайт меняет правила и всё встаёт.

Отдельная ошибка - не мониторить сам факт блокировки. Если парсер молча получает пустые страницы и пишет их в базу как валидные, вы неделю собираете мусор и узнаёте об этом, когда менеджер спрашивает, почему цены в отчёте не менялись с прошлого вторника.

Как поддерживать парсер после запуска в продакшн

Сайты меняют вёрстку без предупреждения - обновили дизайн каталога, и селекторы, которые вчера работали, сегодня возвращают None. Парсер без мониторинга падает тихо, и об этом узнают через две недели, когда данные в отчётах перестают биться с реальностью.

Ставлю на такие проекты простую схему: cron или n8n запускает скрипт по расписанию, при ошибке или нулевом количестве собранных записей улетает уведомление в Telegram через бота на aiogram - так о сбое узнают в течение минуты, а не через неделю. n8n удобен именно для оркестрации: расписание, повторные попытки, ветвление на случай ошибки - без него пришлось бы писать этот слой руками на каждом проекте заново.

Сколько стоит поддержка, зависит от того, сколько сайтов-источников и как часто они меняют структуру. Разработка самого парсера у меня начинается от 20 000 ₽, а на регулярное сопровождение - проверку селекторов, обновление логики под изменения сайта-источника - беру от 15 000 ₽ в месяц.

Данные и процессы на автопилоте

Парсинг / Автоматизация

от 20 000 ₽

Подробнее →

Частые вопросы

Сколько стоит разработка парсера сайта под ключ?

Простой сборщик по статическому HTML с выгрузкой в таблицу начинается от 20 000 ₽. Если сайт рендерит контент через JS, нужна ротация IP или интеграция с CRM и эквайрингом вроде T‑Bank - стоимость считаю индивидуально после того, как посмотрю структуру сайта-источника и объём данных.

Легально ли парсить сайты конкурентов для мониторинга цен?

Сбор открытых данных без авторизации с публичных страниц - обычная и законная практика, если соблюдать rate-limit, не заходить в закрытые разделы за логином и не собирать персональные данные посетителей. Проблемы начинаются, когда парсер лезет туда, куда доступ явно закрыт, или начинает создавать нагрузку, сравнимую с атакой.

Как часто нужно обновлять парсер после запуска?

Зависит от сайта-источника: крупные каталоги и маркетплейсы меняют вёрстку в среднем раз в 2-4 месяца. Проверяю работоспособность через уведомления от самого скрипта - если сборщик вдруг возвращает ноль записей за проход, это сигнал, что пора чинить селекторы, а не ждать планового аудита.

Можно ли собирать данные с сайта без программирования, через n8n?

Для простых случаев - да: нода HTTP Request плюс парсинг HTML внутри n8n закрывает задачу, если сайт отдаёт статический контент и страниц немного. Как только нужна пагинация с сотнями страниц, обход блокировок с ротацией IP или рендеринг JS-контента, быстрее и дешевле написать отдельный скрипт на Python, а n8n оставить для расписания и уведомлений.

Есть задача?

Обсудим в мессенджере

Расскажите, что нужно сделать — отвечу в течение 4 часов в рабочее время. Первая консультация бесплатно.

Самозанятый Калинкин Н. А. · работаю с физлицами и юрлицами

Продолжая пользование настоящим сайтом Вы выражаете своё согласие на обработку Ваших персональных данных (файлов куки) с использованием Yandex.Metrika.
Понятно