Как стать автором
Обновить

Как мы автоматизировали большой интернет-магазин и стали сопоставлять товары автоматически

Время на прочтение21 мин
Количество просмотров24K
Всего голосов 20: ↑19 и ↓1+18
Комментарии33

Комментарии 33

Хорошая, наверно, работа получилась. Молодцы.
К нам когда-то обратился клиент, у которого подобным образом сливались прайсы поставщиков и возникла проблема, что в авторежиме какая-то группа NVMe накопителей идентифицировалась как SATA, соответственно в анализ и прайс шли цены на порядок ниже. Это вызвало довольно много неприятных моментов в общении с клиентами.
Изучив проблему, перестроили систему таким образом:
1) уболтали всех поставщиков предоставлять в прайсе свои артикулы, артикулы производителя и наименование товара в отдельных колонках (в цифрах — порядка 50 поставщиков, ассортимент 250к уникальных позиций, ежедневная загрузка порядка 2х миллионов строк);
2) создали внутренний «эталонный» справочник наименований товаров, каждому товары присвоили свой уникальный артикул;
3) процедура автоматической линковки товаров поставщиков к эталонному справочнику осталась преимущественно старой, но добавили возможность ручной перелинковки в случае ошибки, слинкованные товары (автоматически или вручную) в автолинковку уже не попадали;
4) во все товарные документы, с момента определения поставщика и партии, стали подставлять наименование и артикул поставщика, чтобы менеджер/кладовщик мог вычитать и сообщить, если автолинковка дала сбой и товар, который заказал клиент это не тот, который предлагает поставщик.
Компания осталась довольна, хаос стал подконтрольным, залёты с ценами прекратились.
Возможно, это будет следующим шагом и в вашей системе.
Хорошо когда поставщики готовы что-то менять. Хотел уточнить как с таким справляетесь, пример «согласовали прайс поставщика» уточнили 100% вот железно ничего менять не будут. Через 3 дня либо добавят колонку в xls, либо поменяют её название, либо вообще другой файл пришлют. Потом оказывается что они его руками формируют. Дошло до того что перед заливкой данных из прайса идет сравнение с прошлым прайсом на предмет «не поменялся ли формат» и если поменялся — уходит уведомление руководителю торгового направления.
Мы делаем так: у поставщиков есть конфигурируемое время устаревания, а поставщика мы автоматически узнаем по формату файла (названия колонок, вкладок, возможно, контактная информация в файле). Если колонки добавились, поменялись местами и так далее — то все ок, мы его узнаём и продолжаем обрабатывать. Если совсем другой файл — мы его не обработаем, соответственно, цены устареют, и мы покажем об этом предупреждение на главной странице. Пойти и исправить настройки под новый формат занимает две-три минуты, поэтому исправляем сами и с поставщиком даже не связываемся (если это не системно происходит).

При работе с 400 поставщиками менять настройки приходится один-два раза в неделю.
Phoenix-lib,
Было несколько поставщиков, у которых ИТ на аутсорсе, и им пришлось помочь с формированием выгрузки прайса из учетной системы.
Но по большому счету они все уже работали на автомате, руками в эксель никто не лазил, как их учетная система формировала файл, так его и высылали. Учетки разные (1с 7/8, SAP, Axapta, кастомные CRM, в т.ч. на ASP, PHP), но эксель выгружали исправно.
Для тех, кто пытался отказаться менять формат файла, у нас был бронебойный аргумент — «Компания не будет вручную разносить ваши цены. Если вы не сможете предоставить выгрузку в приемлемом виде, ваши товары не будут в системе, и компания не сможет их продавать фактически.» Технари, они понятливые. Две колонки в файле делаются за пару часов (с тестами и выкладкой в прод), а при отказе мы пошли бы к их начальству, что ничем хорошим для них не закончилось бы.
Тут надо понимать, что наш заказчик — клиент своих поставщиков, а значит, по рыночным правилам, всегда прав ) Этим и воспользовались.
Дошло до того что перед заливкой данных из прайса идет сравнение с прошлым прайсом на предмет «не поменялся ли формат»
250 тыс товаров, 2 млн строк — в среднем по 8 предложений на товар в нашем случае. Поэтому, если один поставщик не будет загружен из-за неверного формата, или часть строк его будет пропущена, на бизнес-логику нашего заказчика это не повлияло бы, товар не уникальный, есть у конкурентов, пойдет от другого поставщика. Сам поставщик понимает, что не в его интересах менять форматы.
Сама система при загрузке отображает статистику — сколько строк в файле, сколько загружено, сколько из них слинковано, сколько ошибочных строк. Загрузку контролирует оператор, так что на административном уровне может обнаружить косяк с форматом — вылезет большое число ошибок и таблица загружаемых товаров будет пустой после зачитки файла.
Загрузка прямо из почты была отключена, т.к. нужен был контроль за ценообразованием. Т.е. сначала грузятся все прайсы поставщиков, затем рассчитывается и утверждается прейскурант на текущий день для клиентов (прейскурантов несколько, но не суть), после чего клиентам делается автоматическая рассылка сегодняшних цен. И до конца дня работа ведется по этим расчетам. Утром следующего дня цены рассчитываются по-новой.

Вообще, мне сложно представить, что поставщик отказывается менять формат выгрузки прайса или меняет его слишком часто. В его интересах, чтобы его товар продавался быстро и удобно.
Лет 15 назад, когда обмен файлами остатков был еще не у всех и не всегда, были случаи, когда в прайсах могло быть разное количество колонок (например, для разных товарных групп или разных форм оплаты — с НДС/без НДС и колонки). Тогда проще всего было определять номер колонки по заголовку столбца — «Артикул», «Наименование», «Цена», «Остаток». Тоже неплохо работал алгоритм.
До внедрения этой проверки часто могли возникать ситуации когда колонка остатков становились на место цен, а цены на место остатков
У нас всегда перед загрузкой проверяется формат файла и наличие ожидаемых данных в ожидаемых местах. Если, например, в какой-то строке нет артикула — вся строка уходит в отбраковку, результат преобразования в число количества или цены равен или меньше нуля — брак. Разве что наименование не валидировали. Мало ли поставщик просто коды пришлёт, чтобы можно было обновить данные без загрузки новых товаров.
Я вот подумал — 6 человек на зарплате занимаются сопоставлением выгрузки. А может быть найти несколько самых неаккуратных поставщиков и слить их/постаивть ультиматум. Просто жесть же сколько им на зарплату уходит (если в белую).
6 человек на зарплате занимаются сопоставлением выгрузки
Жестко, бессмысленно и беспощадно! )))

Это не только сопоставления, это в том числе и в первую очередь наполнение сайта содержимым. Поиск характеристик товаров, изображений и так далее. Эту часть мы тоже автоматизировали насколько смогли, но про неё я не писал, потому что решение временное и работает с большего на старом коде. А автоматизация заключается в сопоставлении с конкурентами, мы из новой системы отдаём ссылки на страницы с описанием товаров, а дальше полуавтоматический паркинг уже на старом коде.


Уволить — не вариант, у нас план активно расти и, наконец, дело сдвинулось с точки.

А Вы найденные характеристики Яндексу в YML выгружаете?
Да. Но эта часть пока работает на старой инфраструктуре и к ней есть вопросы, в первую очередь по прозрачности процесса.

В свое время делал специальную программу для схожих задач — http://pricematcher.ru. Она даже неплохо продавалась. Потом из-за нехватки времени забросил развитие. Сейчас пет-проджектом потихоньку некий аналог делаю, но с хранением данных в облаке (основное неудобство, с которым сталкивались пользователи pricematcher, было то, что приходилось заморачиваться с установкой и настройкой mssql server).
Ну и есть несколько других готовых программ у моих "конкурентов", которые упрощают процесс сопоставлений прайсов. Поищите, если не искали, а то немного похоже на изобретение велосипеда.

Изначально у нас было платное решение для 1с. Работало плохо, и с идеей перейти на другую систему мы работали два года. Искали, пробовали разные системы. Одну попробовали внедрить, но не пошло. Своё начали делать практически от безысходности.


Если рассказывать о причинах, то разные системы не подошли по разным причинам. Большинство сопоставляло плохо и медленно, но были и другие вопросы. Интеграции, возможности конфигурировать ценообразование и иногда немного демпинговать и так далее.

А какие системы ещё всё-таки пробовали? Я отрыл сейчас свои записи. Elbuz E-Trade, как мне казалось, имели наиболее обширные возможности. И ещё штук 20 их там.
Просто из ваших описаний я не увидел никаких особо нестандартных задач, вроде бы все то же самое, что и всем владельцам магазинов обычно надо. Странно, что ничего не подошло

Да, у них самые обширные возможности и их мы рассматривали. У них на сайте есть калькулятор, если количество записей ( каталог, поставщики, конкуренты) выставить в 500 000, больше калькулятор не даёт, то получается больше 1500$ в месяц. А у нас записей больше пяти миллионов, если все считать. Даже на специальных условиях и если поторговаться — много получается. (Мы не торговались, если что)


Или, например, такое в тарифном плане (в другом сервисе) «Ротация: 5 SKU в рабочий день (обрабатываются по 5 SKU в день в порядке добавления)». Это план за 150 долларов. А нам надо минимум в сто раз больше.


Не всех пробовали лично, где-то получалось договориться с партнерами день поработать у них и посмотреть, как все происходит.


Делать антирекламу кому-то я не хочу, поэтому перечислять всех не буду.

Вот что только люди не делают, лишь бы не внедрять MDM
А что это?
Очень здорово, когда есть несколько алгоритмов для 400 поставщиков! Представляю себе ситуацию, когда каждый поставщик будет предоставлять свои API и для магазина потребуется много реализаций. :)

Как вы считаете, правда ли то, что если на СНГ рынок ворвётся Amazon или EBAY, то можно сворачивать активность своего интернет магазина?
Думаю, да, если придет амазон или алибаба — все сильно изменится. Ебей скорее останется незамеченным. Но в любом случае рынок будет стремиться к укрупнению, останется только несколько крупных игроков. Это не произойдет в один момент. Просто у магазинов в том виде, в котором они есть сейчас, дела пойдут немного хуже. Через год закроется 20%. Еще через год — еще 20%. И увидеть переломный момент и начать менять концепцию бизнеса смогут не все, большинство будет занято текущими проблемами.

Но в то же время, я думаю, у интернет-магазинов есть шанс адаптироваться. Уйти в узкие ниши во-первых. Амазон все же про массовость. Принять амазон как площадку и работать по его правилам, во-вторых. Стать сервисным провайдером для того же амазона, в-третьих. Построить инфраструктуру с нуля на всей террирории России пока никому не удавалось, и вряд ли Амазон в это станет вкладываться.
Как вы считаете, правда ли то, что если на СНГ рынок ворвётся Amazon или EBAY, то можно сворачивать активность своего интернет магазина?
Амазон и Ебей — это разные системы. Общего у них только агрегатор интернет-магазинов (у нас есть Яндекс.Маркет). Амазон.Пэй конкурирует с Пейпал (аналог Яндекс.Деньги). Амазон прайм, фулфилмент и стор не имеют аналогов в Ебей и Яндексе.
Таким образом, что-то измениться может, только если Амазон захочет открыть свой магазин и автоматом потянет фулфилмент и прайм услуги.
Вероятность такого события крайне мала, т.к. для открытия своего магазина придется сертифицировать кучу товаров, либо использовать локальных поставщиков, которых используют все другие интернет-магазины. В любом случае для Амазона это будет мясорубка, на которой можно построить тотализатор.

С учетом того, что Амазон работает жестко в рамках инструкций, разработка их под российский рынок займёт не один год. И даже если инструкции будут успешно разработаны, у интернет-магазинов будет достаточно времени, чтобы адаптироваться — сменить ассортимент или лечь под Амазон заблаговременно.
если на СНГ рынок ворвётся Amazon или EBAY


ebay давно пришёл, уже несколько лет назад покупал в русских магазинах разную мелочёвку (речь именно о магазинах, а не о частниках)
1. Расскажите, пожалуйста, каким образом вы создавали начальную базу карточек товаров?
А именно:
— сколько процессов, сколько ip адресов понадобилось и как создавался маршрут для получения необходимой информации :)
— каким образом решали вопрос с водяными знаками на фотографиях

2. Какой тип хостинга предпочли для системы? Рассматривали ли возможность экономии, купив собственное железо, на котором работают массивные части системы например как обработка прайсов и +реплика в облаке на подстраховку в случае отказа локальной машины?
1. По карточкам товаров не могу ответить подробно, это сделано до меня. Но доля ручного труда там большая, настраиваются соответствия, замены и так далее.
Водяные знаки — проблема. В частных случаях помогает опыт олимпиадного программирования и знание принципов обработки изображений.
2. Хетзнер в нашем случае лучше собственного железа. Не надо решать вопросы с охлаждением, питанием и так далее. Машина в облаках с такими характеристиками раз в 10 дороже. Скорее всего, там же и останемся в ближайшее время, возможно, возьмем больше машин по мере роста нагрузки. Архитектура проекта позволяет. Но в настоящем времени на подстраховку у нас только регулярные бекапы.
Спасибо!
Поставщикам, которые заказы получают в собственном формате, выгружайте дополнительно каждый раз заказы ещё и в формате, который на Ваш взгляд мог бы быть отраслевым стандартом. Тот же YML. И напоминайте время от времени их начальству, что вот в таком формате всем было бы удобнее, и им в том числе.

Такая вода очень эффективно точит камень. Постепенно, импортилки заказов к себе из такого удобного формата могут сделать очень многие из ваших поставщиков.
Спасибо, попробуем. Дельная идея.
А в процессе работы были ли попытки использовать sphinxsearch?
Нет, конкретно sphinx не пробовали.
Я не работал с sphinx, но elastic или full text search нам не подходят по следующим причинам:
  • Скорость. Я не знаю, как достичь 10 000 сопоставлений в секунду
  • Гибкость. Мы потратили несколько месяцев, придумывая алгоритмы, подбирая оптимальные параметры, тестируя каждое изменение. Я не знаю, как можно настроить, например, больший приоритет у токенов, которые содержат и буквы, и числа.

Со sphinx (или другим универсальным движком) можно получить результат быстрее. Писать что-то свое узкоспециализированное было долго и сложно, но, думаю, это было правильным выбором с учетом нашей цели обрабатывать десятки миллионов товаров в день.
Дальше придумали хэш-функцию, не чувствительную к порядку токенов

А можно немного подробнее раскрыть? Ведь замысел в том, что бы один и тот же товар давал один и тот же хэш, так? Но если в названии товара пропушена часть названия? Разве в припеденном в статье примере все эти название дадут один хэш?
Замысел состоит в том, что есть простые, быстрые и точные способы сопоставить товары. Например, полное совпадение названий. Потом совпадение названий с точностью до перестановок (с оговоркой, что существует единственный вариант). И если сработал один из этих способов, то результат у нас есть, и дальше обрабатывать товар не нужно. Естественно, это работает не всегда, на одних данных ничего не дает, на других дает 10% сопоставлений.

Не все названия из примера дадут одинаковый хэш. Но после алгоритма с хэшированием есть еще другие, которые могут сопоставить эти товары.
Просто перестановка токенов даем же нам комбинаторный взрыв. Или перестановка в одном варианте, допустим в алфавитном? Но это не решает проблему пропущенных токенов в названии т.к. дает другой кэш. Хотя дальше видимо идет сравнение по триграммам или нечто подобное?
А сколько по времени занимает проверка через эту цепочку фильтров проверка? Я на коленке когда-то собирал подобное (используя в том числе морфологический словарь нормализацию слов), но выходило это достаточно долго. Если не ошибаюсь больше секунды.
Мы не генерируем перестановки, хэш-функция, которая не чувствительна к порядку, вполне с этим справляется.
Вариант с пропущенными токенами обрабатывается позже.
Что касается скорости, то на относительно современном ноутбуке (i5-7300HQ) сопоставляется 10 тысяч записей в секунду. С сохранением результатов в базу — 2-5 тысячи в секунду. Обработка 2.5 миллионов цен занимает около 5-10 минут.
10к RPS это в однопоточном режиме, так? Когда все данные для работы находятся в ОЗУ?
А есть ссылки на почитать насчет хэш функции? Я как то привык, что разные строки дают разный хэш. А тут получается без перестановок и учета пропустов две разных строки дают один хэш. Звучит непонятно.
10-20к RPS — это с данными в памяти, да.
А что касается функции, то, не вдаваясь в нюансы, такая будет соответствовать условиям с перестановками. С пропусками — нет, там другой алгоритм, не все сводится к хэшам.

public static int GetHash(string s){
    return GetHash(s.Split(' '));
}

public static int GetHash(IEnumerable<string> tokens)
{
    long hash = 0;
    foreach (var token in tokens.Distinct())
    {
        hash ^= token.GetHashCode();
    }
    return hash;
}
Спасибо, теперь понятно. Я просто изначально немного удивился про хэши. Теперь в целом ясно. Цепочка проверок, каждая вносит в итог какой-то вес.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории