Месяц назад я поставил себе задачу: хочу знать, когда конкурент меняет цену, не открывая вручную двадцать сайтов каждое утро. Задача старая, парсеры существуют сто лет. Но я решил собрать именно агента — такого, который сам решает когда парсить, сам складывает данные и сам шлёт сигнал, когда что-то изменилось. С первого раза не получилось. Вот что я понял по итогу.
Почему обычный парсер не подошёл
Я пошёл по привычному пути: написал скрипт на Python с BeautifulSoup, настроил крон на каждый час — и успокоился. Работало три дня. Потом один сайт поставил Cloudflare, второй начал отдавать цены через JavaScript-рендеринг, третий тихо поменял структуру вёрстки. Скрипт упал молча, без единого сообщения об ошибке.
Я обнаружил это через неделю — случайно зашёл на сайт конкурента и увидел, что цена там изменилась ещё семь дней назад. Данные за неделю потеряны.
Вот тут стала понятна разница между парсером и агентом. Парсер делает то, что ему сказали. Агент следит за тем, что происходит, и реагирует на изменения — включая собственные сбои.
Из чего я собрал агента
Стек простой, без экзотики:
- Python 3.11
- Playwright — для сайтов с JavaScript-рендерингом
- OpenAI API (gpt-4o-mini) — для страниц с нестандартной вёрсткой
- SQLite — хранить историю цен
- Telegram Bot API — уведомления
Модель я подключил не для красоты. Жёсткие CSS-селекторы ломаются при любом редизайне — это я уже знал. Поэтому стал передавать агенту HTML-фрагмент со страницы и просить найти цену в тексте. Решение оказалось на удивление устойчивым: даже когда сайт менял вёрстку, модель продолжала находить нужное число.
Запрос устроен просто: передаю очищенный текст блока с товаром и прошу вернуть только цифру. Никаких рассуждений, никакого лишнего контекста — просто число или "не найдено". Дальше агент работает с числом, а не с текстом, и это принципиально.
Как устроена логика агента
Я не стал городить сложный оркестратор. Агент — это цикл с состоянием и несколькими ветками решений.
Каждые два часа он проходит по списку URL. Для каждого: загружает страницу через Playwright с рандомным user-agent и небольшой паузой, извлекает нужный блок по грубому селектору — раздел с ценой, не конкретный элемент, — передаёт текст в модель и получает цену. Дальше сравнивает с последней записью в базе. Если изменение больше порогового процента — шлёт уведомление.
Пороговый процент я поставил в 3%. Без него агент слал уведомление каждый раз, когда цена менялась на рубль из-за скидки или округления.
Отдельная ветка — обработка ошибок. Если три попытки подряд вернули сбой, агент шлёт отдельное сообщение: "сайт недоступен или изменилась структура, нужна проверка". Именно это я и хотел с самого начала.
Где я обжёгся
Час потратил на то, чтобы понять, почему Playwright возвращает пустую страницу на одном из сайтов. Оказалось, сайт проверял реальность браузера через navigator.webdriver. Решилось одной строчкой — аргумент при запуске, который убирает признак автоматизации.
Другой тупик: я сначала передавал в модель весь HTML страницы. Дорого и медленно. gpt-4o-mini справляется с задачей, но когда страница весит 200 КБ HTML, токены горят быстро. Переписал предобработку: сначала вырезаю нужный блок регуляркой по ключевым словам — "цена", "price", "руб", "₽" — и только этот кусок отдаю модели. Стоимость запроса упала раз в пятнадцать.
Третье, что я не предусмотрел сразу — ротация запросов. Два сайта из семи заблокировали мой IP после первых суток работы. Пришлось добавить случайную задержку от 40 до 120 секунд между запросами к одному домену и ограничить частоту тремя запросами в час к одному хосту. После этого блокировок не было.
Что я получил на выходе
Агент работает уже пять недель без ручного вмешательства. За это время один конкурент снизил цены на топовую позицию на 12% — я узнал об этом через три минуты после изменения. Второй тихо поднял цены на 8% в пятницу вечером, явно рассчитывая, что в выходные никто не заметит.
В Telegram прилетает короткое сообщение: название товара, старая цена, новая цена, разница в процентах, ссылка. Без украшений — только данные.
На практике база уже накопила кое-что интересное. Один из конкурентов регулярно снижает цены во вторник утром и поднимает в четверг. Вручную я бы это не заметил никогда.
Что дальше
Следующий шаг, который я пока не сделал — мониторинг наличия товара. Сейчас агент видит только цену. Но "цена снизилась до нуля" и "товар закончился" — это разные ситуации, и агент их не различает.
Ещё хочу попробовать недельную сводку: не просто уведомления о каждом изменении, а отчёт с трендами. Хотя не исключено, что это превратится в ещё один дашборд, который открываешь раз в месяц и закрываешь.
Но это следующая версия. Текущая работает — и это главное.
