Вы заходите на сайт, вводите «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+ реализованных проектов. Мы не просто пишем код — мы проектируем архитектуру, которая не падает под нагрузкой и легко масштабируется. Оценим ваш проект бесплатно. Свяжитесь — предложим архитектуру, сроки и стоимость под ключ.







