
Парсер Яндекс Маркет с помощью ZennoPoster за 30 минут.
Одна из основных задач с которыми сталкиваются владельцы интернет-магазинов – это его наполнение, не говоря уже об анализе конкурентных предложений, мониторинге цен, корректировке описаний и многом другом.
Представьте сколько Вы потратили бы времени и денег, делая это всё вручную или делегируя такую работу фрилансерам? И то, и другое требует постоянных инвестиций т.к. данная работа циклична, но с помощью ZennoPoster Вы можете решить все вопросы с минимальными затратами, не прибегая к помощи программистов.
Парсинг – это обработка информации по определённому алгоритму. То, что человек делает за несколько дней по сбору и обработке информации, парсер выполнит весь объем работы, пока Вы будете пить чашку чая.
Чаще всего парсинг интернет магазинов вызывает недоумение у начинающих вебмастеров, ведь звучит так сложно и непонятно, что приводит к тратам на программы или скрипты, работающим по задумкам автора (разработчика) и не имеющим тех или инных функций, необходимых именно Вам.
Благодаря ZennoPoster Вы сможете создать собственный парсер, который будет работать так как Вы захотите, без программистов, регистраций и смс всего за 30 минут. Не верите? Читайте дальше!
На примере Яндекс Маркет мы создадим автоматизированный шаблон, который будет собирать названия товаров, фотографии, цены и другие данные с последующей выгрузкой в Excel \ CSV файл.
Статья будет содержать информацию, как для новичков, так и для продвинутых пользователей.
Создаем шаблон парсера Яндекс Маркет за 30 минут. Быстрый старт для новичка.
Всё начинается с создания нового проекта, далее нам необходимо добавить действие перехода на страницу, а точнее категорию товаров, данные которых мы будем собирать.
Ссылку на категорию мы будем указывать во входящих настройках при запуске шаблона. Создаём InputSettings и добавляем туда текстовое поле.
Но перед тем, как продолжить нам необходимо изучить пациента и выстроить логику работы. Для примера возьмём каталог мобильных телефонов.
Зайдя на страницу, первое на что я обратил внимание – это количество отображаемых позиций: 12. Их определённо необходимо увеличить.
Сделать это мы можем с помощью переключателя:
Так же мы видим 2 варианта перехода на следующую страницу:
- Подгрузка данных
- Классический постраничный листинг
Я выбираю второй вариант т.к. если выбрать первый, в процессе работы браузер может начать тормозить или вовсе зависнуть от большого количества данных с которым Ваш ПК не справится.
И, пожалуй, изменим вид отображения так как нам нужны ещё и краткие характеристики товара.
Стоит заметить, что при клике на иконку, изменился URL нашей страницы. Появился параметр: viewtype=list
И вместо того, чтобы эмулировать нажатие иконки для смены вида отображения, мы просто подставим данную конструкцию в URL изначально.
Добавляем действие перехода на страницу, где в качестве ссылки мы указываем:
{-Variable.URL-}list?viewtype=list
Сразу выполняем этот кубик и продолжаем работу прямо во внутреннем браузере Project Maker. Теперь нам необходимо добавить 2 действия клика для смены кол-ва видимых позиций.
Исследуем элемент выпадающего списка и пробегаем по его свойству и древу в целом.
Наша задача – определить параметр(ы) для поиска нужного нам элемента на странице. Желательно чтобы в найденных отображался только он. Я остановился на таких значениях:
Жмём кнопку “Добавить в проект”. Далее делаем тоже самое для выпадающего списка, пункта “Показывать по 24”.
При таком раскладе у нас находится 2 элемента, а нам нужен один. Поэтому я решил добавить ещё параметр поиска. Для этого так же жмём “Добавить в проект” и щелкаем 2 раза левой кнопкой мыши по ново-созданному кубику.
И в условиях я указал:
- Группа: 0
- Атрибут: innerHtml
- Тип поиска: regexp
- Значение: 24
- Номер совпадения: 0
А для нашего первого условия поменял номер совпадения с 0 на “0-end”. Это было сделано для того, чтобы если вдруг изменится набор пунктов, поиск проходил не только по первой позиции, а по всем пунктам от начала и до конца. Подробнее о диапазонах читайте здесь: https://zennolab.com/wiki/ru:ranges
О правильном поиске элементов Вы можете прочитать в одной из конкурсных статей: Правильный поиск элементов на странице и работа с ними! Основы и хитрости! Должен знать каждый!
Переходим непосредственно к парсингу. В рамках данной статьи собирать данные мы будем только со сниппетов карточек товаров т.е. не переходя на саму страницу.
А именно: Наименование, Цена, Категория и подкатегория, Характеристики (краткие), Фотография и Ссылка на товаров в Я.М.
Из всего набора данных один из параметров является статичным, поэтому его нужно будет спарсить только один раз – это (под)категория.
Расположение которой находится в самом вверху и именуется, как “Хлебные крошки”. Чтобы удобнее было распарсить всё это дело, предлагаю положить фрагмент этого HTML кода в отдельную переменную, путём исследования элемента по условиям:
- Группа: 0
- Атрибут: id
- Тип поиска: text
- Значение: n-breadcrumbs
- Номер совпадения: 0
И действием GET, где атрибут outerhtml.
Если мы не изменим переменную назначения, данные попадут в автоматически созданную. Теперь нам необходимо получить названия ссылок и отправить их в переменную “cat”.
Делать мы это будем с помощью регулярных выражений. Если Вы не умеете с ним работать, рекомендуем ознакомиться с этими статьями:
Так же в ProjectMaker есть удобный конструктор регулярных выражений, где Вы можете просто заполнить соответствующие поля и регулярка сформируется автоматически.
Добавляем кубик обработки текста, а в опциях выбираем Regex.
Итоговое регулярное выражение:
(?<=a class="link[^"]*"[^>]+>)[\w\s]+
Так как нужна вся иерархия, забираем “Все” и кладем в список.
Следующим шагом объединяем в переменную “cat” и очищаем список.
А куда мы будем складывать данные? Пора создать файл сделать привязку.
Создаём таблицу “Файл экспорта” и делаем, как на скриншоте:
Отлично! Добавляем действие -> Таблицы –> Операции над таблицей, в опциях выбираем «Привязать к файлу».
Путь:
{-Project.Directory-}{-Variable.cat-}[{-TimeNow.Datedd-MM-yy-}].csv
Где последний тег – это время.
Файл будет выглядеть примерно следующим образом: Электроника-Телефоны и аксессуары к ним-Мобильные телефоны[03-11-17].csv
Как насчёт заголовков в нашем CSV файле?
Между 2-мя этими кубиками следует добавить паузу секунд на 5, чтобы файл успел создаться.
Мы будем парсить по одному сниппету, а далее в цикле разбирать его по косточкам. Вновь возвращаемся к нашему любимому занятию – исследование элемента с GET’ом на атрибут outerhtml. А после жмём по кубику правой кнопкой мыши и выбираем пункт “Повторить в цикле”.
У нас появилась авто-переменная counter0, её необходимо будет добавить в номер совпадения, чтобы по итогу у нас получилось так:
- Атрибут: class
- Тип поиска: regexp
- Значение: n-snippet-card2 b-zone i-bem
- Номер совпадения: {-Variable.Counter0-}
А всё, что попало в {-Variable.0-}, мы кладём в список “Карточки товаров”.
Вот, что у нас получилось:
Откуда взялось {count}, спросите Вы. Вместо него должно быть число 24 так как именно столько товарных позиций будет на каждой странице. Но может, например, сломаться селект или что-то не прогрузится и их кол-во не изменится, поэтому имеет смысл сделать программную проверку.
Создадим C# кубик и расположим его перед синим кубиком со скриншота. Его содержимое:
return instance.ActiveTab.FindElementsByAttribute("div", "class", "n-snippet-card2 b-zone i-bem", "regexp").Count;
Чтобы его не потерять, выделите код в кубике и нажмите правую кнопку мыши, а далее по пункту “Сохранить в C# сниппет”. Теперь, если появится необходимость в подсчёте элементов, достаточно будет кликнуть «Вставить C# сниппет».
Результат кладём в переменную “count”.
А минус -1 в конце потому, что «машинный счёт” идёт с 0, а не 1. Можно, конечно, построить цикл по-другому или вообще отказаться от него, но об этом в другой раз.
Как только все элементы будут обработаны, можем приступать ко второму циклу – парсингу значений по мини-карточкам товаров, которые сейчас находятся в списке “Карточки товаров”.
Протягиваем красную стрелку от кубика логики к «Получению строки из списка с удалением», которую будем класть в переменную data. А дальше начинается разрабор данные с помощь регулярок.
Название
(?<=<div\ class="n-snippet-card2__title"><a[^>]+>)[^>]+(?=</a></div>)
Цена
(?<=<div class="price">от&nbsp;)[\d\s]+
После нам необходимо убрать в цене лишние пробелы, чтобы было не так 6 990, так 6990.
Делаем это с помощью замены текста по Regex, а конкретно {-String.Space-} (пробел) на пустую строку.
Характеристики
(?<=li class="n-snippet-card2__desc-item">)[^<]+
Но здесь нам необходимо получить все совпадения, а не первое. Поэтому кладём результат в список «Временные данные» и после объединяем элементы в переменную char. По завершению удаляем данные из списка.
Изображение
(?<=img class="image" src=")[^"]+
Ссылка на карточку в Я.М.
(?<=a class="link[^"]*" href=").*?search
В ссылке может быть HTML-сущность, которую необходимо заменить на обычный символ.
В переменную yam_link упадёт относительная ссылка. Если же нам нужна абсолютная, добавьте кубик обработки переменных со значением:
https://market.yandex.ru{-Variable.yam_link-}
Финальным шагом мы добавляем полученные данные в нашу таблицу «Файл экспорта», которая привязана к файлу.
Добавить действие -> Таблицы -> Операции над таблицами -> Добавить строку
Далее считаем сколько осталось строк в списке “Карточек товаров” и кубиком логики проверяем, чтобы это значение было > 0. Цикл будет продолжать, пока не будут обработаны все данные.
Как только все товары со страницы будут обработаны, пора переходить к следующему листу, протянув красную стрелку к следующему блоку:
Первым кубиком мы выводим оповещение в лог.
Далее плюсуем 1 ед. к переменной по подсчёту обработанных страниц.
Щелкаем по кнопке вперёд, как это сделать, я думаю Вы уже знаете, но если у Вас возникнут сложности, в конце статьи будут шаблоны, где Вы сможете подсмотреть решение.
А далее в случае успеха мы переходим к кубику “Считаем кол-во товаров на странице”, продолжая цикл, пока не обработаем все страницы, либо к оповещению о завершении проекта, если элемент не будет найден.
Парсер Яндекс Маркет с помощью XPath для продвинутых пользователей.
Выше описанный вариант – это не единственный способ написания шаблона, но второй способ, что будет изложен ниже, требует определённых навыков, как например знание HTML разметки и базовое понимание C# кода.
XPath — Это гибкий и мощный язык запросов к элементам xml или (x)html документа и xslt преобразований по DOM, который является стандартом консорциума W3C.
Для тех, кто хочет познакомиться с ним ближе: http://zennolab.com/wiki/ru:xpath
В нашем продвинутом варианте мы заменим все кубики распарса сниппета по регулярным выражениям на поиск значений через XPath. Начнём, пожалуй, с поиска категории по хлебным крошкам.
project.Variables["cat"].Value = string.Empty; // Парсим хлебные крошки var chars = instance.ActiveTab.FindElementsByXPath("//*[@id='n-breadcrumbs']/li/a"); string sep = "-"; int count = chars.Count; int i = 1; // Перебираем ХК и парсим категории\подкатегории foreach(HtmlElement item in chars) { if (i==count) sep = string.Empty; project.Variables["cat"].Value = string.Format(@"{0}{1}{2}", project.Variables["cat"].Value, item.FindChildByXPath(".", 0).InnerText, sep); project.SendInfoToLog(i.ToString()); i++; } // Удаляем лишние пробелы и отступы project.Variables["cat"].Value = project.Variables["cat"].Value.Trim();
Где мы забираем все элементы <a> принадлежащие идентификатору n-breadcrumbs в коллекцию.
Далее в цикле получаем каждый элемент и записываем его в переменную «cat«.
Переходим к парсингу характеристик. В данной конструкцию мы избавляемся складирования сниппетов карточек товара в список и производим парсинг в момент обращения к элементу.
// Инициализируем счётчик int i = Convert.ToInt32(project.Variables["Counter0"].Value); // ID товара string itemID = instance.ActiveTab.FindElementByXPath(".//*[contains(@data-id, 'model-')]", i).GetAttribute("data-id").Replace("model-", ""); // Наименование товара var name = instance.ActiveTab.FindElementByXPath(".//*[contains(@data-id, 'model-"+itemID+"')]//div[contains(@class, '_title')]/a[contains(@class, 'link')]",0); project.Variables["name"].Value = name.GetAttribute("innertext"); // Цена var price = instance.ActiveTab.FindElementByXPath(".//*[contains(@data-id, 'model-"+itemID+"')]//div[contains(@class, 'main-price')]/a/*[contains(@class, 'price')]",0); project.Variables["price"].Value = Regex.Match(price.GetAttribute("innertext"), @"[\d\s]+").Value.Replace(" ", ""); // Убираем в цене лишнее. Оставляем только цифры. // Характеристики project.Variables["char"].Value = string.Empty; var chars = instance.ActiveTab.FindElementsByXPath(".//*[contains(@data-id, 'model-"+itemID+"')]/div//ul/li"); // Перебериаем коллекцию элементов foreach(HtmlElement item in chars) { project.Variables["char"].Value = string.Format(@"{0}{2}{1}", project.Variables["char"].Value, item.FindChildByXPath(".", 0).InnerText, System.Environment.NewLine); } // Удаляем лишние пробелы и отступы project.Variables["char"].Value = project.Variables["char"].Value.Trim(); // Ссылка на карточку товара в Я.М. var url = instance.ActiveTab.FindElementByXPath(".//*[contains(@data-id, 'model-"+itemID+"')]//div[contains(@class, '_title')]/a[contains(@class, 'link')]",0); project.Variables["yam_link"].Value = url.GetAttribute("href"); // Фотография var photo = instance.ActiveTab.FindElementByXPath(".//*[contains(@data-id, 'model-')]//div/a[contains(@class, '_image')]/img",0); project.Variables["img"].Value = photo.GetAttribute("src");
Сначала мы получаем кол-во товаров на странице, а далее в цикле прогоняем наш код, где первым делом мы получаем ID товара и подставляем его в каждый запрос, для более точного нахождения элементов. По завершению работы кубика, все данные будут разложены по переменным.
Данная часть написана с целью демонстрации возможностей ZennoPoster для общего понимания, поэтому сложные С# конструкции при написании шаблонов не были использованы.
Если Вы хотите подробнее узнать о базовых C# приемах или XPath — оставьте свой комментарий в обсуждении к данной теме.
Итог
Как Вы видите, с помощью ZennoPoster можно написать шаблон любой сложности при использовании инструментов, как из стандартного набора, так и при применении собственного кода. И необязательно быть программистом.
Шаблоны для использования
Быстрый старт: https://yadi.sk/d/35O_M86G3PTBfv
XPath: https://yadi.sk/d/N3mttLWi3PTBgF