[xParser] 1.3.0 - Регулярные выражения + Кейс


Обработка регулярным выражением полученных данных доступна уже давно, благодаря такой сногсшибательной функциональности Fenom. А с версии 1.3.0 регулярки были внедрены:
а) в конфигурацию задания при указании записи селектора,
б) в поля источника.

Пользователю это даёт более гибкую выборку записей из источника. Под катом пример того, как я извращался при помощи регулярок в xParser.


Кейс


Дано

Возникла потребность распарсить сайт, имеющий странную структуру записей. На CSS или XPath синтаксисе к ним было не подобраться. Пример странной структуры:
<div class=content>
<p> 
<h2>Какой-то заголовок</h2>
Текст с описанием раздела
<p>
18.01.10 <a href="http://domain.zone/link1.html">Запись 1</a>
< br>Описание записи 1
<p>
24.12.09 <a href="http://domain.zone/link2.html">Запись 2</a>< br>
Описание записи 2
<p>
23.12.09 <a href="http://domain.zone/link3.html">Запись 3</a>
< br>Описание записи 3
<p>
22.12.09 <a href="http://domain.zone/link4.html">Запись 4</a>< br>
Описание записи 4
...
</div>
Я умышленно поставил пробел перед br, т.к. modx.pro съедал их.

Что мы имеем:
  1. Запись не содержится в отдельном контейнере. Отсюда сложность получить ее. Решаемо за счет регулярки!
  2. Теги p в каждой записи открыты, но не закрыты. Решается внутренними средствами xParser без вашего участия!
  3. Тег br может стоять, как сразу после ссылки, так и на следующей строке под ней. Решаемо за счет регулярки!
Версия xParser ниже 1.3.0 не решала такое, честно скажем…

Выборка записи

Как обычно, мы создаем задание. Только теперь при указании селектора записи в конфигурации задания, мы можем выбрать синтаксис, среди которых: CSS, XPath, RegExp. Нам нужны регулярные выражения!


Вот такую регулярку я составил для выборки записей из странной структуры:
/<p>\s?([0-9]{2}\.[0-9]{2}\.[0-9]{2}) <a href="([^"]+)">(.+)<\/a>\s?< br>\s?(.*)\s?<\/p>/ui
Я умышленно поставил пробел перед br, т.к. modx.pro съедал их.

Таким образом мы получим каждую запись на странице. Всего их было около 100 шт.

Поля источника

После чего нам надо распарсить поля источника. Это я тоже реализовал на регулярных выражениях:


Ссылка:
Синтаксис: RegExp
Ключ: link
Селектор:
/<a.*href="([^"]+)/ui

Дата:
Синтаксис: RegExp
Ключ: date
Селектор:
/<p>\s?([0-9]{2}\.[0-9]{2}\.[0-9]{2})/ui

Описание:
Синтаксис: RegExp
Ключ: description
Селектор:
/<p>\s?[0-9]{2}\.[0-9]{2}\.[0-9]{2} <a href="[^"]+">.+<\/a>\s?< br>\s?(.*)\s?<\/p>/ui
Я умышленно поставил пробел перед br, т.к. modx.pro съедал их.

Итого

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

А ещё в прошлых версиях были добавлены классные функции:

  1. Указание кодировки страницы-источника,
  2. Переменная $_pls в параметры @INLINE чанка в системном поле, которая содержит массив значений, для получения нестандартных полей, например с двоеточием в ключе,
  3. Можно указывать скачивание медиа для конкретных полей, а не для всего задания в целом,
  4. Переписан метод xmlToArray на основе DOMDocument, что позволило парсить атрибуты у XML тегов, у которых указан контент. Контент теперь хранится в ключе массива @content, если у тега присутствуют атрибуты.
По последнему пункту: в связи с этим у некоторых пользователей могут слететь поля guid, которые указываются и с атрибутом, и с контентом внутри, одновременно. Для этого достаточно переписать получение этого поля на:
@INLINE {$guid['@content']}
Павел Гвоздь
17 февраля 2017, 05:13
modx.pro
2
4 421
+10
Поблагодарить автора Отправить деньги

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

Илья Уткин
17 февраля 2017, 09:37
0
Оффтоп…

У меня, вроде, br не съедаются:
<br>
    Павел Гвоздь
    17 февраля 2017, 10:46
    +2
    Что у тебя за br такой?))

    Вот:
    Вот тут будет тег:
    А тут текст после него...
      Илья Уткин
      17 февраля 2017, 10:48
      +3
        Василий Столейков
        17 февраля 2017, 15:21
        1
        0
        Да, мне тоже интересно, как ты его заставил отобразиться?
        Даже спецсимволы типа & lt; br & gt; съедаются…
          Василий Наумкин
          17 февраля 2017, 17:34
          +4
          Двойное кодирование не внутри тегов code и pre:
          &amp;lt;br>
          <br>
      Владимир
      17 февраля 2017, 09:58
      +1
      Как же это замечательно!
      PS Обновляться же безбоязненно можно? Не увидел что это версия до которой я и так успешно уже обновился.
      Спасибо!
        Nikita
        15 марта 2017, 18:39
        0
        Павел, добрый день!

        Вот тут у вас спрашивали, можно ли результаты парсинга сохрнять в TV.

        А можно ли результаты парсинга просто сохранять в бэк-энде, скажем как список в Tickets, но без создания собственно страниц/ресурсов сайта?
          Павел Гвоздь
          16 марта 2017, 07:44
          0
          Что за список в Tickets? В целом можно будет делать что угодно через плагин, просто он не нужен пользователям компонента, поэтому его ещё нет. По крайней мере заявки на его внедрение ещё не поступало.
            Nikita
            17 марта 2017, 17:30
            0
            Я имел ввиду списком внутри, в бэк-энде MODX, без создания страниц сайта.
          Алексей
          09 октября 2017, 17:25
          0
          Не понял как указать поле «link_attributes». В выпадающем списке не видно, да и пагинация почему-то не работает. (вторая страничка такая же как первая)
            Павел Гвоздь
            09 октября 2017, 18:46
            0
            Напишите в ТП на modstore, пжл.
              Алексей
              12 октября 2017, 13:58
              0
              Большое спасибо за обновление! Единственно не понял, как бороться с
              max_execution_time
              лимитом при парсинге даже около ~50 страниц это занимает больше обычных 60 секунд.
              link_attributes — нашел в файлике
              /core/components/xparser/processors/mgr/combo/getfields.class.php
              замечательную функцию:
              excludeResourceFields
              из которой закомментил
              // 'link_attributes',
              и все заработало!

              PS: также в новых версиях хотелось бы видеть функционал вырезки ненужного контента при парсинге.
            Impulse
            20 ноября 2017, 12:10
            0
            Всем привет! Настроил этот парсер, вроде нормально все, но при запуске пара секунд и всплывает окно
            Результаты парсинга:
            Заданий: 1
            Создано: 0
            Обновлено: 0
            Ошибок: 0
            Неудачный запусков: 1

            Из за чего не удачный запуск то?
            Columb
            23 июля 2021, 02:47
            0
            Настроил парсинг новостных лент, записи создаются в Ticket. Проверяются записи (уникальное поле) по URL донора, который записывается в системное поле introtext.

            Если настроить парсер так, чтобы созданные записи автоматически публиковались, то все работает как и указано в основном задании (записи добавляются, обновляются, до-записываются).

            Но если запись автоматически не публикуется (публикуется вручную после проверки и редактирования), то при повторном запуске парсера создается ее дубль. Создается впечатление, что при «ручной» смене статуса записи на опубликованную, парсер уже не проверяет уникальное поле (URL записаный в системном поле introtext).

            Пробовал дополнительном задании указать по-умолчанию resource|published = 0, а затем вручную публиковать — проблема остается.

            P/S К сожалению, техническая поддержка закончилась 25.03.21.
              Павел Гвоздь
              23 июля 2021, 08:11
              0
              Возможно, у вас properties у ресурса затирается каким-то образом.
                Columb
                23 июля 2021, 11:45
                0
                Добрый день, Павел! Спасибо, что откликнулись! Вы совершенно правы — Tickets после публикации отредактированного ресурса перезаписывает properties, удаляя запись парсера

                1. properties tickets при создании (не опубликован)
                {"tickets":{"disable_jevix":true,"process_tags":false,"was_published":false},"xpUnique":"a128300e31a340c3bb649bb25f3b7d1d9fc0b2c4","xpTask":"203","ms2gallery":{"media_source":"3"}}
                2. properties tickets после редактирования (не опубликован)
                {"tickets":{"disable_jevix":true,"process_tags":false,"was_published":false},"xpUnique":"a128300e31a340c3bb649bb25f3b7d1d9fc0b2c4","xpTask":"203","ms2gallery":{"media_source":"3"}}
                3. properties tickets после редактирования (опубликован)
                {"tickets":{"disable_jevix":true,"process_tags":false},"ms2gallery":{"media_source":"3"}}

                «Виновник» найден, но как решить данную проблему? Очень бы хотелось «подружить» между собой Tickets и xParser
                  Павел Гвоздь
                  25 июля 2021, 05:10
                  0
                  Учитывая, что у вас помимо Tickets на сайте ещё что-то есть, стоило бы удостовериться точно, что в нём дело. А по поводу «как решить», если в Тикетс дело, то доработать Тикетс в том месте, где он затирает неугодные ему properties. Но мне больше интересно, почему свойство «ms2gallery» остаётся на месте…
                    Columb
                    01 августа 2021, 13:29
                    0
                    Свойство «ms2gallery» остаётся на месте, вероятно, из-за того, что в системных настройках Тикетс ms2gallery указан в качестве источника медиа для тикетов (tickets.source_default).

                    К сожалению, мои знания не позволяют «доработать Тикетс в том месте, где он затирает неугодные ему properties». НО я нашел способ, как можно обойти данную проблему —
                    1. Созданный помощью xParser Тикет редактируем и сохраняем ТОЛЬКО в неопубликованном состоянии.
                    2. Публикуем (снимаем с публикации) Тикет ТОЛЬКО в разделе с тикетами (кнопкой).
                    3. Если необходимо отредактировать уже опубликованный Тикет — в разделе с тикетами (кнопкой) снимаем Тикет с публикации + редактируем и сохраняем неопубликованный Тикет + переходим в раздел с тикетами и кнопкой его публикуем.

                    Вот такие «танцы с бубном» для тех, кто не умеет писать код)
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              19