Data Scientist
14,4
рейтинг
26 ноября 2015 в 10:41

Разработка → Анализ изменения цен в российских интернет-магазинах


В последние пару лет меня достаточно сильно интересовал вопрос ценообразования в российских интернет-магазинах. Каждый раз при заявлении интернет-магазина о большой скидке в душу закрадывается сомнение… Действительно ли такая большая скидка? Была ли реальна цена которая сейчас зачеркнута?
Резкие изменения курса доллара в конце 2014г. подлили масла в огонь. Очень захотелось получить ответ на вопрос как зависят цены от курса доллара в реальности.
В итоге, я решил покончить с этими вопросами и собрать историю изменения цен по российским интернет-магазинам. По катом результаты работы + несколько интересных закономерностей.

Немного технический подробностей


На данный момент в системе работают несколько десятков парсеров написанных на python.
Хранить данные в лоб мне показалось очень расточительным, решил хранить только изменения цены. Если цена не меняется — записи в БД не создаются, такой подход позволяет очень хорошо экономить ресурсы. На данный момент в таблице всего 200 000 000 строк, что не так много для данных по ~100 000 товаров в >1000 магазинов за 8 месяцев.
В качестве хранилища используется MySQL 5.6. Недавно пришлось переехать на SSD, так как обычные HDD на Hetzner не очень справлялись с большой нагрузкой на запись.

В данной статье я хотел бы описать интересные закономерности найденные при анализе собранных данных:

1. Синхронное изменение цены


Собрав базу за несколько месяцев, я решил проанализировать коэффициент корреляции между предложениями одного и того же товара от разных магазинов. Для этого был быстренько набросан скрипт на python + pandas. Pandas в данном случае очень помог наличием функции resample.

sql = """
SELECT pr.date, pr.shopitemid, price from prices AS pr
JOIN shopitems AS si
ON pr.shopitemid = si.id
WHERE si.itemid = 1
AND si.shopid > 10
AND si.last_price IS NOT NULL
ORDER BY pr.date
""" 
df = pd.read_sql_query(sql, engine)
for item in df['shopitemid'].unique():
    x= df[df['shopitemid'] == item]
    nans = x.isnull().sum()['price']/float(len(x))
    if nans > 0.2 or len(x['price'].unique()) < 10 or \
    x['date'].min() >  (datetime.now() - relativedelta(months=3)):
        df = df.drop(df[df['shopitemid'] == item].index)
df = df.dropna()

df = df.pivot(index='date', columns='shopitemid', values='price')
df = df.fillna(method='pad')
df = df.dropna()
df = df.resample('24h', fill_method='pad', how='last', loffset='24h')
mtrx =  df.as_matrix().T
columns = df.columns.values

corr = np.corrcoef(mtrx)
z = np.where(corr > 0.90)
for x,y in zip(z[0],z[1]):
    if x<y:
        print columns[x],columns[y]
        myplot(mtrx[x])
        myplot(mtrx[y])
        
        plt.show()

Проанализируем историю изменения цен на примере холодильника Indesit SB 185.
На выходе получились достаточно интересные графики типа такого:


Ещё графики





Здесь можно посмотреть данный график в более удобном формате.
В данном примере видно что у трех магазинов цена изменяется абсолютно синхронно в течение 8 месяцев. Мне видятся такие вероятные причины такого явления:
  • В двух из трёх используются системы автоматического выставления цены на основе цен конкурентов.
  • Магазины как-то связаны организационно и имеют доступ к общей БД цен


2. Появление нового смартфона.
В момент анализа я наткнулся на график цен по Samsung Galaxy S6.



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

3. Самые дешевые интернет-магазины для каждой категории товаров


Собрав достаточно большую базу цен, появилась идея сформировать ТОП-10 самых дешевых магазинов для каждой категории товаров.
Разберем принципы формирования данного списка на примере категории Холодильники:
Пробегаемся по каждому товару категории.
Каждому магазину, продающему данный товар, начисляем баллы от 0-дорого, до 1-дешево.
Алгоритм расчета баллов score = (maxprice-price)/(maxprice-minprice)
Вычисляем среднее от баллов набранных каждым магазином.
Удаляем магазины продающие очень мало товаров данной категории.

Например, для категории телевизоры, получился такой список:
Название
Кол-во баллов
Рейтинг на Yandex.Market
Кол-во оценок на Yandex.Market
КРАСНАЯ КНОПКА
0,877
5
697
Топтел
0,854
5
1358
Pleer.ru
0,853
4
52711
Greenbook
0,853
5
200
ОГО
0,832
5
4009
Technosteps.ru
0,832
5
294
Soundbreeze
0,812
5
662
ELECTROGOR
0,808
5
6445
ЦИФРОВИК
0,805
5
460
ЭЛЕКТРОЗОН
0,804
5
1664


4. Зачем же я всё это писал?


В качестве фидбэка от уважаемого сообщества мне очень хотелось бы получить ваши идеи по анализу данного датасета.
Что ещё можно проанализировать, какие интересные закономерности попробовать найти?
Чтобы предоставить возможность каждому посмотреть историю цен, тем более скоро черная пятница, я набросал простенькую веб-морду с возможностью поиска по товарам. Можете поиграться тут, надеюсь, не ляжет.

UPD 01.12.2015: Добавил возможность уведомления при снижении цены ниже определенного порога.
Сергей @ssh1
карма
34,0
рейтинг 14,4
Data Scientist
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Разработка

Комментарии (62)

  • 0
    Отличный сервис, весьма полезно. Только таблицы не сортируются, а жаль.
    • 0
      Да, это первый вариант. Я думаю соберу фидбэк и что-то доработаю.
      • 0
        Нужно из графика выкидывать (может опционально) экстремум. Сейчас получился например такой график, ничего не разглядеть.
        • 0
          Да, это косяки при сборе данных. Лучше обрабатывать при сборе, а не на выводе.
          Спасибо за пример.
  • +13
    В данном примере видно что у трех магазинов цена изменяется абсолютно синхронно в течение 8 месяцев. Мне видятся такие вероятные причины такого явления:

    В двух из трёх используются системы автоматического выставления цены на основе цен конкурентов.
    Магазины как-то связаны организационно и имеют доступ к общей БД цен


    Я вот буквально вчера на сайте МВидео читал, что они готовы продать товар по меньшей цене, если у конкурентов цена меньше. Так вот, оказывается, они учитывают только тех конкурентов — а там прям явно написан их список мелким шрифтом внизу, каких — у которых цены точно такие, как у них плюс-минут 100 рублей. А у кого цены меньше на несколько тысяч — «сорри, это неправильный конкурент».

    Очевидно, что цены они согласуют между собой, вопрос только в механизме.
    • +2
      Этот механизм называется РРЦ. А подобные функции типа «готовы продать товар по меньшей цене, если у конкурентов цена меньше» делаются в первую очередь для мониторинга цен конкурентов усилиями клиентов, в не самого магазина. Все немного иначе с другой стороны. ;)
      • 0
        Вот только если у кого-то реально цены ниже — то они не готовы по такой цене продать
        • 0
          Готовы. Покупал объектив за 5к вместо 6
          • 0
            А сколько вы времени потратили в поисках у кого дешевле?
            • 0
              Минуты 2
              • +1
                С другой стороны, вы сказали, что есть дешевле, и вам отдали за 5к. Через 10 минут пришёл другой покупатель, он не знал, что есть дешевле, и взял за 6к. Тоже вполне себе модель бизнеса.
                • 0
                  Все верно, а параллельно они включают определенные рычаги и цена конкурента становится не 5 тыс, а те же 6 тыс.
        • 0
          Кто-то готов. Но, возможно, кто-то возьмет от вас полезную информацию, а продавать не будет. Хотя последний случай очень странный и ведет не только к потере клиента и минимального дохода, но и к негативной оценке. Мы, бывало, даже в минус себе продавали, только бы отстоять заявленные нами правила игры. Не скажу, что это сделало нас в итоге супер-счастливыми, но факт в том, что такие магазины бывают, если задаться целью их найти.
  • +2
    А еще они могут иметь одного поставщика.
    • +1
      И фиксированные наценки.
  • +1
    Некоторые (многие?) магазины могут играть ценой за счет изменения цены доставки, специально или так получается, но это тоже важно, особенно если товар категории до 5т.р. даже 500р доставка уже ощутима.
    Можно парсить их предложение по доставке в пару тройку регионов страны пары-тройки товаров разной категории (мини — сотовый, средний — ноутбук/монитор,… большой — холодильник), соответственно визуализация может быть либо учтена в графиках при выборе особенности стоимости доставки выше либо отдельные графики по каждой категории товаров.
  • +2
    Вообще, очень крутая тема:
    1. Можно пробовать ловить демпинг. На некоторые товары есть минимальная цена. Производитель обычно строго следит, чтобы она не нарушалась, можно ему помочь
    2. Пробовать определять успешность продукта по тому, как быстро падает его цена. Например, сравнить Айфоны
    3. Пробовать предсказать по первым неделям продаж, какая будет цена через несколько месяцев. Поможет определиться покупать сейчас или подождать
    4. Проверять действительно ли магазин делает скидку или сначала повешает, а потом понижает цену
    5. Посмотреть с какой задержкой и как влияют курсы на цены и предсказывать цены исходя из курсов
    • +3
      Только часто бывает цена на сайте одна, а звонишь — и там она, оказывается, совсем другая, такая же как у конкурентов («не успели обновить сайт»).
      • 0
        Не часто, но первые 3-5 строчек на прайсру действительно мошенниками забиты. Наверное, они статистически должны выявляться провалом в 5% от всех конкурентов.
    • 0
      Спасибо за идеи.
      1. Вопрос где её взять, да, и интересно ли это производителю.
      2. А является ли падение цены критерием успешности?
      3. Интересно, но отсмотрев вручную около сотни графиков закономерностей не нашёл.
      4. Спасибо, надо подумать как достать предложение о скидке. Бывает приходит рассылка: «Вот купон, он дает ссылку 10% на эти товары» и т.д.
      5. Тоже думал. Доллар вырос в 2 раза. У многих товаров цена вообще не зависит от него. Хотя возможно она бы падала в случае неизменного курса.

      Вообще я думал попробовать предсказать цену товара на основе прошлых цен + цен на товары в других категориях. Есть надежда что цены на стиралки, например, могут являться хорошими фичами для предсказания цен на холодильники. Пока не дошли руки.
  • 0
    Замечательный сервис, спасибо. Праздный вопрос — повествование ведется от первого лица, ниужели это все сделано «в одни руки»?
    • +1
      Спасибо. Да, долго, нудно, но в одни )
      • +1
        Снимаю шляпу )
      • 0
        Вы цены откуда берете?
        Из xml-выгрузок?
        Или парсите сайты? Все >1000?
        И почему магазинов больше 1000, а товаров всего то 100 000?
        • 0
          Парсинг магазинов/аггрегаторов
          100 000 имеется в виду уникальных товаров, а не пар товар-магазин.
          Да, кстати, как поживает ваш аналогичный проект? Планируется какое-либо развитие?
          • 0
            Спасибо, что спросили.
            Сам сервис живет нормально.
            Всё работает, цены каждый день я скачиваю и отображаю на сайте. С этим нет проблем.
            С развитием пока не делаю ничего.
            Скоро приступлю, я думаю к доработкам.
            И первое, что сделаю, это нормальный удобный интерфейс. )))
            • 0
              А что за проект?
  • 0
    Поиск несколько странный. Sony z5 не находит, выдаёт кучу товаров и ни одного телефона.
    • +1
      Согласен, поиск не очень хорош. Думаю прикрутить sphinx как дойдут руки.
      • 0
        Может на хабре опишете как реализован ваш проект? Какие технологии, языки, библиотеки…
        • 0
          Парсеры python + urllib
          База MySQL 5.6 недавно перешел на SSD
          Пришлось немного повозиться чтобы научиться писать данные без избыточности
          WEB — python + Django + bootstrap + highcharts
          Memcached
          Среднее время ответа сервера, судя по ньюрелик, 20-30мс. Учитывая что в кэше явно есть не всё, считаю это вполне достойным результатом)

  • +1
    В копилку «дурацких идей» — вполне очевидная секция «Latest Deals». Навеяно «Черной пятницей».
    Список TOP X товаров, цена на которые опусилась [в магазине N] ниже медианы на YY% за какой-то период.

  • 0
    Хотелось бы копию проекта, натравить на магазины своего региона! А то перед покупкой много работы приходится делать в поисках…
    И то находишь цену, уточняешь, а она не актуальна или нет в наличии и т.д…
  • 0
    Как строится монетизация проекта?
    • 0
      Пока никак, с рекламы есть надежда окупить часть затрат на сервер.
      В дальнейшем, была идея преобразовать это в сервис рекомендаций по ценообразованию. Отслеживаем цены конкурентов -> выставляем оптимальную цену на автомате.
      Но это уже другая история, вопрос, дойдут ли руки.
  • +1
    Замечательная работа проделана. Спасибо.
    Может быть стоит добавить к графику кривую курса $, добавило бы наглядности скачков цен, а точнее их обоснованности курсом или подготовкой к «распродаже».
    • 0
      Спасибо. Скорее всего действительно добавим.
  • –4
    А вы ведь данные собираете какими то ботами?
    Можете сделать канал у нас в сервисе PushAll, чтобы можно было подписываться на определенные товары? Ну т.е. например если цена на какой то товар упадет ниже определенной цены — уведомить меня об этом push-уведомлением.
    Даже можно сделать эту фичу платной, чем собственно окупить в итоге ваш проект.
    PS. у нас в сервисе будут платные каналы, можно на основе этой платформы сделать платный канал с оповещениями о изменении цен.
    Например я хочу купить Nexus 9 где нить в районе 20-21к, вроде цена много где падает, причем интересно. что цена уже сейчас ниже чем зарубежом в $, интересно упадет ли еще.
  • +4
    А как вы связывали товары между собой?
    В магазинах же может быть разное название у одного и того же товара.
    • 0
      Это делает API Яндекс.Маркета, на сколько я понял принцип сервиса.
      • 0
        Связки достаточно сделать один раз.
        Тут работает свой алгоритм определения близости по цене и названию + парсинг агрегаторов. В общем есть куда развиваться.
        • +1
          Раз не из Маркета берёте, то за алгоритм (и его ручную доводка) отдельный респект. Огромная работа.
          • 0
            Скажем так: часть там, часть там.
            Бывает такое в названиях накрутят)
  • 0
    Здравствуйте. Заинтересовался сервисом и решил проверить на личном опыте.
    На днях подбирал смартфон и, в частности, смотрел на модель Prestigio Muze C3. Один такой уже купил жене, теперь заказал дочке.
    Так вот, оба телефона приобрел в Юлмарте.
    Ваш сервис сообщает что на сегодня (27.11.15г.) его нет в наличии в данном магазине. Иду в магазин — есть. Возможно его нет в каком-либо другом городе. Но тогда нужно и это учитывать в Вашем сервисе. Либо Вы не смогли получить данные с сайта (вчера в 19:00, например, сайт Юлмарта лежал глухо).
    И да, они, видимо как и все другие, перед «черной пятницей» подняли на него цену, а затем сделали скидку. Скидка здесь без кавычек, так как скинули все-таки больше, чем добавили. «Но осадочек остался».
    Ваш сервис показывает что вчера (26.11.15) цена на него была 7490руб., но я его приобрел вчера же со скидкой за 5990руб.
    А вообще приятный сервис. Лишний раз убедился что честных скидок не бывает.
    • 0
      Спасибо за комментарий. Данные на графиках выводятся после ресэмплинга, соответственно, если на графике точка в 18:00, это не значит, что именно в 18:00 была такая цена. Плюс к этому магазины скорее всего очень часто меняют цены в период чёрной пятницы.
      Спасибо за фидбэк, попробую изучить подробнее что происходило.
      • 0
        Возможно проблема в том, что нет цены на этот телефон в магазине Юлмарт на Яндекс.Маркете.
        • 0
          Как вариант. Спасибо, посмотрю подробнее.
  • 0
    Впечатляет! Очень интересно, спасибо. Помимо курса доллара, о котором говорили выше, еще хотелось бы на графиках видеть собственно даты (месяцы), чтобы понять наличие сезонных колебаний цен (есть ли смысл покупать под Новый Год, например)
    • 0
      Спасибо. Какие даты вы имеете в виду? Снизу вроде есть даты?
      • 0
        Да, вы правы. Это я сфокусировалась на графиках по холодильникам — там по оси Х только числа (номера наблюдений, видимо).
        Получается, вы где-то с весны начали собирать данные (смотрю опять же холодильники на сайте), то есть про Новый год можно будет в следующем году сказать. И кстати про 8 марта тоже будет интересно, по каким категориям цены меняются, если меняются вообще.
        Интересно, что максимальная цена меняется чаще и больше, чем минимальная — почему так может быть? Возможно, минимальная установлена на уровне близком к нулевой рентабельности?
        • 0
          Да, все праздники в следующем году можно будет отследить в реальном времени.
          Мне кажется, максимальная цена меняется чаще, так как в районе максимальной цены плотность магазинов намного меньше чем в районе минимальной. Соответственно пропадание товара в магазине с максимальной ценой ведёт к более резкому скачку.
  • 0
    А еще вопрос: сколько человекочасов заняла организация парсинга (написание, отладка)? А сколько написание этого материала, включая анализ? Мне кажется, это огромная работа, хочется оценить ее как-то количественно )
    • +2
      Проект делался в свободное время, в качестве хобби.
      Если пересчитать:
      Парсинг + отладка + игра «успей за изменениями на источнике» — 5 недель
      Веб морда — 3 недели
      Анализ — 5 часов
      Статья — 1 час

      Могу ошибаться в 2-3 раза в любую сторону)
  • 0
    Сколько магазинов подключено вручную? Ведь довольно много магазинов, которых нет на маркете.
  • 0
    Есть ли API или выгрузка для интернет-магазинов?
    Учитываются ли разные цены на разные цвета в одной карточке товара?
    Сюда ещё бы интеграцию с я.маркетом, чтобы помечалось «эта позиция в этом магазине рекламируется в я.маркете». Ведь не все магазины там размещаются, поэтому не всегда там лучшие цены.
    Максимальная цена возможно считается неправильно в этом товаре http://priceanalytic.com/item/3612/, цифра 88800 пишется, но магазинов с такой ценой нет.
    Ну и актуальный фичареквест — переключатель рубли/USD/Euro для исторических данных.
    Также хотелось бы обновления таблицы магазинов при нажатии на дату на графики, например непонятно кто это устроил аттракцион невиданной щедрости 3го августа здесь http://priceanalytic.com/item/40352/
  • 0
    API и интеграции пока нет.
    По ошибкам и предложениям спасибо, подумаю.
  • 0
    Всем спасибо за обратную связь.
    Добавлены уведомления при снижении цены ниже определенного порога.
  • +2
    Круто! Народ, зацените график для цен на айфоны priceanalytic.com/item/73558. Видны два отчётливых пика перед 4 и 11 ноября, которые были днями распродажи) Очередное доказательство, что чёрная пятница в РФ не более чем утка!
  • 0
    <к_слову>А помните эту тему?! Сервис снова работает.</к_слову>
  • 0
    Добрый день.
    Скажите, техподдержка по сайту ещё работает?
    У меня просьба приделать поиск товаров по маске. Я вам писал много раз.
  • 0
    В Fetchee мы решаем задачу слежения за ценами каждый день, причём делаем это в любых интернет-магазинах. Возможно, автору и читателям будет полезен наш новый сервис для разработчиков, который позволяет парсить данные о товаре по URL. Недавно мы опубликовали на Хабре подробную замету про наш Product API с примерами.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.