Привет! Маркетплейсы очень сильно изменили нашу жизнь, сделав ее супер удобной. Это классно, но думаю всем знакома картина, когда добавил товар в корзину, отвлекся, а он уже на 500р дороже. Или дешевле. Или вообще продается на косарь меньше на другом маркетплейсе. Ах да, как насчет «зачеркнутых выгодных» цен вида ̶1̶7̶0̶0̶0̶ 800р?
Все это превращает покупки в биржу (или большой рынок), где одни и те же товары уезжают разным людям по разным ценам. А если так, то значит это дело надо автоматизировать и хочу рассказать как это сделал я.

Приступим!
Скажу сразу, что это все носит развлекательно-познавательный характер и пост я писал дольше, чем код. Но вышло прикольно, оно работает, легко воспроизводимо кем угодно и легко тюнится, — а значит имеет право на существование.
Пока космические AI-корабли бороздят просторы вселенной, а именно — весь мир рассуждает, как изменится экономика планеты и паттерны покупок и насколько сильно они изменятся AI-агентами (которые будут честно сами ходить и искать нам лучшие предложения, отчаянно торгуясь и отстаивая свою точку зрения через MCP или A2A с поставщиками), покупать на этой бирже товаров что-то на сотку дешевле хочется уже сейчас.
Я обожаю готовить на огне, заказываю много поварских штучек и грильных расходников, и каждый раз все это стоит по разному. Не то, чтобы это приносит страдания, но мне вдруг стало очень интересно решить эту продуктовую задачу инженерным путем.

Давайте посмотрим ̶к̶а̶к̶ ̶я̶ ̶с̶о̶б̶р̶а̶л̶ ̶с̶о̶б̶с̶т̶в̶е̶н̶н̶о̶г̶о̶ ̶A̶I̶-̶а̶г̶е̶н̶т̶а̶, что с этим можно сделать.
Кстати, да, конечно, когда цена стала ниже — я тихо доволен как обмазанный сметаной кот, когда стала выше — гневу нет предела, потому что опять капиталисты забрали всю прибыль.
Ключевые требования и парсинг
Начнем с требований и, так сказать, набросков систем дизайна. Парсить все подряд — идея бессмысленная, потому что у маркетплейса много внутренних механизмов изменения цен, начиная от органического соревнования ценами от самих поставщиков до предложений индвидуальных скидок по каким-то эвристикам.
Поэтому ключевое требование — товары должны быть именно в моей корзине, потому что это достаточно сильный сигнал маркетплейсу о желании что-либо купить. Поэтому цена в моей корзине и публично доступная цена — это могут быть две разные цены, и нас интересует только реальная — первая.
Промышленно парсить маркетплейсы — удовольствие странное (хотя это делают все), нужны фермы проксей, аккаунтов, браузеров с историями и вообще там постоянная битва меча со щитом. Но нам это и не надо! Нам надо лишь открыть свою корзину, аккуратненько спарсить ее содержимое и все залогировать.
Вот наши ключевые требования:
Нам нужен залогиненный в мой акк браузер
Нужно периодически обновлять корзину (по сути — просто заходить на страницу корзины каждый раз)
Парсить ее содержимое, различать что изменилось
Нужен какой-то автоматический кросс-маркетплейсный матчинг
Нужна БД и какой-то приниматор решения, которому не надо детально ставить задачу
Нужен крон и выполнятор логики
ТГ-бот: ну куда же без уведомляхи в тг-бота
Все это нужно проделать для трех маркетплейсов (озон и я.маркет — мои основные, плюс немножко wb).
Звучит как задачка на несколько часов (так и вышло, а на пост ушло сильно-сильно больше). God save the LLMs&Cursor.
Делаем себе реальный браузер
Итак, нам нужен браузер. Мой самый любимый инструмент — это питоновская либа Playwright. В нем можно запустить браузер, понасохранять в него что угодно, а потом в таком состоянии запускать его серверно (через xvfb, например), проделывая любые визуальные действия, которые будут реальными действиями из реального браузера. Здесь есть социальный договор — ты не создаешь проблем маркетплейсам, они не банят тебя, поэтому для нашей задачи годится.
Для начала нужно запустить из кода визуальный браузер с gui, чтобы честно авторизоваться и сохранить честные и настоящие куки и в целом обозначиться. При первом старте мы видим «antibot challenge page», которую быстро проходим и попадаем на главную страницу, потому что, перефразируя классиков, «кто ж его заблочит — он же браузер!».

Это шутка. Кажется, ну а что они нам сделают — это же настоящий браузер с руками-ногами! Но на самом деле антибот-системы отлично умеют палить любые сценарии: headless-браузеры, одинаковые фингерпринты, слишком ровные движения мышки и чего только нет. Антибот-системы делают очень умные ребята и они, конечно же, про все это в курсе. И мы для них скорее «неуловимый джо» из анекдота — отловить можно, но смысла нет. И это ровно то, что нам нужно.
В нашем случае мы имитируем сценарий «честный пользователь с закладкой на корзину» и это действие от полноценного пользователя, банить нас пока не за что. Фермы ботов делаются схожими, но более профессиональными способами, им долго добавляют поведенческие паттерны, историю, разные fingerprints, эмуляторы устройств ios/android и прочее разное сложное прикольное (там вечная борьба щита и меча). По таким же эвристикам могут отловить и нас, но как будто бы это еще надо заслужить.
Ок, мы пробились, авторизовались, а дальше заходим несколько раз в день (ну все как в жизни, ну), создавая минимальную нагрузку, но получая все, что нам нужно.
Так как у нас возникает некий ETL, то нам нужен оркестратор и в качестве его я выбрал идеально подходящий Airflow.

Ну, конечно же, это шутейка. Все что нам нужно — это годами проверенный дедовский способ — один мутный скрипт, который делает все, что нужно.
Как парсить — да через любой парсер просто цепляясь за нужные теги. Но здесь очень-очень важно то, что парсить можно только после полного рендеринга DOM и какого-то ощутимого таймаута после него (чтобы избежать lazy-load чего-то или shadow DOM), поэтому playwright должен все это проделать и скидывать финальный html. Иногда быстрее (но не всегда лучше) вытащить из XHR, но для нашего случая сейчас — пойдет. И так же важно сделать простой sanity-check на стабильность нужного блока с товарами, чтобы в случае изменений на маркетплейсах мы о них быстро узнавали.
Итого, у нас уже есть возможность сохранять наши товары в базу (взята SQLite за ее простоту). Табличка одна (для упрощения логики) и тривиальная: название, цена, дата, маркетплейс, упакованным текстом важные описашки (типа скидок, последних товаров и тд), активность 0/1. Тут важно сохранять именно движение цены, но и любое движение цены нам тоже не важно — первый прогон показал, что цены могут меняться даже на 2р, что не годится — поэтому % от цены не меньше какого-то фикса типа 20р.
Да, чтоб все завелось, в текущем виде надо сначала вручную добавить сами товары в корзину (именно той вариации, что нам нужно, то есть руками поискать и добавить), а уже затем наслаждаться автоматикой. Да, тут можно добавить всякое разное и поиск и автоматическое добавление в корзину — все это сделать несложно и можно, но задачи такой в первой версии не стояло.
При запуске скрипт получает html корзин со всех маркетплейсов, разбирает все на товары и вставляет в базу прям как есть. Если я что-то купил, то товара в корзине уже нет, оно зануляет активность и товар перестает мониториться для всех.
Ок, цены и товары есть. И тут мы по касательной встречаемся с одной из главных сложностей маркетплейсов — матчингом. Матчингом и поиском в маркетплейсах занимаются тоже чертовски умные ребята и там проблем и без нас хватает. Наши же масштабы сведения товаров прям крошечные и тут нам помогут LLM.
Здесь нужно сделать микро-отступление про LLM.
""" начало отступления
LLMки сейчас пихают (или даже скорее «пытаются запихнуть») куда только не попадя, в том числе туда, где неплохо справится и классический NLP ̶,̶ ̶н̶у̶ ̶в̶о̶т̶ ̶и̶ ̶я̶ ̶т̶о̶ж̶е̶ ̶з̶а̶п̶и̶х̶н̶у̶л̶. На самом деле, у меня было именно осознанное решение, потому что я обожаю LLMки за то, что они дают единый интерфейс к большому количество решаемых задач. Да, для многих штук LLM в проде это настоящий оверкил, но для прототипов, концептов и небольшого софтика — лучше не придумать. Их сила в том, что единым типовым запросом по API можно порешать огромное количество разных штук, которые пришлось бы упорно писать самим.
Да, если концепт вырастает в нечто большое — окей, разбираем все по кирпичикам, делаем промышленно и оптимизируем. Но иногда проекту просто не суждено вырасти (например, какой-нибудь сгружатор тикетов из гитлаба для небольшой команды), у него by design нет нагрузки и больших данных, но какую-то полезную бизнес-функцию он все же выполняет.
Кстати, здесь ровно такой случай: есть мини-матчинг и затем принятие решения.
Для своих всяких штучек-экспериментов я обожаю mini-версии флагманских LLM, так как они мощные, дешевые, легко подключаемые и легко доступные по API. Production-ready magic box.
конец отступления """
Интерфейс и подключение LLM
Сначала про данные. Мы знаем, что товары по своей сути одинаковые, но называться они могут максимально по-разному и без какой-либо обработки строк LLM это все легко съест. То есть, нам достаточно иметь в базе «Соус Kikkoman Соевый натурально сваренный, диспенсер, 150 мл» и «Соевый соус Kikkoman классический, 150 мл., Япония», а дальше все это кидануть в ллмку, она разберется. Никакой обработки, автоматический «матчинг» из коробки, если это можно так назвать.
Чтобы понимать, что мы вообще мониторим, можно собрать два простеньких контейнера фронт-бек для показа товаров и отдельную историю цен по каждому товару. Разворачиваться мне есть где, поэтому проблемы инфры не стоит. И да, цены все в интах, чтобы помочь ллмке разобраться в ее любимой проблеме 9.9 / 9.11.

К товарам в корзине и к такой динамике цен можно написать текущий промпт из моих пожеланий — он накладывается на хорошо подготовленный системный промпт.
Выглядит все следующим образом: есть промпт на текущую корзину и чего бы с ней хотелось — написано максимально разговорным языком. Это супер крутой концепт, в котором простая постановка задачи заменяет все правила в коде. Код с кучей if писать не надо — и это круто.
Для примера: «дождись цены на кофе меньше 1000р», «пришли когда соус подешевет на 150р» (куплю ящик), «пришли если на тумбу будет скидка больше 5%», «пришли товар, который сильно подорожал» (нет особо времени ждать, куплю аналог), «вся корзина дешевле на 500». Ну кайф же.

В итоге в LLM собирается гранд-промпт: системный промпт, корзина товаров, история цен, текущий промпт под задачу. Все запромчено так, что бы возвращалось либо 0, либо расшифровка того, что нужно сделать и послать в тг: эй, тут щепа подешевела до 2 тыщ как ты хотел, можно и брать. Да, стоит просить присылать json, чтобы дополнительно ответ отфильтровать.

Если мы готовы сталкерить товар очень долго, то вместо просто списка цен подойдут какие-то фичи из цен.
В итоге пайплайн выглядит так: несколько раз в день крон запускает браузеры для обновления цен, потом еще один собирает гранд-промпт и посылает его в ллмку, и по результату шлет уведомление в бота.
Вот так:

Экономика: типичный запрос для трех товаров около 700-1000 токенов (90% in и 10% out), цена gemini 2.0 flash-lite 1M токенов $0.1 in / $0.40 out, три запуска в день это грубо 3к токенов, 30 дней в месяц. И мы получаем что-то около $0.012 за месяц, со всеми накладными расходами — полтора рубля. Значит, как только мы экономим 2 рубля, ̶м̶ы̶ ̶п̶о̶к̶а̶з̶ы̶в̶а̶е̶м̶ ̶п̶р̶и̶б̶ы̶л̶ь̶ ̶и̶н̶в̶е̶с̶т̶о̶р̶а̶м̶ ̶и̶ ̶в̶ы̶х̶о̶д̶и̶м̶ ̶н̶а̶ ̶I̶P̶O̶, система экономически целесообразна ?
Понятное дело, что это концепт, все на коленке под ключ за один выходной, нулевая масштабируемость и отказоустойчивость, есть миллиард всего, что стоит улучшить, ллмка может свалиться в галлюцинации, завтра сработает рейт-лимитер или вообще все отвалится. Но я очень доволен, это было весело и прикольно (надеюсь, что и вам тоже), и, возможно, кого-то это вдохновит на что-то похожее и большее для себя.
А пока писал пост, на почти две сотки отследил снижение. Современные проблемы требуют современных решений!
Спасибо!
P.S.: мне нравится писать всякое разное, но гораздо приятнее это делать для большего количества людей, поэтому если статья вам понравилась, то можно поддержать мой совсем начинающий зеленый канальчик в тг, в котором мне хотелось бы делиться интересностями
Мои другие статьи:
Комментарии (9)
cry_san
24.08.2025 14:53и теперь имеем +100500 товаров в корзине
не проще было хранить, например, ссылки на товары в текстовом файле
и дать программе их проверять?
+ зачем платить буржуям, когда можно развернуть сеть у себя (например через LM Studio) и отправлять запросы ейMrCooger
24.08.2025 14:53Сделать много запросов или один? И как мне кажется рейт лимитеры как будто в таких конторах есть
losander
24.08.2025 14:53Не понял.
А если у другого продавца этот же товар станет все таки дешевле? То есть мне надо у всех продавцов добавлять эти позиции в корзину?
В этом случае может появиться новый продавец с такой же позицией и его мы уже не мониторим получается.
Dacom_777
Может кто-то наконец запилит такой агрегатор! Пусть он будет платным, не вопрос
antipov_dmitry Автор
Скорее всего, не запилит, увы, потому что во всех офертах маркетплейсов написано, что промышленно парсить их нельзя, а значит перепродажа таких услуг будет в довольно серой зоне. Конечно, сами мп и особо крупные продавцы тихо скрапят друг друга, и сторонние сервисы (они есть) тоже их скрапят (и продают результаты как "аналитику" - довольно сомнительного качества), но все, что делается "с улицы" (то есть, не по официальной датке самих мп, а им это не интересно) - в больших масштабах это все равно будет некая аппроксимация от реальности. Ну и плюс на масштабах это действительно сложно