Мониторинг цен конкурентов
08.10.26
Ozon и Wildberries: какие поля снимать и как часто обновлять цены

Мониторинг цен конкурентов держится на трёх решениях: что снимать с карточки, как часто и через какие адреса. Ошибка в любом из них даёт таблицу, которой нельзя верить. Я снимаю цены для магазина с 6 000 позиций на двух маркетплейсах, и первые 2 недели сравнение врало по простой причине: сборщик брал цену до скидки, хотя покупатель видел совсем другую. Расхождение доходило до 11 процентов. На половине каталога.
Ниже 5 шагов в том порядке, в каком я их прохожу на новом проекте: поля, частота, особенности Ozon и Wildberries, хранение, расчёт потоков. Цифры в примерах мои, подставляйте свои.
Поля, без которых сравнение врёт
Главная ошибка новичка: сн имать одну цену. На маркетплейсе у товара их 3-4, и сравнивать нужно ту, которую видит покупатель в момент решения. Остальные тоже пригодятся, по ним видно, как конкурент строит скидку.
Что пишу в базу на каждое снятие:
идентификатор товара на площадке: артикул nmId на Wildberries, SKU на Ozon;
цена до скидки;
цена для покупателя со всеми скидками продавца;
цена с картой или кошельком площадки: с Ozon Картой на Ozon, с WB Кошельком на Wildberries;
наличие и остаток, если площадка его показывает;
продавец;
рейтинг и число отзывов;
срок доставки;
время снятия с точностью до минуты.
Сопоставление своих товаров с чужими делается один раз и живёт в отдельной таблице соответствий: ваш артикул, артикул конкурента, площадка. Сопоставлять по названию бесполезно, продавцы переписывают названия карточек под поиск каждые пару недель, и связка по тексту рассыпается молча. Надёжнее связывать по бренду и модели, а спорные пары проверять глазами.
Время снятия я пишу в UTC и перевожу в местное только в отчёте. Так два сервера сборщика с разными настройками часов не путают историю, и переход на другую машину не сдвигает графики.
Как часто снимать цены
Частота зависит от того, как быстро в категории меняются цены. Угадывать её не нужно, её меряют. Неделю снимайте 100 товаров каждый час и посчитайте, сколько раз за сутки цена реально менялась. Если 1-2 раза, 4 съёмов в сутки хватит с запасом. Если цена меняется каждый час, значит, конкуренты подключили автоматический репра йсер, и тогда частоту поднимают для топовых позиций, остальной каталог можно оставить на прежнем графике.
Съёмы ставлю на одни и те же часы каждый день, например 6:00, 12:00, 18:00 и 0:00. Тогда снятия разных дней сравнимы между собой, и рост цены во вторник в полдень видно на фоне понедельника в то же время. Плавающий график такие сравнения ломает. Проверено.
Мои рабочие значения после таких замеров:
категория с частыми акциями и репрайсерами: 4-6 раз в сутки;
обычная категория: 2 раза в сутки;
медленная категория вроде запчастей и инструмента: 1 раз в сутки;
дни распродаж: каждый час по 200 главным позициям.

Ozon и Wildberries: что учесть при съёме
Wildberries
Карточка WB подгружает данные отдельным JSON-ответом. Его видно в DevTools на вкладке Network, если открыть товар и отфильтровать запросы по типу Fetch/XHR. Разбирать JSON проще и надёжнее HTML: поля называются одинаково, вёрстка на них не влияет. Две детали портят данные чаще всего. Цены в ответе лежат в копейках, их нужно делить на 100, иначе в отчёте все конкуренты станут в 100 раз дороже. И в запросе есть параметр dest, который задаёт точку доставки: от него зависят срок доставки и цена в ответе. Выберите один dest и держите его на всех съёмах, иначе история цен будет сравнивать разные вещи.
Список артикулов для съёма держу у себя готовым. Поиск по площадке гоняю раз в неделю, только чтобы найти новых конкурентов, и это экономит большую часть запросов.
Ozon
Ozon показывает на карточке две цены: с Ozon Картой и без неё. Снимайте обе. Простой HTTP-клиент на Ozon нередко получает страницу проверки вместо карточки, поэтому сборщик через браузер, Playwright или Selenium, здесь работает стабильнее, хотя каждый запрос тяжелее по ресурсам. Позиция в выдаче и срок доставки зависят от адреса доставки, в части случаев и цена с учётом логистики. Адрес фиксируйте так же, как dest на Wildberries.
Браузерный сборщик тянет картинки, шрифты и видео, а для цены они не нужны. В Playwright их отрезает одна строка:
await page.route('**/*.{png,jpg,jpeg,webp,gif,woff2,mp4}', r => r.abort());Трафик на карточку падает в несколько раз, и страница загружается быстрее.
Карточки, на которые Ozon ответил страницей проверки, я не повторяю сразу. Они уходят в конец очереди и повторяются через другой адрес, когда основной проход закончен. Так один неудачный ответ не тормозит весь поток.
Где хранить историю и как сравнивать
Каждое снятие пишется новой строкой, старые значения не перезаписываются. История нужна: по ней видно, кто и когда снижает цену, сколько держится акция и в какие часы конкурент обновляет прайс. Для каталога на 20 000 товаров при 4 съёмах в сутки это около 160 000 строк в день и примерно 5 миллионов в месяц. PostgreSQL держит такой объём на обычном сервере без особых настроек.
CREATE TABLE price_snap (
market TEXT, -- wb или ozon
item_id TEXT, -- nmId или SKU
seller TEXT,
price_base INTEGER, -- до скидки, в копейках
price_buy INTEGER, -- для покупателя
price_card INTEGER, -- с картой или кошельком
in_stock BOOLEAN,
taken_at TIMESTAMP
);
CREATE INDEX ON price_snap (item_id, taken_at);
SELECT DISTINCT ON (item_id, seller) item_id, seller, price_buy, taken_at
FROM price_snap
ORDER BY item_id, seller, taken_at DESC;Последний запрос отдаёт свежую цену каждого продавца по каждому товару. Дальше её сравнивают с вашей через таблицу соответствий. Оповещение я ставлю на одно условие: цена конкурента для покупателя ниже моей больше чем на 3 процента, и товар у него в наличии. Продавец без остатка может держать любую цену, в сравнение он не идёт.
Пропуски тоже данные. Если товар не снялся 2 раза подряд, сначала проверьте, жива ли карточка, и только потом отмечайте его как снятый с продажи.
Раз в сутки собираю для закупок короткий отчёт из трёх списков: где я дороже рынка, где дешевле больше чем на 10 процентов и теряю маржу, и где конкурент пропал из наличия. Третий список самый ценный. Пока у соседа нет товара, у вас есть пространство для цены.

Потоки и адреса под мониторинг цен конкурентов
Считаю от объёма и окна съёма. Арифметика простая. 20 000 товаров на 2 площадках при 4 съёмах в сутки дают 160 000 запросов. Каждый съём должен укладываться в 60 минут, иначе цены внутри одного снятия расходятся по времени и сравнение теряет смысл. Значит, за час нужно пройти 40 000 запросов, это около 11 запро сов в секунду.
Один поток с ответом около 1,5 секунды и паузой 2 секунды делает примерно 0,28 запроса в секунду. 11 делим на 0,28, получаем около 40 потоков. На Ozon через браузер запрос тяжелее, поэтому браузерную часть я запускаю отдельной очередью и смотрю на загрузку процессора: упёрся в 90 процентов, потоки дальше не добавляю, добавляю машину.
Тот же расчёт коротко, чтобы подставить свои числа:
карточек на один съём: товары × площадки, у меня 20 000 × 2 = 40 000;
запросов в сутки: карточки × число съёмов, 40 000 × 4 = 160 000;
окно съёма: 60 минут, отсюда 40 000 / 3600 ≈ 11 запросов в секунду;
скорость потока: 1 / (1,5 + 2) ≈ 0,28 запроса в секунду;
потоков: 11 / 0,28 ≈ 40, с запасом 20 процентов на повторы выходит около 48.
Адресов нужно столько, чтобы на каждый приходилась малая доля запросов. С ротацией на каждый запрос это решается на стороне пула: 160 000 запросов в сутки расходятся по разным IP, и нагрузка на каждый отдельный адрес остаётся маленькой. Трафик считайте заранее. JSON-ответ WB весит килобайты, браузерная карточка Ozon даже с отрезанными картинками заметно тяжелее, и на десятках тысяч загрузок в сутки набегают ги габайты.
Мониторинг упирается в два ресурса: сколько запросов идёт одновременно и по скольким адресам они расходятся. У WinGate прокси для мониторинга цен работают с автоматической ротацией, новый IP достаётся каждому запросу, трафик безлимитный, а потолок в 5000 потоков с запасом перекрывает 48 потоков из расчёта выше. Под площадки есть отдельные страницы: парсинг wildberries и парсинг ozon. Подключение по IP или строкой IP:PORT:LOGIN:PASS, протоколы HTTP, HTTPS и SOCKS5. Общая логика сбора с ротацией разобрана в статье прокси для парсинга.
Расчёт стоит проверить на своём каталоге: пул открывается на бесплатный тест до 2 часов. Прогоните один полный съём на 1 000 товаров с двух площадок и сравните время прогона и долю пустых ответов с тем, что заложили в расчёт.
После запуска раз в сутки сверяйте число снятых карточек с длиной списка. Снялось меньше 97 процентов, и причину ищите в логе до следующего съёма, пока дыра в истории не разрослась на неделю.
Свежие статьи
