Каталог, который наполняется сам: парсеры, прайсы поставщиков и импорт, который можно откатить
Тысячи товаров из нескольких источников - это бесконечное копирование: новые модели, изменённые характеристики, новые фото, прайсы в разных форматах. Хаб за магазином Ezeden берёт эту работу на себя: сам читает источники, показывает, что изменится, и не даёт импорту испортить каталог.
Задача
Магазин с тысячами технических товаров зависит от данных, которые пишет не он. Производители меняют модели и характеристики на своих сайтах, поставщики присылают прайсы каждый в своём формате, а в старом магазине лежат годы работы над каталогом. Поддерживать всё это вручную - отдельная ставка, а один неудачный файл может обнулить цены или описания по всему ассортименту.
Мастер-каталог Ezeden должен был сам забирать данные - и безопасно: показывать, что изменится, останавливаться, когда что-то не так, никогда не затирать то, что поправил человек, и позволять откатить любой импорт.
Парсеры сайтов производителей
Там, где лучший источник - сайт производителя, хаб читает его страница за страницей, с разрешения владельца: название, описание, характеристики, фото, PDF-паспорта и чертежи, а также другие цвета модели.
Парсер по умолчанию работает аккуратно: одна страница раз в несколько секунд и только в ночное окно. Почти каждую ночь читается только то, что изменилось на сайте; раз в неделю полный проход проверяет всё.
Страница без артикула, названия или цены отклоняется как неполная: это не товар с пустым полем, поэтому она откладывается как нечитаемая, с причиной, и никогда не применяется. Если отказов больше 5 %, импорт задерживается: когда столько страниц не читается, почти всегда сайт сменил вёрстку. Ничего не применяется, команда получает письмо, а задержанный импорт показывает, какая часть страницы пропала. Парсер останавливается и тогда, когда сайт говорит “нет”: после пяти отказов подряд он не продолжает напролом, а следующий запуск продолжает с того же места.
Товар, снятый с производства, перестаёт продаваться: если полный проход больше не находит модель, хаб помечает её снятой с продажи, остаток распродаётся до нуля, товар уходит из списков категорий, а страница остаётся. Если модель вернулась - возвращается и товар. Решение менеджера всегда важнее.
Прайсы поставщиков без программиста
В хабе есть механизм для файлов поставщиков в Excel, CSV и XML. Менеджер заводит поставщика в админке, загружает пример файла и собирает шаблон: хаб по заголовкам предлагает, какая колонка - артикул, цена или остаток, менеджер поправляет и сохраняет. Преобразования - десятичные разделители, множитель, словарь значений, разбиение ячейки на список - это настройки, а не код.
Для каждого поставщика менеджер решает, по какой колонке узнавать товар, могут ли незнакомые строки создавать товары (по умолчанию о них только сообщается) и для каждой колонки - обновлять всегда, только заполнять пустые поля или писать только в новые товары.
Файлы приходят четырьмя путями: ссылка, которую поставщик держит актуальной, папка на FTP или SFTP либо почтовый ящик, где письмо выбирается по отправителю, теме и имени вложения. Хаб проверяет каждые несколько минут и никогда ничего не перемещает, не переименовывает и не удаляет на стороне поставщика. Каждый полученный файл сохраняется, так что любую поставку можно пересмотреть или применить снова.
Предпросмотр, аномалии и откат
Все источники проходят один путь: чтение в промежуточную зону, проверка, контроль аномалий, применение. До последнего шага живой каталог не меняется.
Предпросмотр показывает, что сделает импорт: какие товары будут созданы, изменены или останутся как есть, какие строки ни с чем не совпали, и каждое изменённое поле - как при проверке кода: удалённые слова красным, добавленные зелёным. Оттуда же менеджер сопоставляет незнакомую категорию, оставляет значение каталога или исключает строку. Первый файл нового шаблона всегда останавливается здесь.
Детектор аномалий задерживает импорт, если источник вдруг вернул намного меньше товаров, чем в прошлый раз, обнулил цены или остатки у большой части ассортимента или если слишком много страниц не прочиталось. Скачок цены выше заданного порога ставится на удержание, пока его не одобрит человек.
Ручную работу защищают режимы полей. Каждое поле товара либо синхронизируется с источником, либо локальное (исправлено вручную), либо заблокировано, а импорт обновляет только синхронизируемые поля. Описание, которое переписал менеджер, остаётся переписанным, что бы ни пришло в следующем файле.
Каждое значение, записанное импортом, остаётся в истории рядом с прежним. Поэтому можно откатить импорт целиком - новые товары уходят в архив, более поздние ручные правки сохраняются - или вернуть одно изменение.
Дубли и характеристики в порядке
Когда источников несколько, товар может прийти дважды. Хаб ищет дубли по EAN, по нормализованному артикулу производителя, по кодам модели в названии и по сходству, которое оценивает ИИ. Сам он товары никогда не объединяет: он показывает кандидатов менеджеру.
С характеристиками то же самое. Один источник пишет “Цвет”, другой - “Цвет модели”, третий - на другом языке. Менеджер объединяет два названия в одно, а старое остаётся синонимом, и следующий импорт попадает в нужную характеристику, а не создаёт её заново. Объединение можно отменить. Очередь кандидатов подсказывает, какие пары могут означать одно и то же: например, две характеристики, которых нет одновременно ни у одного товара и у которых много общих значений. Единицы пересчитываются при загрузке, так что “21,5 см” попадает в поле в миллиметрах как 215.
Группы вариантов и кадрирование фото
Смеситель в шести покрытиях - это шесть товаров, у каждого свой артикул, своя цена и свой остаток. Группа вариантов объединяет их в один переключатель цвета на странице товара. Группы берутся из источника - сайта производителя, где перечислены другие цвета, - или из правила бренда, которое читает покрытие из артикула. Иначе хаб предлагает товары с одинаковым названием, которые отличаются только цветом или покрытием. Какие характеристики образуют переключатель, предлагается один раз; дальше выбор за менеджером.
Фото принимаются в том виде, в каком их присылает производитель, в том числе TIFF, PSD и HEIC, и хранятся как мастер-файл ограниченного размера. Кадрирование - обрезка, масштаб, центровка, поля - хранится как данные, а не как правка файла, поэтому его всегда можно сбросить. Автокадрирование находит предмет на ровном фоне и даёт ему одинаковую долю кадра на каждом фото, так что цвета одной модели выстраиваются в ряд; снимок в интерьере остаётся как есть. Магазин получает нужные размеры в WebP с запасным JPEG.
Переезд с OpenCart
Первый каталог пришёл из существующего магазина на OpenCart. Хаб читает его базу напрямую и только на чтение: товары, тексты на обоих языках магазина, категории, характеристики, фото, документы из описаний, акции и сопутствующие товары. Клиенты и заказы не переносятся.
Тип каждой характеристики определяется по её значениям: числа с единицами становятся числовыми полями в базовой единице, короткий набор значений - списком, остальное - текстом. Текст, записанный не в тот язык, - русский в украинском поле, что видно по буквам, которые есть только в одном из языков, - очищается, чтобы его правильно заполнил слой перевода. Блоки фильтров магазина переносятся в соответствующие категории в том же порядке, но только для характеристик, которые действительно есть у товаров, а фильтр, убранный менеджером, не возвращается. Магазин можно перечитывать каждую ночь, и запуск, который что-то изменит, останавливается на отчёте об изменениях для менеджера.
Технологии
- Хаб: Laravel 13 + Inertia + React 19 + Ant Design
- Парсеры: Symfony HttpClient + DomCrawler
- Файлы: OpenSpout (xlsx, csv), потоковый XMLReader
- Доставка: Flysystem FTP/SFTP, webklex/php-imap
- Изображения: Intervention Image + Imagick
- Фоновые задачи: Laravel Horizon на Redis 7; данные в MySQL 8.4Результат
Подключить бренд или поставщика - это настройка и сопоставление, а не проект разработки. Каталог сам обновляется с сайтов производителей, из файлов поставщиков и старого магазина, при этом каждое изменение видно до применения, подозрительные импорты ждут человека, ручные правки не трогаются, а любой импорт можно откатить.



