Розробка price-агрегатора
Price-агрегатор — сервіс, який собирает ціни на однакові товари з різних магазинів і показує їх рядом. Користувач бачить, де дешевше, і переходить туди. Технічно це задача парсингу, нормалізації даних та сопоставлення товарів. Кожен з цих етапів нетривіальний у промислових масштабах.
Джерела даних
Дані про товари та ціни поступають трьома способами:
Прайс-листи та фіди — магазин предоставляє 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 (запис в timeseries)
↓
ElasticsearchIndexer (оновлення індексу)
Черга: Celery + Redis для Python-стеку, Laravel Horizon для PHP-стеку. Кожен фід обробляється незалежно, помилка в одному источнику не блокує інші.
Сопоставлення товарів
Найскладніша частина. Задача: визначити, що 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, особливо для різних формулювань одного товара. Модель обучається на історично підтверджених матчах.
Історія цін
Основна цінність агрегатора — не тільки поточна ціна, але й історія змін. Це означає, що кожна зміна ціни повинна записуватися, не перезаписуватися.
price_history (
id BIGSERIAL,
source_offer_id BIGINT,
price NUMERIC(12,2),
in_stock BOOLEAN,
recorded_at TIMESTAMPTZ DEFAULT NOW()
)
Для зберігання timeseries даних в PostgreSQL застосовуємо TimescaleDB — розширення, яке автоматично партиціонує таблицю по часу, прискорюючи вибірки за період. Альтернатива — InfluxDB або ClickHouse для високих навантажень.
Графік історії цін — стандартний компонент сторінки товара. Використовуємо Chart.js або Recharts, дані агрегуємо по дням: SELECT date_trunc('day', recorded_at), min(price) FROM price_history.
SEO-стратегія
Агрегатори генерують органічний трафік на сторінки конкретних товарів. Ключові запроси: «[назва товара] купити», «[назва товара] ціна», «[назва товара] дешево».
- Сторінка кожного канонічного товара: унікальний title з діапазоном цін
- Structured data:
Product+AggregateOfferзlowPrice,highPrice,offerCount - Статичні сторінки категорій з агрегованою статистикою (середня ціна, кількість пропозицій)
- Блог з оглядами та підбірками — довгостроковий SEO-трафік
Терміни
- MVP: фіди від 3–5 источників, ручний matching, сторінки товарів, базовий пошук — 8–12 тижнів
- Повноцінний агрегатор: автоматичний matching (fuzzy + ML), історія цін з графіком, кабінет магазина, партнерський трекинг — 20–30 тижнів
- Підключення кожного нового источника (парсинг): 3–7 робочих днів залежно від складності
Агрегатор — це продукт, який постійно вимагає операційної підтримки: источники змінюють структуру, товари потрібно реметчити, нові магазини підключати. Це не разова розробка, а платформа з командою підтримки.







