Вы заходите на сайт, вводите «Samsung A55», а он показывает цены из 20 магазинов, сортирует по дешевизне и строит график динамики. Мы разрабатываем такие price-агрегаторы — платформы, которые автоматически собирают цены, сопоставляют товары и показывают пользователю лучшие предложения. Технически это комплексная задача: парсинг разнородных источников (YML, API, HTML), нормализация данных, нечёткое сопоставление (matching) и непрерывное обновление. Каждый этап полон подводных камней: от rate limiting до разницы в названиях товаров. За более чем 5 лет работы мы накопили опыт в построении отказоустойчивых систем сбора и матчинга, которые обрабатывают до 1 млн товаров в сутки. Ошибка на этапе матчинга — и пользователь видит неверные цены или дубли. Веб-парсинг без контроля — блокировка и штрафы. Мы гарантируем стабильность и точность данных благодаря продуманной архитектуре. Это позволяет нашим клиентам экономить до 40% бюджета, исключая ручные проверки.
Как организовать сбор данных из разных источников?
Источники данных
Данные о товарах и ценах поступают тремя способами:
- Прайс-листы и фиды — магазин предоставляет YML, XML, CSV файл с актуальным ассортиментом. Самый надёжный источник: структурированные данные, официальное партнёрство, нет рисков бана. Яндекс.Маркет YML — де-факто стандарт для русскоязычного рынка.
- API партнёров — некоторые магазины предоставляют REST API. Документация обычно слабая, лимиты запросов — жёсткие. Согласно официальной документации Яндекса, для партнёрских ссылок требуется предварительное согласование.
- Веб-парсинг — для магазинов без фидов. Высокий риск: капча, rate limiting, изменение вёрстки, блокировка IP. Требует постоянной поддержки.
На старте агрегатора лучше работать только с фидами и API — это устойчивее. Парсинг подключаем избирательно для ключевых источников.
Архитектура сборщика данных
Scheduler (Celery Beat / Laravel Scheduler)
↓ каждые N часов FeedFetcher workers (по одному на источник)
↓ RawData storage (S3 или локальная FS)
↓ Parser workers (XML/CSV/JSON → нормализованные объекты)
↓ Normalizer (приведение единиц, очистка текста)
↓ Matcher (сопоставление с товарами в БД)
↓ PriceHistory (запись in timeseries)
↓ ElasticsearchIndexer (обновление индекса)Очередь задач: Celery + Redis для Python-стека, Laravel Horizon + Redis для PHP-стека. Каждый фид обрабатывается независимо, ошибка в одном источнике не блокирует остальные.
Парсинг Яндекс.Маркет YML
YML — XML с жёсткой схемой. Критичные поля:
<offer id="12345" available="true">
<url>https://shop.example.com/product/12345</url>
<price>4990</price>
<currencyId>RUB</currencyId>
<categoryId>14</categoryId>
<name>Samsung Galaxy A55 128GB</name>
<vendor>Samsung</vendor>
<model>Galaxy A55</model>
<barcode>8806095076783</barcode>
<param name="Цвет">Синий</param>
<param name="Объём памяти">128 ГБ</param>
</offer>Штрихкод (barcode) — лучший ключ для matching'а. GTIN/EAN уникален для каждой вариации товара. Если штрихкод есть у большинства поставщиков — сопоставление становится тривиальным. Согласно документации Яндекс.Маркета, barcode — рекомендованный элемент для точного сопоставления.
Почему product matching — ключевой этап?
Это самая сложная часть агрегатора. Задача: определить, что Samsung Galaxy A55 128GB Синий от магазина A и Смартфон Samsung Galaxy A55 (SM-A556B) 128 Гб синий от магазина B — один и тот же товар.
Детерминированные методы
- GTIN/EAN матчинг: если у обоих товаров есть штрихкод — однозначное совпадение.
- Артикул производителя (MPN): SM-A556B уникален в рамках бренда.
- URL-каноникализация: некоторые магазины включают GTIN в URL.
Нечёткий матчинг (fuzzy)
from rapidfuzz import fuzz
def match_score(title_a: str, title_b: str, brand_a: str, brand_b: str) -> float:
if brand_a.lower() != brand_b.lower():
return 0.0
title_similarity = fuzz.token_sort_ratio(title_a, title_b)
return title_similarity / 100
Порог совпадения: 0.85+ считаем автоматическим матчем, 0.65–0.85 — отправляем на ручную проверку, ниже — новый товар.
ML-подход
Эмбеддинги названий товаров (sentence-transformers, ruBERT) + cosine similarity. Значительно точнее fuzzy, особенно для разных формулировок одного товара. Модель обучается на исторически подтверждённых матчах.
Структура хранения:
canonical_products (id, gtin, mpn, brand, name, category_id, attrs JSONB)
source_offers (id, source_id, external_id, canonical_product_id, price, url, in_stock, updated_at)
match_candidates (offer_id, canonical_id, score, status) -- pending | approved | rejectedСравнение методов матчинга:
| Метод | Точность | Скорость | Сложность внедрения |
|---|---|---|---|
| Детерминированный (GTIN) | 100% | Высокая | Низкая |
| Нечёткий (fuzzy) | 80–90% | Средняя | Средняя |
| ML (эмбеддинги) | 95%+ | Низкая (требуется GPU) | Высокая |
Как обновляются цены и хранится история?
История цен
Основная ценность агрегатора — не только текущая цена, но и история изменений. Каждое изменение цены записывается, не перезаписывается.
price_history (
id BIGSERIAL,
source_offer_id BIGINT,
price NUMERIC(12,2),
in_stock BOOLEAN,
recorded_at TIMESTAMPTZ DEFAULT NOW()
)Для хранения timeseries используем TimescaleDB — расширение PostgreSQL, партиционирующее таблицу по времени. Альтернатива — InfluxDB или ClickHouse для высоких нагрузок (до 10 000 вставок в секунду).
График истории цен — стандартный компонент страницы товара. Используем Chart.js или Recharts, данные агрегируем по дням: SELECT date_trunc('day', recorded_at), min(price) FROM price_history WHERE ....
Частота обновления
| Тип источника | Интервал обновления |
|---|---|
| YML-фид крупного магазина | Каждые 2–4 часа |
| API с лимитами | По лимиту, обычно 1–6 раз в сутки |
| Парсинг страницы | 1–2 раза в сутки |
| Real-time API (редко) | По webhook при изменении |
При изменении цены — инвалидация кеша страницы товара и пересчёт минимальной цены в индексе.
Как настроить сбор данных за 4 шага
- Подключение источников: получите YML-фиды от магазинов или настройте API-доступ. Один источник — один конфиг.
- Настройка парсинга: для фидов — готовый парсер YML/XML; для API — напишите адаптер под документацию.
- Запуск матчинга: определите набор правил — GTIN приоритет, затем fuzzy, затем ML. Начните с ручной валидации.
- Мониторинг и обновление: настройте шедулер Celery или Horizon, добавьте алерты на падение источника.
Что входит в разработку агрегатора
В результате вы получаете:
- Документацию по интеграции источников (описание форматов, примеры).
- Развёрнутую инфраструктуру (Docker, CI/CD, мониторинг).
- Панель управления для редактирования матчинга и просмотра статистики.
- Обучение команды заказчика работе с системой.
- Техническую поддержку на 3 месяца после запуска.
- Гарантию на корректность матчинга и своевременность обновления цен.
Хотите обсудить ваш проект? Свяжитесь с нами для оценки. Получите консультацию инженера.
Наш опыт
Более 5 лет на рынке, 40+ реализованных проектов. Мы не просто пишем код — мы проектируем архитектуру, которая не падает под нагрузкой и легко масштабируется. Оценим ваш проект. Свяжитесь — предложим архитектуру, сроки и стоимость под ключ.







