ZeroPost
Все статьи

Парсинг с ИИ — когда это правда нужно, а когда перебор

ZeroPost AI6 сентября 2026 г. 5 мин чтения
Парсинг с ИИ — когда это правда нужно, а когда перебор

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

Сработало. Не идеально, но сработало — и когда вёрстка снова поменялась, парсер не упал. Он просто продолжил работать, потому что GPT-4 видит не классы, а смысл. И вот тут я понял, что парсинг с ИИ — это не просто модная фишка, а реальный инструмент. Но с оговорками.

Разбираюсь, где это заходит, а где нет, и как не слить бюджет на API-вызовы.

Классический парсинг умер? Нет, но болеет

Обычный парсинг работает так: пишешь селектор (BeautifulSoup, Cheerio, Puppeteer), он находит элемент по структуре HTML, вытаскиваешь текст. Быстро, дёшево, предсказуемо. Пока сайт не меняется.

А сайты меняются постоянно. Редизайн, A/B-тесты, динамические классы вида css-1a2b3c4d — и твой парсер превращается в тыкву. Правишь селекторы, снова ломается, правишь опять. Если парсишь один сайт — терпимо. Если десять — начинается ад.

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

И вот тут ИИ предлагает другой подход: не ищи элемент по структуре — понимай содержимое.

Как это работает: LLM как универсальный экстрактор

Идея простая. Берёшь HTML (или его кусок), отправляешь в GPT-4 или Claude с промптом: «Вытащи из этой страницы название товара, цену и рейтинг». Модель читает разметку как текст, находит то, что похоже на название, цену и рейтинг, — и возвращает JSON.

Никаких селекторов. Никаких xpath. Описываешь что нужно, а не где это лежит.

Пример из практики. Был у меня HTML карточки товара — 15 килобайт вёрстки, половина — инлайн-стили и аналитика. Скормил его Claude 3.5 Sonnet с промптом:

Найди в этом HTML:
- название товара
- цену в рублях
- рейтинг (если есть)
- количество отзывов

Верни JSON: {"title": "...", "price": 1234, "rating": 4.5, "reviews": 89}

Модель вернула чистый JSON за две секунды. Проверил на десятке карточек с разных сайтов — работало везде, хотя вёрстка была разной.

Главное преимущество: когда сайт меняет дизайн, парсер продолжает работать. Модель не привязана к конкретным классам — она ищет смысл, а не div с class="product-title".

Где это реально полезно

Нашёл три сценария, где ИИ-парсинг оправдан.

1. Парсинг разнородных источников

Когда нужно собрать данные с десятков сайтов с разной структурой. Писать отдельный парсер на каждый — геморрой. LLM справляется одним промптом.

Пример: собирал описания вакансий с разных джоб-бордов. У каждого своя вёрстка, у некоторых вообще рендер на клиенте. Вместо пяти парсеров написал один скрипт: Puppeteer рендерит страницу, вытаскивает HTML, отправляет в Claude. Модель находит название позиции, зарплату, требования — независимо от того, как это оформлено.

2. Извлечение сложных данных

Когда информация не лежит в одном теге, а размазана по странице или вообще спрятана в тексте. Допустим, дата публикации записана как «вчера в 14:30» или «3 дня назад». Классический парсер такое не переварит, а LLM нормализует без проблем.

Ещё пример: прайс-листы в PDF. Таблицы без чёткой структуры — где-то цена справа, где-то внизу, где-то вообще в скобках после названия. GPT-4 справился, потому что понял контекст, а не просто искал паттерн.

3. Когда сайт часто меняется

Если знаешь, что через месяц селекторы отвалятся, — проще сразу использовать ИИ. Дороже, зато не придётся каждый раз чинить.

Где это не нужно

ИИ-парсинг — не серебряная пуля. Есть ситуации, где он лишний.

1. Статичные сайты с предсказуемой структурой

Если парсишь один сайт, который не меняется годами, — зачем платить за API? Обычный BeautifulSoup справится за миллисекунды и ноль центов.

2. Большие объёмы данных

LLM-вызовы стоят денег и времени. Нужно спарсить сто тысяч страниц — счёт за OpenAI улетит в космос. Плюс скорость: классический парсер обработает страницу за 10 мс, LLM — за 1–3 секунды.

Посчитал для своего кейса: десять тысяч карточек товаров через GPT-4 Turbo обошлись бы в $50–70 (по 5–7 центов за запрос с учётом токенов). Тот же объём через Cheerio — копейки на хостинге.

3. Когда точность критична

LLM может ошибиться или привнести. Если нужна стопроцентная точность — финансы, медицина, — лучше жёсткие селекторы и валидация. ИИ хорош для «достаточно правильных» данных, но не для критичных систем.

Как я это делаю: гибридный подход

Самое разумное — миксовать подходы. Использую такую схему:

  1. Puppeteer рендерит страницу — для SPA и сайтов с динамической подгрузкой.
  2. Вытаскиваю нужный кусок HTML — не весь исходник, а только блок с данными, например карточку товара. Это режет количество токенов и ускоряет обработку.
  3. **Отправляю в Claude Sonnet 4.6 — дешевле GPT-4, но для парсинга работает отлично.
  4. Валидирую результат — проверяю, что цена — число, название не пустое. Если модель вернула мусор — логирую и пропускаю.

Код на Node.js:

const puppeteer = require('puppeteer');
const Anthropic = require('@anthropic-ai/sdk');

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_KEY });

async function parseProduct(url) {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(url, { waitUntil: 'networkidle2' });
  
  const html = await page.evaluate(() => {
    const card = document.querySelector('.product-card'); // упрощённо
    return card ? card.outerHTML : document.body.innerHTML;
  });
  
  await browser.close();
  
  const message = await anthropic.messages.create({
    model: 'claude-3-5-Claude Sonnet 4.6',
    max_tokens: 1024,
    messages: [{
      role: 'user',
      content: `Извлеки из HTML: название товара, цену в рублях (только число), рейтинг.
Верни JSON: {"title": "...", "price": 0, "rating": 0}

HTML:
${html}`
    }]
  });
  
  const result = JSON.parse(message.content[0].text);
  
  // валидация
  if (!result.title || result.price <= 0) {
    console.error('Invalid data:', result);
    return null;
  }
  
  return result;
}

Ещё добавил кэширование. Если структура сайта не изменилась, нет смысла каждый раз гонять через LLM. Храню хеш HTML-структуры и селекторы — пока они работают, использую их. Как только отваливаются — переключаюсь на ИИ-экстрактор. Это держит расходы под контролем и скорость высокой.

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