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







