Попробовать
Назад к блогу

Мониторинг цен конкурентов через прокси: как построить парсинг цен

Мониторинг цен конкурентов через прокси: как построить парсинг цен

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

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

Ротируемые прокси

Ротируемые резидентские прокси с гео до города для мониторинга цен конкурентов

Попробовать

Схема целиком

Цикл мониторинга цен: список товаров, расписание, сбор через прокси, извлечение цены, хранение истории и уведомления
Мониторинг цен как цикл: сопоставить, запланировать, собрать, извлечь, сохранить, оповестить
  1. Каталог и сопоставление. Список ваших SKU и для каждого — адреса аналогичных товаров у конкурентов.
  2. Планировщик. Решает, как часто заходить на каждый адрес.
  3. Сборщик. Скачивает страницы или ответы API через пул прокси.
  4. Извлечение и нормализация. Превращают разметку в чистую запись: цена, валюта, наличие, продавец, время.
  5. Хранилище и оповещения. Держат всю историю, сравнивают новое значение с прошлым и сообщают нужному человеку.

Каждый этап ломается по-своему, поэтому делайте их отдельными модулями со своими логами. Когда оповещения замолчали, нужно сразу видеть, что случилось: встал планировщик, кончились прокси или сломался селектор.

Схема мониторинга цен
Схема мониторинга цен

Шаг 1. Сопоставление товаров

Мониторинг хорош ровно настолько, насколько точны пары товаров. Сравните свою бутылку на 500 мл с упаковкой конкурента на литр — и все отчёты окажутся неверными.

  • Сначала идентификаторы. GTIN, EAN, UPC или артикул производителя (MPN) дают точное совпадение. Многие магазины показывают их в разметке schema.org или в таблице характеристик.
  • Затем атрибуты. Бренд, модель и ключевые параметры (объём, размер, цвет) выручают, когда кодов нет. Перед сравнением приведите единицы к одному виду: граммы, миллилитры, штуки.
  • Нечёткие названия — в последнюю очередь. Сходство по токенам или эмбеддинги текста отбирают кандидатов, но сомнительные пары человек должен один раз подтвердить; дальше подтверждённая пара живёт в каталоге.

Храните пары таблицей с полями your_sku, competitor, url, match_type и confidence. Время от времени перепроверяйте их: маркетплейсы отдают старые адреса карточек под другие товары чаще, чем кажется.

Шаг 2. Расписание: как часто проверять

Частота должна зависеть от того, как часто меняется цена, а не от одного общего cron. Практичная разбивка:

Группа товаровОбычный интервалПочему
Хиты продаж на маркетплейсахРаз в 1–4 часаАвтоматическое переоценивание меняет цену несколько раз в день
Основной каталогРаз в суткиХватает для еженедельных ценовых решений
Длинный хвост2–3 раза в неделюЦена меняется редко, экономится трафик
Период акцийЕжечасно, пока идёт акцияСкидки начинаются и заканчиваются в неожиданное время

Распределяйте запросы по интервалу, а не запускайте всё ровно в полночь: всплески выглядят по-роботски и перегружают ваших же воркеров. Хорошо работает адаптивное расписание: если цена товара две недели не менялась, проверяйте его вдвое реже; если сегодня поменялась дважды — вдвое чаще.

Шаг 3. Сбор страниц через прокси

Страницы с ценами защищают одними из первых: магазины не хотят пускать именно конкурентов. Сборщик, который тысячи раз в день ходит на один домен с одного адреса, получит ответы 403 и 429, капчу, а в худшем случае — тихо подменённые цены. Из-за последнего каждую запись потом нужно проверять.

Правила здорового сбора:

  • один IP обращается к одному домену не чаще нескольких раз в минуту;
  • повторные попытки идут через другой IP с экспоненциальной задержкой;
  • заголовки, язык и часовой пояс соответствуют стране выходного IP;
  • cookies держатся в одной сессии, если магазин привязывает цену к выбранному городу или адресу доставки.

Наши ротируемые прокси выдают новый адрес на каждый запрос или на заданный интервал — это удобно для каталогов из тысяч ссылок. Темп и заголовки подробнее разобраны в статье о том, как снизить риск блокировки при парсинге.

Шаг 4. Извлечение и нормализация цен

Перебирайте источники по степени надёжности:

  1. Структурированные данные. Многие магазины встраивают для поисковиков объекты schema.org Product и Offer в формате JSON-LD: price, priceCurrency, availability, иногда gtin13. Такая разметка переживает редизайны.
  2. Встроенное состояние или внутренние API. Современные витрины подгружают цены из JSON-эндпоинта, который видно во вкладке Network браузера.
  3. HTML-селекторы. Запасной вариант; выбирайте стабильные атрибуты вроде data-testid, а не сгенерированные классы.
# offer_reader.py: price and stock from schema.org JSON-LD, with a sanity check
import json
from decimal import Decimal
from bs4 import BeautifulSoup

def read_offer(html: str) -> dict | None:
    soup = BeautifulSoup(html, "html.parser")
    for tag in soup.select('script[type="application/ld+json"]'):
        try:
            blob = json.loads(tag.string or "")
        except json.JSONDecodeError:
            continue
        nodes = blob if isinstance(blob, list) else blob.get("@graph", [blob])
        for node in nodes:
            if node.get("@type") != "Product":
                continue
            offer = node.get("offers") or {}
            offer = offer[0] if isinstance(offer, list) else offer
            amount = offer.get("price") or offer.get("lowPrice")
            if amount is None:
                continue
            return {"price": Decimal(str(amount)), "currency": offer.get("priceCurrency"),
                    "in_stock": "InStock" in str(offer.get("availability", ""))}
    return None

Больше всего мусора возникает при нормализации. Строки вида 1 299,00 ₽ или $1,299.00 переводите в десятичное число с явным кодом валюты, а не во float. Фиксируйте, какую именно цену сняли: базовую, со скидкой, по карте лояльности или с купоном. Доставку храните отдельно: два магазина с одинаковой ценой и разной стоимостью доставки — не одно и то же предложение.

Перед сохранением проверяйте каждую запись. Цена, упавшая за ночь на 90 %, чаще оказывается ошибкой разбора или страницей-приманкой, чем настоящей скидкой, — помечайте её на проверку, а не поднимайте тревогу в отделе продаж.

Шаг 5. Региональные цены

Многие ритейлеры назначают цену по стране, а крупные маркетплейсы — по городу или складу. На то, что вы увидите, влияют две вещи: геолокация IP и регион, сохранённый в сессии (cookie с выбранным городом или индексом доставки).

Чтобы надёжно снять региональную цену, берите выходной IP в этом регионе, выбирайте город так, как это сделал бы покупатель, и читайте цену в той же липкой сессии. Прежде чем верить цифре, проверьте, какой регион определил магазин; почему базы иногда расходятся, объясняет статья о геолокации по IP. Особенности маркетплейсов разобраны в руководствах по парсингу Wildberries и парсингу Ozon.

Одна и та же мышь Corsair на Amazon: цена для США в долларах и для Великобритании в фунтах
Один товар, две цены: регион доставки меняет то, что показывает Amazon

Шаг 6. Хранение и оповещения

Ведите таблицу наблюдений только на добавление: sku, competitor, price, currency, in_stock, region, collected_at. Из неё получаются текущая цена, графики истории и события изменений. Такое хранилище ещё и позволяет доказать, когда конкурент поменял цену, — это важно для контроля минимальной рекламируемой цены (MAP).

Оповещения, которые действительно читают:

  • срабатывают на процентный порог, а не на любое изменение;
  • не повторяются: одно сообщение на одно изменение, а не на каждый обход;
  • для длинного хвоста собираются в ежедневную сводку, мгновенно — только по ключевым SKU;
  • содержат старое и новое значение, ссылку и скриншот или HTML-снимок как доказательство.

Какие прокси выбрать для мониторинга цен

ПлощадкаТип проксиПочему
Крупные маркетплейсы с сильной антибот-защитойРотируемые резидентскиеДомашние IP, большой пул, гео до города
Магазины, живущие в мобильных приложенияхМобильныеIP оператора делят много реальных абонентов
Небольшие магазины и сайты брендовДата-центровыеДёшево и быстро там, где защита слабая
Цены по конкретным городамРезидентские с липкой сессиейРегион и корзина не меняются

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

Частые вопросы о мониторинге цен

Законен ли парсинг цен?

Сбор публично показанных цен — распространённая и в целом допустимая практика, но законы, правила сайтов и права на базы данных различаются по странам. Не заходите в личные кабинеты, не собирайте персональные данные, не давите запросами и сверяйтесь с местными нормами при коммерческом использовании.

Как часто проверять цены конкурентов?

По волатильности: раз в несколько часов для хитов маркетплейсов, раз в сутки для основного каталога, несколько раз в неделю для длинного хвоста. Больше всего трафика экономит адаптивное расписание, которое ускоряется после изменений.

Почему я вижу не те цены, что реальные покупатели?

Магазин мог распознать дата-центровый IP, чужую страну или невыбранный город и показать цену по умолчанию либо намеренно изменённую. Используйте IP в регионе покупателя и выбирайте город в той же сессии.

Какие прокси лучше для мониторинга цен?

Ротируемые резидентские прокси справляются с защищёнными маркетплейсами и региональными ценами, для слабо защищённых магазинов хватает дата-центровых. Мобильные IP помогают с ритейлерами, которые живут в приложениях.

Как сопоставить свои товары с карточками конкурентов?

Начните с кодов GTIN, EAN или MPN, затем переходите к бренду, модели и нормализованным характеристикам, а нечёткие совпадения по названию один раз подтвердите вручную. Подтверждённые пары храните в таблице каталога.