[xParser] 1.2.0 - Парсер HTML контента + совмещение заданий

Парсер HTML контента востребованная штука, поэтому естественным шагом было его внедрение в xParser.

А с версии 1.2.0 компонент позволяет совмещать задания. Например, вам нужно распарсить RSS ленту и каждую запись выпилить с сайта полностью. Для этого:
  1. Создаётся пара заданий (первое — RSS, второе — HTML),
  2. Настраивается,
  3. Запускается.

Подробнее об HTML парсере


Так как в RSS ленте у нас по-умолчанию присутствует некий массив полей, которые можно распределить по полям MODX, то в HTML дела обстоят несколько сложнее: нам нужно самим создать эти поля, указав селектор до каждого из них.
Давайте на примере MODX.pro рассмотрим, как это делается:

Добавляем задания


Покажу пример, в котором происходит запуск одного задания из другого. Для этого нам надо будет создать 2 задания:

Добавляем primary задание

Primary заданием я называю список новостей, которые нам необходимо распарсить.
Жмём Добавить => Добавить HTML задание.
На вкладке Основное заполняем примерно так:


Переключаемся на вкладку Конфигурация, где указываем:
  • Селектор записи (пока только CSS-подобный синтаксис),
  • С какой по счёту записи стартовать,
  • Сколько записей парсить,
  • Шаблон для создаваемых ресурсов,
  • Контекст,
  • Родительский контейнер в пределах выбранного контекста,
  • Скачивать ли медиа-контент.


Жмём Сохранить — задание добавлено!

Добавляем secondary задание

Secondary заданием я называю задание с настройкой парсинга для полной статьи. Его мы будем указывать в качестве наследника для первого задания.
Жмём Добавить => Добавить HTML задание.
На вкладке Основное заполняем примерно так:

Важно указать:
  • URL — ссылку на какую-нибудь статью с modx.pro (потребуется для настройки полей источника),
  • Поставить галочку Является подзадачей.
Переключаемся на вкладку Конфигурация, где указываем:
  • Селектор записи: #content

Настройка источника


Так как задания у нас типа HTML, то придётся вручную создавать данные источника, которые будем парсить. Потребуется сделать это также, для двух заданий. Жмём на задании правой мышью => Источник.

Настройка источника для primary задания

Здесь достаточно добавить всего 1 поле — ссылку на полную версию статьи. Однако, я предлагаю добавить ещё и поле content, в котором будет храниться вступительная часть статьи. В этом вступительном тексте также указывается основное изображение статьи, вот его то мы и будем выдирать с помощью регулярки. Происходить это будет на шаге Настройки полей primary задания. Жмём Добавить.

Здесь у нас есть возможность указать CSS-подобный или XPath синтаксис. Для разных полей часто требуется и тот, и другой.

Внимание: XPath синтаксис имеет неприятный баг: не понимает названия тегов, поэтому приходится указывать тег, как *

Заполняем примерно так:



Там же можно проверить, насколько корректно парсер получает указанные нами значения. Для этого требуется нажать на кнопку с глазом:


Настройка источника для secondary задания

Тут я добавил также 2 поля: pagetitle и content.

Pagetitle:
Синтаксис: CSS
Ключ: pagetitle
Селектор: h3.page-title

Content:
Синтаксис: CSS
Ключ: content
Селектор: .page-content

Настройка полей задания


По большому счёту тут всё очень похоже на настройку RSS задания, т.к. у нас уже есть данные из источника, которые можно просмотреть в виде распечатанного массива, кликнув по кнопке Массив сырых значений. Сейчас нам надо, опираясь на эти ключи и значения источника, правильно добавить поля для парсинга. Жмём на задании правой мышью => Поля.

Описывать подробно возможности пакета на данном этапе не буду, кому интересно, может почитать это в описании настройки RSS заданий.

Настройки полей primary задания

Здесь тоже достаточно одного поля — link, но мы добавим и поле с основным изображением поста. Выдернем это изображение из вступительной части статьи с помощью Fenom и регулярного выражения. Жмём Добавить.

Link:
Системное поле: пусто
Поле в источнике: link
Значение по-умолчанию: пусто

Introtext: (запишем сюда изображение)
Системное поле: Resource.introtext
Поле в источнике:
@INLINE {$content | preg_get : '!https?://.+\.(?:jpe?g|png|gif)!Ui'}
Значение по-умолчанию: пусто

Теперь в таблице добавленных полей задания у поля link кликаем на звезду (поле должно стать оранжевым) и на соседнюю кнопку. Откроется окошко добавления связанного задания. Там есть сноска, продублирую:
1) Убедитесь, что выбранное поле действительно является ссылкой.
2) При парсинге эта ссылка будет передана в задание, которое вы выбрали ниже.
3) Из выбранного задания будут получены все поля для создания объекта.
4) Полученные поля перезапишут аналогичные поля из текущего задания.

В поле Принимающее задание выбираем MODX.pro (Secondary). Таким образом, текущее задание (Primary) передаст УРЛ из поля link в задание (Secondary). Жмём Сохранить. Поле link в таблице подсветится синим цветом:


Настройки полей secondary задания

Тут добавляем 3 поля: pagetitle, content и published.

Pagetitle:
Системное поле: Resource.pagetitle
Поле в источнике:
@INLINE {$pagetitle | preg_replace : '! \<sup class.*!ui'}
Значение по-умолчанию: пусто

Content:
Системное поле: Resource.content
Поле в источнике: content
Значение по-умолчанию: пусто

Published:
Системное поле: Resource.published
Поле в источнике: пусто
Значение по-умолчанию: 1

Итого


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

P.S.: Следующим шагом будет внедрение возможности путешествия по страницам.

P.P.S.: Компонент успешно вырос из логотипа, надеюсь modstore заметит это. :)
Павел Гвоздь
15 января 2017, 01:18
8
3 985
+17
Поблагодарить автора Отправить деньги

Комментарии: 32

Владимир
15 января 2017, 10:06
+1
Круто! Спасибо, Павел!
Дмитрий Иванов
15 января 2017, 14:18
+1
А через прокси умеет ходить на сайты?
    Павел Гвоздь
    15 января 2017, 17:55
    +1
    Пока нет, но и это в планах: авторизация на сайте перед парсингом, вход через прокси.
      Антон
      15 января 2017, 19:50
      0
      Можно стену вконтакта парсить?
        Павел Гвоздь
        16 января 2017, 22:13
        +2
        Скорее да, чем нет. :) Не проверял подобное. Если интересно — могу позже проверить и отписаться.
Yar
Yar
16 января 2017, 00:53
0
Мало создать компонент, нужно еще научить им пользоваться. У Павла отлично получается и первое и второе.
Но, кроме этого, хорошей мотивацией к покупке дополнения (для меня точно) станет публикация кейсов (практической выгоды — трафика на сайт) от использования ХParser.
    Владимир
    16 января 2017, 10:00
    +2
    Извини, научить заработать при помощи какого то инструмента — это уже чья то отдельная работа, разве нет? А ты предлагаешь что бы тебе в стоимость ПО добавили не только документацию, а «публикация кейсов (практической выгоды — трафика на сайт) » и мотивировали тебя тем самым купить. Честно, прочел, аж обалдел. Это инструмент, у него много способов применения, и, наверно логично что бы пользователи делились опытом и кейсами.

      Yar
      Yar
      16 января 2017, 14:01
      -4
      Я лишь высказал свое мнение, адресованное не только автору дополнения, но и всем кто его прочитает. С него (мнения) можно «обалдеть», а можно принять к сведению…
    Павел Гвоздь
    16 января 2017, 22:17
    +3
    Как уже правильно заметил Владимир: я продаю лишь инструмент, а что с ним делать — ваша забота. Парсер можно использовать для совершенно разных целей.
Евгений Шеронов
03 февраля 2017, 09:08
0
Можно ли с помощью этого компонента реализовать подобное?

В ресурсе в ТВ или в любых других полях, хранятся ссылки, к примеру 3.
Запуск по крону раз в день парсинга этих ссылок для каждого ресурса.
Промежуточные результаты парсинга нужных полей (для простоты будет по 1 полю для источника, то есть ещё 3 тв или других полей) записываются в эти 3 поля.
И по окончанию парсинга ссылок каждого ресурса запускается сниппет, который уже будет обрабатывать промежуточные результаты.

Не нужно, чтобы компонент все эти действия делал, а нужна возможность управлять им в этой цепочке действий.
    Павел Гвоздь
    03 февраля 2017, 10:43
    +1
    Скоро будут добавлены события на плагины, там будет возможность не только запустить свой код на определенном шаге парсинга, но и заменить окончательное действие парсера (добавление ресурса в базу) на свое, либо остановить парсинг текущей записи вовсе, отдав статус ошибки.
Игорь
16 февраля 2017, 02:54
0
Для формирования XPath синтаксиса воспользовался XPath Helper для Google Chrome. В результате получил разный синтаксис. Например, вместо указанного в статье
.//*[@class="title"]/*
получил
//*[@id="tickets-rows"]/div/div[1]/h3
Каким образом можно получить верный XPath синтаксис для настройки xParser?
Александр
22 января 2018, 13:08
0
Подскажите, этот компонент подойдет для парсинга XML такого вида?
www.tss.ru/bitrix/catalog_export/yandex_800463.xml
    Павел Гвоздь
    22 января 2018, 13:36
    0
    Думаю, да!
    Базовый тег ленты: offers
    Базовый тег записи: offer
    Вот что получаем в качестве данных записи:
    Array
    (
        [url] => http://www.tss.ru/catalog/elektrostantsii/dizelnye_elektrostantsii/tss_deutz/dizelnyy_generator_tss_ad_25s_t400_1rm6_006533/
        [price] => 574770
        [currencyId] => RUB
        [categoryId] => 156198
        [picture] => Array
            (
                [0] => http://www.tss.ru/upload/iblock/963/96345baa8c9803081a7eda6b50d2ff29.jpeg
                [1] => http://www.tss.ru/upload/iblock/bbe/bbe36c018fe04464b4cdc4c1abc3a5cd.jpeg
                [2] => http://www.tss.ru/upload/iblock/103/10383a412da94c070450fb80dda8ef38.jpeg
                [3] => http://www.tss.ru/upload/iblock/27a/27a143c97fe28b09a6f96d22b11c5b1d.jpeg
            )
    
        [name] => Дизельный генератор ТСС АД-25С-Т400-1РМ6
        [description] => Дизель-генератор TSS Deutz номинальной мощностью 25 кВт (31,2 кВА) предназначен для обеспечения электропитания объектов электроснабжения как в качестве основного, так и в ка...
        [param] => Array
            (
                [0] => Array
                    (
                        [@content] => <p><b>Дизель-генератор TSS Deutz ...
                        [name] => Полное описание
                    )
    
                [1] => Array
                    (
                        [@content] => 24
                        [name] => Гарантия, срок (мес)
                    )
    
                [2] => Array
                    (
                        [@content] => 400/230
                        [name] => Напряжение (В)
                    )
    
                [3] => Array
                    (
                        [@content] => 006533
                        [name] => Артикул
                    )
    
            )
    
        [id] => 2181526
        [available] => true
    )
    Я заведомо сократил список параметров, т.к. получалась простыня. Также убрал весь код из параметра «Полное описание»…

    Дальше эти данные можно обработать при помощи Fenom и вставить в нужные поля в MODX.
      Александр
      23 января 2018, 18:29
      0
      Спасибо, сейчас проверю на тестовом. В целом этого должно хватить для дальнейшей работы. Осталось только разобраться, как создавать категории и подкатегории и можно покупать компонент.
        Павел Гвоздь
        23 января 2018, 22:04
        0
        В вашем XML есть, вроде, список категорий. Их парсинг также можно выставить отдельным заданием.
Никита
23 января 2018, 19:05
0
Добрый день! Скажем, я создаю агрегатор для других ресурсов, мне нужно автоматически собирать актуальные цены. Я смогу по селектору html элементов собирать нужные цены с других ресурсов и автоматически публиковать у себя на страницах?
    Павел Гвоздь
    23 января 2018, 22:04
    +1
    Что за «другие ресурсы»?..
      Никита
      24 января 2018, 00:53
      0
      Другие сайты.
      Например, у меня агрегатор кредитов от различных банков, нужно каждый день парсить актуальные данные с html страниц банков, ориентируясь по селекторам, собирать проценты, условия, и выводить в таблице сравнения.

      Или агрегатор квартир в Москве, каждый день парсить сайты застройщиков, получая из нужного селектора html актуальные цены, количество оставшихся страниц и так далее
        Павел Гвоздь
        24 января 2018, 01:42
        +1
        Теоретически можно, на практике надо ближе знакомиться с задачей.
          Никита
          24 января 2018, 14:25
          0
          Если на практике, то можно спарсить с другого сайта определённую строку, ориентируясь по селектору, применить к ней регулярные выражения, сохранить в какой-нибудь таблице бэкенда и от туда уже брать данные на фронтента?
            Павел Гвоздь
            24 января 2018, 19:15
            +1
            Увы, сейчас пока нельзя работать с кастомными объектами.
              Никита
              24 января 2018, 19:24
              0
              Это планируется в будущем реализовать?
MODXyou
09 февраля 2018, 12:15
0
Добрый день! Подскажите Ваше дополнение modstore.pro/packages/import-and-export/xparser может ли парсить YML файлы? Если да то каким это будет выглядить образом? Спасибо!
    Павел Гвоздь
    12 февраля 2018, 10:58
    0
    Увы, YML парсить не умеет. Можно внедрить, но смысла пока не вижу в этом.
Ольга
26 февраля 2018, 14:12
+1
Павел, можно ли автоматически создавать и удалять товары minishop2? сохранять фото, характеристики? заказчик хочет периодически синхронизироваться с сайтами поставщиков, удаляя не найденные товары и добавляя новые.
    Павел Гвоздь
    26 февраля 2018, 21:31
    0
    Удалять — нет. Остальное — да.
      Ольга
      28 февраля 2018, 15:53
      0
      А обновлять на существующие товары цены?
        Павел Гвоздь
        28 февраля 2018, 17:44
        0
        Обновлять товары можно, если они созданы парсером. Дело в том, что парсеру для обновления ресурса/товара нужно внедрить уникальный ID.
Sergey
13 марта 2019, 19:29
0
Есть задача парсить каталог товаров с опциями для minishop2
Скажите, какие условия должны быть у сайта с которого парсим?
    Павел Гвоздь
    13 марта 2019, 21:45
    0
    Нужно, чтобы товары были доступны в коде сайта. Вообще, можете потестировать на modhost.pro.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.