Реализация парсинга через Cheerio/BeautifulSoup (HTML-parsing)

Сайты меняют разметку, и парсеры внезапно перестают собирать данные — знакомо? Мы разрабатываем устойчивый парсинг HTML под ключ: настраиваем разбор страниц, следим за изменениями и сокращаем ручной сбор данных в разы.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Реализация парсинга через Cheerio/BeautifulSoup (HTML-parsing)

Бэкенд-разработка: Laravel, Node.js, Django, Rails, GoПростойот 1 дня до 3 дней
Часто задаваемые вопросы

Почему парсинг HTML ломается на реальных сайтах

Парсер, который отлично работал на тестовой выборке из десяти страниц, ломается на проде в первый же день. Причина почти всегда одна: статичный HTML из документации и реальная выдача — это два разных мира. Разметка приходит уже собранной скриптами, селекторы держатся на классах вроде css-1x2y3z, которые генерирует сборщик и меняет при каждом релизе, а сервер отдаёт контент только при валидной сессии и правдоподобных заголовках запроса. Разбираем, как это закрывается на практике.

Динамическая разметка — самая частая причина пустых выборок. Если данные подгружаются асинхронно, парсер получает каркас страницы без нужных узлов: селектор формально валиден, но возвращает null. Лечится не «подождать подольше», а работой с итоговым состоянием страницы — рендерингом через headless-браузер либо разбором тех же запросов, которыми фронтенд забирает данные. Второй путь быстрее и стабильнее, но требует анализа сетевой активности.

Селекторы — вторая точка отказа. Привязка к автогенерируемым классам и к цепочкам вида div > div:nth-child(3) > span означает, что любая правка вёрстки обнуляет выборку. Устойчивые парсеры опираются на смысловые атрибуты, микроразметку и текст-якоря, а не на позицию в дереве, и явно проверяют, что нашли ожидаемое число элементов, — иначе молчаливая деградация вместо ошибки.

Защита от автоматических запросов и кодировки добивают остальное. Ограничение частоты, проверки на признаки бота, подмена контента для подозрительных клиентов — всё это даёт ответ с кодом успеха и пустым телом. Кодировка добавляет свою порчу: без явного указания сервер отдаёт windows-1251 или latin-1, и кириллица превращается в мусор, который ломает сравнение строк. Поэтому в конфигурации парсера кодировка задаётся принудительно, а не определяется автоматически.

Практический вывод: парсер — это не скрипт на один запуск, а сервис с мониторингом. Мы закладываем проверку полноты выборки, оповещение при падении доли успешных разборов и версионирование селекторов, чтобы смена разметки на источнике не превращалась в тихую потерю данных.

Что даёт устойчивый парсинг HTML-страниц

Устойчивый парсинг — это когда разбор страницы не ломается от смены вёрстки, а доля успешных разборов держится на уровне 98-99% вместо 70-80% у «одноразовых» скриптов. Разница видна не в момент запуска, а через месяцы: селекторы устаревают, структура DOM меняется, и парсер либо продолжает работать, либо тихо отдаёт пустые поля.

Мы строим разбор так, чтобы сбой был виден сразу и локализован в одном месте. Селекторы выносятся в отдельный слой конфигурации, а не размазаны по коду — правка под новую вёрстку занимает минуты, а не часы регрессионного тестирования. Ниже — что именно даёт такой подход.

  • Доля успешных разборов 98-99% — вместо «работает, пока не сломается». Каждый запуск фиксирует, сколько страниц разобрано полностью, сколько частично, сколько упало.
  • Поддержка селекторов за минуты — правила вынесены в конфиг, при смене вёрстки правится один файл, а не весь код парсера.
  • Уходят целые классы отказов — пустые поля из-за смены классов, дубли записей при повторном проходе, зависания на динамических блоках.
  • Повторный проход по упавшим страницам — то, что не разобралось, ставится в очередь и переразбирается, а не теряется молча.
  • Проверка целостности данных — обязательные поля валидируются до записи, битые записи не попадают в базу.
  • Мониторинг деградации — если доля успешных разборов падает ниже порога, приходит сигнал раньше, чем это заметит заказчик.

Итог — парсер перестаёт быть хрупким скриптом и становится частью инфраструктуры: предсказуемой, наблюдаемой и ремонтопригодной.

Подходы к разбору разметки и их ограничения

Разбор HTML — это всегда выбор между устойчивостью к изменениям вёрстки и точностью извлечения. Селекторы по классам и идентификаторам работают быстро и предсказуемо, пока разметка не меняется: стоит разработчику сайта переименовать обёртку или добавить промежуточный контейнер, и правило молча отдаёт пустой результат вместо ошибки. Поэтому на практике мы комбинируем несколько подходов и закладываем проверки, которые ловят деградацию разбора.

Вариант Когда подходит Ограничения
Статические селекторы по классам и идентификаторам Стабильная вёрстка, известная структура блоков Ломается при смене классов, нет сигнала об ошибке
Разбор по структуре документа Списки, таблицы, повторяющиеся карточки Чувствителен к вложенности и порядку узлов
Шаблоны под типовые блоки Каталоги, карточки товаров, ленты Требует поддержки при смене макета
Ручной разбор текста Разнородные страницы без чёткой разметки Медленно, много исключений, хрупко

Статические селекторы дают максимальную скорость, но привязаны к именам классов, которые меняются чаще всего. Разбор по структуре документа опирается на повторяемость узлов — он переживает косметические правки, но ломается при изменении вложенности. Шаблоны под типовые блоки удобны, когда страниц одного типа много: правило описывает карточку один раз и применяется к сотням страниц.

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

Как мы выстраиваем конвейер разбора страниц

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

  1. Аудит источников. Смотрим разметку каждой страницы, частоту правок шаблона, наличие постраничной навигации и скрытых блоков, которые подгружаются отдельно от основного документа. По итогу — карта источников с пометкой, где разбор устойчив, а где потребуется запасной путь.
  2. Схема разбора. Проектируем структуру данных и правила извлечения: какие поля обязательны, как обрабатываем пропуски, что делаем при смене вёрстки. Схема описывает не только «что вытащить», но и как отличить корректную страницу от заглушки или ошибки.
  3. Настройка извлечения. Собираем разбор на Cheerio для серверной отдачи и BeautifulSoup там, где нужна устойчивость к неаккуратной разметке. Селекторы привязываем к смысловым признакам, а не к порядку элементов, — так правка шаблона не ломает весь конвейер.
  4. Проверка на потоке. Прогоняем разбор на реальном объёме страниц, сверяем извлечённые поля с эталонной выборкой, ловим расхождения по типам страниц. Отдельно проверяем поведение при медленных ответах и частично загруженном документе.
  5. Обработка сбоев. Настраиваем повторы, ограничение частоты обращений и журнал ошибок с сохранением исходной страницы — по ней видно, что именно изменилось в разметке.
  6. Передача и регламент. Отдаём схему разбора, описание полей и правила обновления селекторов, чтобы правки вносились предсказуемо, а не по памяти.
  7. Сопровождение. Регулярно сверяем долю успешно разобранных страниц: падение показателя — сигнал, что источник поменял шаблон.

Такой порядок даёт предсказуемый результат: конвейер переживает правки вёрстки, а сбои видны на графике, а не всплывают в готовых данных.

Что заказчик получает на руки после внедрения

После внедрения парсинг перестаёт быть набором скриптов «на одном ноутбуке» и становится управляемым сервисом. Ниже — что именно мы передаём команде заказчика, чтобы решение можно было эксплуатировать и развивать без нас.

  • Конфигурации разбора. Отдельные профили под каждый тип страницы: какие селекторы вытаскивают поля, какие атрибуты и как нормализуются значения. Селекторы вынесены из кода в конфиг — при смене вёрстки источника правка занимает минуты, без релиза приложения.
  • Схемы источников. Карта: адрес, периодичность обхода, глубина, лимиты запросов, правила обхода пагинации и каталогов. Видно, откуда берётся каждый блок данных и что делать при появлении нового раздела.
  • Правила обработки ошибок. Поведение при смене структуры, таймаутах и пустом ответе: повтор с задержкой, карантин записи, уведомление ответственного. Сбой одного источника не останавливает остальные.
  • Валидация данных. Проверки на обязательные поля, типы и диапазоны значений до записи в хранилище — битые записи не попадают в базу и не ломают отчёты.
  • Логи и мониторинг. Журнал прогонов с числом собранных записей, долей ошибок и временем выполнения; алерты на аномалии, чтобы проблему видели до жалобы пользователя.
  • Документация. Описание архитектуры, инструкция по добавлению источника и правке селекторов, разбор типовых сбоев — новый инженер вводится в контур без устных пояснений.
  • Регламенты эксплуатации. Расписание прогонов, порядок обновления профилей разбора, точки контроля качества и ответственные за каждый шаг.

Пакет самодостаточен: команда заказчика может менять источники и правила сама, а мы подключаемся на сложных изменениях. Опишите задачу — вернёмся с оценкой и планом по вашему контуру.

Кейс: как парсер перестал падать на смене разметки

Задача была типовой: собирать карточки товаров и цены с внешнего каталога, который регулярно менял вёрстку. Первая версия разбора на Cheerio держалась на жёстких цепочках селекторов — div.list > div.item:nth-child(3) > span.price. Пока источник не трогали, всё работало, но каждая правка разметки на его стороне ломала разбор: селектор переставал находить узел, парсер отдавал пустые поля, а часть записей уходила в базу с нулевыми ценами.

Доля успешных разборов проседала до 60-70%, и это замечали уже по неверным данным в отчётах, а не по падению процесса — тихая деградация хуже явной ошибки.

Что изменили

Мы переписали извлечение на устойчивые признаки вместо позиции в дереве: атрибуты data-*, микроразметку, семантические теги и текстовые якоря рядом с ценой. Добавили слой проверки схемы — после разбора документ валидируется по ожидаемым полям, и если доля заполненных падает ниже порога, запуск помечается как подозрительный, а не пишется в базу молча. Селекторы вынесли в конфигурацию отдельно от кода: правка источника теперь лечится изменением правил, а не релизом.

Метрики до и после

Показатель До После
Доля успешных разборов 60-70% 98-99%
Время восстановления после смены разметки 1-2 дня 1-3 часа
Записей с пустыми полями в базе регулярно единичные, ловятся валидацией

Ключевое — не сама цифра, а класс отказа. Раньше смена разметки означала тихую потерю данных и ручной разбор инцидента; теперь это сигнал в мониторинге и правка конфигурации в тот же день. Время восстановления упало за счёт того, что точка отказа локализована в правилах, а не размазана по коду разбора.

Чем отличается разбор статической и динамической разметки?

Статическая разметка приходит с сервера целиком: HTML уже содержит все нужные узлы, и парсер читает их напрямую через селекторы. Здесь работают библиотеки вроде Cheerio или BeautifulSoup — они строят дерево документа и позволяют забирать данные по классам, атрибутам и структуре вложенности. Такой разбор предсказуем: один запрос — один полный ответ, а результат зависит только от того, насколько стабильны селекторы на стороне источника.

Динамическая разметка собирается уже в браузере: сервер отдаёт пустой каркас, а данные подгружаются скриптами и появляются в DOM через какое-то время после загрузки. Прямой HTML-парсинг тут вернёт пустоту, поэтому нужен движок, который выполняет сценарии и дожидается отрисовки нужных блоков. Это меняет саму логику: вместо «забрать и разобрать» появляется ожидание конкретного состояния страницы, иначе данные просто не успеют появиться.

Разница напрямую влияет на устойчивость. Статический парсер ломается в основном при смене вёрстки — это заметно сразу и лечится правкой селекторов. Динамический зависит ещё и от порядка загрузки, подгрузки по прокрутке и задержек сети, поэтому здесь закладывают повторные попытки, таймауты и проверку, что элемент действительно отрисован, а не просто присутствует в разметке.

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

Технические сомнения по парсингу HTML

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

Как вы убеждаетесь, что собранные данные корректны?

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

Что происходит, когда сайт-источник меняет вёрстку?

Селекторы привязываем не к классам вида col-md-7, а к устойчивым признакам — структуре блоков, атрибутам, порядку элементов. Если разметка всё же поехала, срабатывает валидация из предыдущего пункта: задача помечается как сбойная, приходит уведомление, сбор останавливается вместо записи мусора. Правку селектора вносим точечно, без переписывания всего сборщика.

Как избегаете блокировок со стороны источника?

Работаем в рамках разумной нагрузки: распределяем запросы по времени, соблюдаем паузы, используем пул адресов и ротацию заголовков. Где у источника есть официальный интерфейс для данных — берём его вместо разбора разметки. Это снижает и риск блокировки, и хрупкость решения.

Можно ли переиспользовать парсер для другого сайта?

Частично. Логика обхода, хранения и проверок переносится, а слой извлечения под каждый источник пишется отдельно — разметка у всех своя. Поэтому новый источник добавляется быстрее первого: инфраструктура уже готова, меняется только описание того, что и откуда брать.

Опишите источники и поля, которые нужны на выходе, — вернёмся с оценкой и планом сбора.

Обсудим вашу задачу по разбору страниц

Разбор HTML — задача, где 80% риска сидит в источниках, а не в коде. Разметка меняется без предупреждения, часть данных подгружается скриптами, где-то стоит защита от частых запросов, а где-то нужны авторизация и сессия. Чем раньше мы увидим реальные страницы, тем точнее оценим объём работ и не заложим в план лишнего.

Опишите задачу — вернёмся с оценкой и планом. Что нам важно понять на старте:

  • какие источники разбираем: список адресов, типы страниц, есть ли доступ по авторизации;
  • что именно забираем: конкретные поля, вложенные блоки, таблицы, вложения и файлы;
  • как часто и в каком объёме: разовая выгрузка, ежедневное обновление или поток в реальном времени;
  • в каком виде нужен результат: база, таблица, выгрузка в файл или передача в вашу систему;
  • как источник отдаёт данные: статичная разметка или подгрузка через скрипты и запросы;
  • есть ли ограничения: лимиты запросов, требования к паузам, правила использования данных;
  • что делать при сбое: уведомление, повтор, откат к последней корректной выгрузке.

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

Пришлите список источников и примеры страниц — этого достаточно, чтобы вернуться с конкретикой.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1543
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1374
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060