С начала работы над Fetchee у нас был план предложить решение для парсинга данных о товарах интернет-магазинов корпоративным клиентов и стартап-сообществу. Отзывы, которые мы собрали за время работы, говорили о его потенциальной востребованности и подвели к запуску нового продукта, который поможет разработчикам быстро создавать собственные приложения, на основе одной из главных функций Fetchee — сбора eCommerce данных и слежения за ценами в любых интернет-магазинах мира.

На старте проекта мы хотели как можно быстрее показать готовый продукт пользователям, поэтому старались упростить приложение всеми способами. Одним из вариантов был отказ от разработки собственного парсера интернет-магазинов и внедрение готового решения.

В целях сокращения объема повествования, упущу сравнение популярных приложений по извлечению данных с сайтов (если хотите увидеть это сравнение, оставьте свой голос в опросе в конце статьи). Достаточно будет сказать, что наиболее подходящим для нашей задачи оказался diffbot — крайне недешёвый сервис, популярный среди крупных компаний и стартапов с приличным финансированием. Его используют многие приложения для создания закладок, ведь качественный парсинг — это трудно.

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

  • Максимально автоматически определять основные параметры товара;
  • Работать с любой валютой и языком;
  • Учитывать географическое положение пользователей и особенности работы магазинов с этим регионом (язык, валюта и страна);
  • Определять магазины с дискриминационным ценообразованием (версия операционной системы и город в пределах страны).

Нам удалось реализовать все описанные выше принципы. Система обучается на новых данных и умнеет на глазах. Чем больше запросов — тем точнее она становится. Наше желание сделать выборку более разнообразной и стало одной из причин предоставления доступа к Product API сторонним разработчикам, т.к. темпы появления новых данных со стороны пользователей замедлились — 90% покупают в одних и тех же интернет-магазинах.

Итак, встречайте Product API от Fetchee. С его помощью вы сможете, указав любой URL товара в интернет-магазине, получить основные данные о вещи, включая название, изображение, цену и валюту. В случае с нашим API, вам не придется настраивать парсер под каждый сайт, система самостоятельно анализирует страницу и определяет нужные данные.

image

Например, вот результаты парсинга велосипеда с Avito.

{
   "id":"58234b6cfd920b507bfd6b1f",
   "url":"https://www.avito.ru/sankt-peterburg/velosipedy/velosiped_author_basic_rama_19_i_21_835103333",
   "title":"Велосипед Author Basic, рама 19\" и 21\"",
   "price":14900,
   "currency":"RUB",
   "img_url":"https://fetch.ee/assets/item-images/5823/4b78475d39467b4b25eb.jpg",
   "created_at":"2016-11-09T16:14:36.542Z",
   "last_track_at":"2016-11-09T16:14:48.061Z"
}

Модной сумки с Wildberries.

{
   "id":"5824212c65ef60477b38b890",
   "url":"https://www.wildberries.ru/catalog/3095060/detail.aspx?targetUrl=GP",
   "title":"Сумка, GUESS",
   "price":13560,
   "currency":"RUB",
   "img_url":"https://fetch.ee/assets/item-images/5824/2144475d39467b4b26de.jpg",
   "created_at":"2016-11-10T07:26:36.368Z",
   "last_track_at":"2016-11-10T07:27:00.544Z"
}

Или внедорожника с автомобильного сайта.

{
   "id":"5824219b65ef60477b38b8be",
   "url":"https://auto.ru/cars/new/sale/bmw/x6_m/1044423007-94d1a/",
   "title":"Продажа BMW X6 M II (F86) в Москве",
   "price":8099000,
   "currency":"RUB",
   "img_url":"https://fetch.ee/assets/item-images/5824/21ad475d39467b4b26df.jpg",
   "created_at":"2016-11-10T07:28:27.038Z",
   "last_track_at":"2016-11-10T07:28:45.516Z"
}

На любой странице, где есть цена, изображение и название товара — Product API найдёт эти данные и вернёт их вам в JSON для дальнейшей обработки.

Попробовать API можно прямо на странице Beta-программы. Если понравится результат тест-драйва, регистрируйтесь как разработчик — чем больше будет заявок, тем раньше мы предоставим полный доступ к API.

Нам очень интересно увидеть как ваши идеи воплощаются в жизнь с помощью Product API.
Я хочу увидеть сравнение парсеров товаров интернет-магазинов

Проголосовало 90 человек. Воздержалось 13 человек.

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

Поделиться с друзьями
-->

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


  1. renardf0x
    11.11.2016 11:18

    Цитата с https://fetch.ee/ru/developers/

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


    По факту имеем
    url: http://m.finn.no/car/used/ad.html?finnkode=15254566

    Вот что мы нашли.

    {
    «id»: «58257ccb65ef60477b39338f»,
    «url»: «http://m.finn.no/car/used/ad.html?finnkode=15254566»,
    «title»: «Mercedes-Benz C-Klasse»,
    «img_url»: «https://images.finncdn.no/dynamic/1280w/6/152/545/66_287309295.jpg»,
    «created_at»: «2016-11-11T08:09:47.474Z»,
    «last_track_at»: «2016-11-11T08:09:57.440Z»,
    «unprocessed»: true
    }

    И ладно, что отсутствует цена, валюта и другие характеристики. Смешнее всего id взятый с потолка.


    1. ragimovich
      11.11.2016 11:28

      ID не с потолка, а, судя по его виду, из MongoDB в которой хранятся результаты парсинга. Посмотрите на примеры в статье, там тоже нет "локальных" ID. Я вообще сомневаюсь в возможности "вытащить" "локальный" ID с помощью "универсального" парсера.


      Да и по поводу цены сложно товарищей винить — "89 900,-" это очень необычный формат обозначения валюты.


      1. silenzushka
        11.11.2016 11:31

        Про ID из MongoDB Вы правы. В формате, кстати, нет проблем (хотя если глянуть на HTML, дизайнерам можно руки оторвать). А вот валюта подвела для этой страницы.


    1. silenzushka
      11.11.2016 11:30

      Спасибо, что решили попробовать. ID в ответе — это идентификатор запроса, к товару он не имеет отношения. Система вернула unprocessed: true, что говорит о невозможности получит все данные. Валюту для этой страницы автоматически определить будет сложно, т.к. нет знака валюты у цены. Именно для таких диковинных сайтов и затеяли публичный API. Цену научимся обрабатывать и дам Вам знать.


      1. renardf0x
        11.11.2016 12:52

        На мой взгляд, было бы честнее предоставить список магазинов, где API работает, вместо утверждения о «любых».
        Однако, если расчет был на то, что множесто людей ринутся проверять, действительно ли любых, то решение верное =)

        Цену научимся обрабатывать и дам Вам знать.


        Вопрос из любопытства — обучение распознаванию происходит в автоматическом, полуавтоматическом или ручном режиме?


        1. silenzushka
          11.11.2016 13:14

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

          API на самом деле автоматически работает со всеми магазинами, которыми пользуется 95% покупателей в интернете. Но верстальщики самые находчивые люди, иногда пользователи добавляют такие сайты, где в коде идёт борьба бессмысленности с глупостью. В этом случае мы вытираем скупую слезу и делаем ручную настройку. Интересно, что товары из этого магазина интересуют, как правило, только одного пользователя.

          Видимо, для полной автоматизации, нужно будет реализовать систему машинного зрения и определения тематических блоков.


          1. renardf0x
            11.11.2016 13:27

            Грандиозная работа! Я в восхищении от методов.

            Прошу простить любопытство (это неуемная тяга к тестированию всего и вся).

            На примере, указанном в одном из комментариев ниже

            «title»: «370 руб. нет в наличии»,

            Насколько я понимаю, парсер не воспринял это как ошибку и, следовательно, не будет самообучаться на данном примере, верно?


            1. silenzushka
              11.11.2016 14:00

              Воспринял и обучился. Вот этот URL уже правильный http://dietjust.ru/products/14061117. API закешировало ошибочный ответ. Новые запросы отрабатывают правильно.

              P.S. Я ценю Ваше любопытство.


              1. renardf0x
                11.11.2016 14:50

                Ниже сказано

                Подкрутили алгоритм

                Отсюда я сделал выводы, что автоматический режим не сработал, что было бы вполне логично, т.к. парсер извлек эти (некорректные) данные как title, что подразумевает, что с его точки зрения это title и есть. Т.е. причин для парсера искать другой title (срабатывания некого триггера) я не вижу.
                Или он подвергает сомнению все собранные данные?


                1. silenzushka
                  11.11.2016 14:56

                  Возможно, я не правильно выразился где-то по тексту. Парсер учится, а указывать на его ошибки — задача человека. Сейчас реализован метод кнута, когда мы не даём систему права на вторую ошибку, принудительно заставляя обрабатывать данные правильно. В идеале, конечно, реализовать полноценную систему машинного обучения, когда от человека будет требоваться только проверка результатов и команды: Верно / Не верно, иди ещё подумай.


                  1. renardf0x
                    11.11.2016 17:09

                    Огромное спасибо за содержательные ответы! Весьма и весьма занимательная система. Очень интересно, во что она вырастет и какими возможностями обзаведется. Желаю успехов!


  1. nerumb
    11.11.2016 11:27

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

    Попробовал несколько ссылок указать, тот же ссылка. В начале несколько минут было «Ваш запрос обрабатывается..», а потом что превышено время ожидания.


    1. nerumb
      11.11.2016 11:28

      Со второй попытки все же нашлось, но без цены, описания и т.п.:

      {
          "id": "5825801c65ef60477b393545",
          "url": "http://www.tehnosila.ru/catalog/tovary_dlja_sporta/velosipedy_i_aksessuary/velosipedy/-/284900",
          "created_at": "2016-11-11T08:23:56.599Z",
          "last_track_at": "2016-11-11T08:28:20.869Z",
          "unprocessed": true
      }
      


      1. silenzushka
        11.11.2016 11:35

        Хаброэффект, не иначе. Всё-таки API в бете, может и призадуматься. Попробуйте ещё раз, цена Техносиле теперь в норме.


        1. nerumb
          11.11.2016 11:41

          del


  1. nerumb
    11.11.2016 11:46

    А с сайтами, которые динамически собирают страницу (spa и т.п.), каким образом вы собираете информацию (если не секрет)? На своей стороне полностью рендерите html и потом ее парсите?


    1. medvoodoo
      11.11.2016 12:13

      Я думаю, что таких сайтов-продавцов меньшинство, т.к. большинство продающих сайтов заинтересованы, чтобы в поисковики попадало как можно больше страниц товаров, и spa для магазина — очень неудачное решение


      1. silenzushka
        11.11.2016 12:52

        На западе их очень много. Значение SEO сильно преувеличено для магазинов. Т.е. запросы на конкретную модель, которая через 4-5 месяцев уже уйдёт из продажи, скорее всего будут перехвачены агрегаторами типа Яндекс.Маркет. Магазины сосредотачиваются на привлечении трафика на посадочные страницы. Ну а сделал пререндер и закешировать посадочную на SPA вообще не проблема.


    1. silenzushka
      11.11.2016 12:40

      По необходимости полностью рендрим страницу вместе с JS. По понятным причинам время ожидания обработки для SPA сайтов немного выше.


  1. Jawwal
    11.11.2016 12:53

    Есть интернет магазины, где важна авторизация, что бы видеть цену со скидкой (присвоенной пользователю). У вас есть/в планах решение?


    1. silenzushka
      11.11.2016 12:57

      В рамках Fetchee для пользователей такое решение есть. Оно не во всех случаях работает, правда. Как реализовать его для API пока не знаю, если только в запросе будет указываться логин/пароль или активная авторизационная кука.


  1. netserfer
    11.11.2016 13:00

    странный парсинг.

    url:
    http://dietjust.ru/products/23748692

    Вот что мы нашли.

    {
        "id": "58258e53b25795f760078d1b",
        "url": "http://dietjust.ru/products/23748692",
        "title": "370 руб. нет в наличии",
        "price": 370,
        "currency": "RUB",
        "img_url": "http://i.siteapi.org/G0mzV92ignFZHjq4iNhLNTfk0DE=/113x0:602x377/fit-in/156x120/filters:fill(transparent):format(png)/ea331f79b074863.ru.s.siteapi.org/img/e3d2f43973a2f83ec36641997f935d5f1ae972bc.jpg",
        "created_at": "2016-11-11T09:24:35.586Z",
        "last_track_at": "2016-11-11T09:24:47.417Z"
    }
    


    По какому принципу в данном случае он выбирал title для меня осталось загадкой.


    1. silenzushka
      11.11.2016 13:01

      Спасибо, что написали. Новые товары в этого сайта будут определяться верно. Подкрутили алгоритм.


  1. meft
    11.11.2016 13:25

    url:
    https://www.computeruniverse.ru/products/90659981/palit-geforce-gtx1060-dual.asp

    Как я понял, с двойной валютой парсер не справился:

    {
        "id": "58259b6740b895da69e0a2d6",
        "url": "https://www.computeruniverse.ru/products/90659981/palit-geforce-gtx1060-dual.asp",
        "title": "Palit GeForce GTX1060 Dual 6.0 GB High End видеокарта",
        "price": 234.37,
        "currency": "RUB",
        "img_url": "https://fetch.ee/assets/item-images/5825/9b9322ae47d46976383b.jpg",
        "created_at": "2016-11-11T10:20:23.492Z",
        "last_track_at": "2016-11-11T10:21:07.712Z"
    }
    


    1. silenzushka
      11.11.2016 13:53

      Спасибо за информацию. Сайт не простой, но система ошибается, а потом учится.


  1. Mak_Di
    11.11.2016 17:30

    Имеется ли в планах апи колл, которому можно передать ошибку парсинга, например, url, который не распарсил.
    Чтобы инфу не через хабр сообщать, а апишкой?


    1. silenzushka
      11.11.2016 17:39

      Я надеюсь, что к моменту запуска полноценного API эта функция не понадобится, ведь это наша забота проверять качество парсинга. Но такой вызов будет, в пользовательском приложении функция жалобы на товар есть.


  1. Mak_Di
    11.11.2016 17:46

    По этому урлу не получил ответ.
    Что по поводу бесплатных проудктов?


    1. silenzushka
      11.11.2016 17:50

      У Стима блокировка по возрасту. Можно обойти, но проще с ними по API интегрироваться, если кому-то понадобится следить за ценами на игры.

      Можете описать ситуацию, когда понадобится получить данные и следить за ценой на бесплатный товар?


      1. Mak_Di
        11.11.2016 17:51

        Сначала игра была платной, а позже стала бесплатной.


        1. silenzushka
          11.11.2016 17:53

          Хорошее замечание, спасибо. Будем учиться учитывать этот случай.


  1. mihmig
    11.11.2016 18:08

    Я так понял — данный сервис нужен для автоматического отслеживания цены/наличия на отдельный товар.
    Извлечение списка товаров со страницы каталоге не планируется?


    1. silenzushka
      11.11.2016 18:21

      Совершенно верно, мы используем технологию для слежения за ценами. Но кто-то может встроить Product API в свой сервис закладок, например. Или любое другое приложение, где пользователи хотят видеть базовую информацию о товаре. Например, модуль предпросмотра ссылок на интернет магазины для форумов или блогов.

      Если коллеги-разработчики скажут, что нужна функция по URL списка товаров пройтись и обработать все ссылки на вещи, да ещё принять в учёт пагинацию — сделаем. Главное, чтоб были кейсы, которые упростят жизнь и окажутся востребованными.


  1. peacemakerv
    14.11.2016 11:04

    Ваше API хотелось бы видеть для использования в приложениях, для создания мобильных клиентов сайтов, не имеющих API.
    Т.е. не только для одного выбранного товара, а для получения каталога (всех данных товара со страницы) с сайта.


    1. silenzushka
      14.11.2016 11:30

      Спасибо за идею! В теории можно так использовать API, но где сейчас движок магазина, который не поддерживает мобильные шаблоны? У нас в приоритете сбор данных о товаре, а не краулинг. Т.е. в принципе, уже сейчас можно использовать Product API совместно с Вашим краулером.


      1. peacemakerv
        14.11.2016 12:09

        Пожалуйста, жду доп. скидку, когда будет API готово :)
        Дело не в краулинге (я верно понял — хождение по страницам сайта ?) — а в получении данных о всех товарах с открытой страницы. Хотя по одному товару — согласен, что и сейчас будет работать.


        1. silenzushka
          14.11.2016 13:36

          Записал ;-) Выше в комментариях уже просили научить API обрабатывать страницы с со списком товаров. Начали уже тренировать систему.


  1. rankov
    14.11.2016 11:33

    Цена не пришла, описание тоже

    http://www.superdrug.com/Bourjois/Bourjois-Healthy-Mix-Foundation-Light-Vanilla-51/p/626461

    {
    «id»: «5828bfa540b895da69e1e038»,
    «url»: «http://www.superdrug.com/Bourjois/Bourjois-Healthy-Mix-Foundation-Light-Vanilla-51/p/626461»,
    «title»: «Bourjois Healthy Mix Foundation Light Vanilla 51»,
    «img_url»: «http://www.superdrug.com/medias/custom-content/microsites/starbuys/popup/2016/wk46/starbuys_wk46.jpg»,
    «created_at»: «2016-11-13T19:31:49.615Z»,
    «last_track_at»: «2016-11-13T19:31:59.686Z»,
    «unprocessed»: true
    }


    1. silenzushka
      14.11.2016 11:33

      Спасибо за наводку. Обновили правила парсера, теперь корректно работает с сайтом.


  1. alekciy
    19.11.2016 23:38

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


    1. silenzushka
      20.11.2016 00:05

      В следующей заметке расскажу больше про команду (спасибо, что спросили ;-). И по технике будет чем поделиться, уже тестируем определение бренда производителя.