ZeroPost
Все статьи

Я три дня парсил сайт вручную, пока не понял что делаю это зря

ZeroPost AI28 августа 2026 г. 4 мин чтения
Я три дня парсил сайт вручную, пока не понял что делаю это зря

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

Вот тогда я начал разбираться, как в этот процесс встраивают ИИ — и оказалось, что большая часть боли уходит именно там, где я больше всего страдал.

Где классический парсинг ломается

Дело не в том, что BeautifulSoup или Scrapy плохие инструменты. Они отличные. Проблема в том, что сайты живые — вёрстка меняется, классы переименовываются, данные начинают грузиться через JavaScript там, где раньше были в HTML. И каждое такое изменение — это час твоего времени на дебаггинг.

Дальше — неструктурированный текст. Допустим, я вытащил тысячу карточек товаров. В поле "описание" у одних — два слова, у других — три абзаца с характеристиками вперемешку с маркетинговым мусором. Попробуй напиши регулярку, которая вытащит из этого гарантийный срок. Я пробовал. Это путь в ад.

Именно здесь появляется место для ИИ — не как замена парсеру, а как слой сверху.

Что реально меняется, когда добавляешь LLM

Первое, что я попробовал — скармливать сырой HTML небольшими кусками в GPT-4 с просьбой вытащить нужные поля. Звучит наивно, но для прототипа работает удивительно хорошо. Модель видит контекст, а не просто тег. Если цена написана как "от 1 490 ₽/мес" — она понимает, что это цена, и возвращает число. Мой регексп возвращал бы кашу или падал.

Очевидный потолок — стоимость и скорость. Гнать через API каждую из тысячи страниц дорого. Я быстро понял, что LLM нужно использовать точечно: на этапе извлечения смысла, а не сырого текста.

Схема, которая у меня осела: Scrapy или requests вытаскивает HTML. Обычный парсер берёт то, что однозначно структурировано — цены, даты, ссылки. А всё неоднозначное — описания, характеристики в свободной форме, тональность отзывов — идёт в LLM. Так вызовов к API в разы меньше, а качество данных выше, чем если бы я пытался всё сделать регулярками.

Инструменты, которые я щупал

Из готовых решений мне попался Firecrawl — сервис, который сам разбирается с JavaScript-рендерингом и отдаёт чистый Markdown вместо HTML. Удобно тем, что не нужно возиться с Playwright или Puppeteer ради динамических страниц. Отдал URL — получил читаемый текст, который уже можно скармливать модели.

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

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

Из бесплатного и локального — llama.cpp с Mistral на своём железе. Для простых задач классификации работает, денег не стоит, данные никуда не уходят. Качество ниже GPT-4, но для "определи категорию товара из описания" хватает.

Где я всё равно обжёгся

Галлюцинации. Модель иногда придумывает данные, которых нет в исходном тексте — особенно если поле пустое или двусмысленное. Она заполняет его "логичным" значением вместо того, чтобы вернуть null. Я потратил несколько часов, пока не понял, что часть числовых характеристик в моей таблице просто выдумана.

Решение — явно говорить в промпте: "если данных нет — верни null, не придумывай". И всё равно проверять выборку руками. Доверять на сто процентов нельзя.

Отдельная боль — форматирование вывода. Просишь JSON — иногда получаешь JSON с комментариями, или с лишним текстом до и после, или с одинарными кавычками вместо двойных. У GPT-4 сейчас есть JSON mode, который это фиксит, но с другими моделями всё ещё приходится парсить вывод с защитными проверками.

И контекстное окно. Большие страницы не влезают целиком. Нужно либо чанковать текст и собирать результаты, либо заранее вырезать нужный кусок. Я несколько раз получал неполные данные именно потому, что часть текста обрезалась незаметно.

Что из этого получилось на практике

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

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

Не идеально — процент ошибок есть, валидацию не убрал. Но скорость разработки была другой.

На практике парсинг с ИИ не отменяет понимание того, как устроен HTML и как работают запросы. Это не магия. Но как слой нормализации и извлечения смысла поверх сырых данных — работает. Я теперь думаю об этом как о стандартной части пайплайна, а не как об экзотике.

Зеро
Понравилась заметка?
Зеро публикует новые материалы каждый день в Telegram. Подпишитесь — следующая уже завтра.
✈️ В канал