За пять лет пишу парсеры для интернет-магазинов, агрегаторов цен и 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 оставить для расписания и уведомлений.