Полный цикл в digital

Встроеная в PHP библиотека XPath

Библиотека XPath это язык запросов для обращения к объектам дерева DOM, структыры xml и html документа.

Запросы можно формировать исходя из разных критериев элементов:

  1. По классам
  2. По id
  3. По именам тегов
  4. По атрибутам

Например можно выбрать все ссылки по тегу <a ..> на странице, получив объект содержащий элементы и дальше продолжить работу по средствам PHP.

Синтаксис XPath

Запись выражений XPath зависит от того какой элемент нужно найти, базовый синтаксис:

XPATH=//tagname[@attribute='value']

Абсолютный путь поиска начинается с одного слэша / и указывает на полный путь из корневого узла к целевому:

XPATH=/html/body/div[1]/h1

Вырожение означает: выбрать первый div-элемент, под html-элементом, под body-элементом, далее выбрать вложенный h1-элемент.

Относительный путь поиска начинается с двойного слэша // и указывает на путь из любого узла который отвечает критериям, к целевому узлу:

XPATH=//div[@id='main']

Вырожение означает: выбрать любой div-элемент, имеющий id-атрибут со значением main.

Основные понятия парсинга XPath

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

Узлы

Узлами называют разнообразные части страницы или документа:

  • Отдельные элементы и записи
  • Тексты
  • Атрибуты
  • Инструкции для обработки какой-то информации
  • Комментарии
  • Пространства имен
  • Другие сущности на странице.

Предки и потомки

Структура иерархична: от корневого элемента как бы «отпочковываются» другие, зависящие от него. У узлов внутри структуры есть предки и потомки:

  • предки узлы, которые находятся «выше» и от которых зависит конкретный узел. Частный случай — родитель, узел на один «уровень» выше. У каждого элемента только один родитель
  • потомки узлы, которые зависят и наследуются от конкретного узла. У элемента может быть ноль, один или больше потомков

Атомарные узлы

Это узлы, которые не зависят от других, не имеют ни потомков, ни родителей. Они фактически одиночные. Как пример — блок текста на странице, не связанный с какими-то другими узлами.

Получение элементов

Синтаксис XPath описывает правила для создания выражений, которые позволяют точно указать, какие элементы и атрибуты должны быть выбраны из структуры при помощи:

  1. Выбор узла, подробнее
  2. Пути выбора, подробнее
  3. Функций, подробнее
  4. Оси направления выбора, подробнее
  5. Логические операторы, подробнее
  6. Предикаты или коллекции, подробнее

Выбор узла

XPath представляет документ в виде дерева состоящего из:

  • Корневой узел
  • Узел элемента
  • Узел атрибута
  • Текстовый узел

Чтобы выбрать нужный узел, нужно обратиться к нему при помощи языка запросов XPath, указав путь к нужному элементу. Узел выбирается следуя по заданному пути:

* Выбрать любой элемент
[] Найти конкретный элемент, например: li[1]имя_узла выбирает все узлы с указанным именем узла. за место li, может быть любой тэг div, p и т.д.
/ Ищет от корневого узла
// Ищет узлы в документе от текущего узла, который соответствует выбору, независимо от того, где они находятся
. Ищет текущий узел
.. Ищет родителя текущего узла
@ Ищет нужный атрибут, например: p[@value="2024"]

Абсолютные и относительные пути обращения к элементам

К конкретному элементу можно обратиться двумя способами, которые отличаются путями, есть абсолютный путь и относительный путь.

Абсолютный путь начинается со слеша / и указывает на полный путь от корневого узла до целевого узла:

/html/body/div[1]/h1

Вырожение выше означает что нужно выбрать первый элемент div, который находится по пути html > body > div и затем выбрать его дочерний элемент h1.

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

//div[@id='main']

Вырожение выше означает что нужно выбрать любой элемент div, который имеет атрибут id со значением main.

Функции XPath

Язык XPath имеет набор встроенных функций, которые позволяют осуществлять различные операции. Вот некоторые из основных функций:

text() Возвращает текстовое содержимое элемента
count() Возвращает количество элементов, соответствующих указанному выражению
normalize-space() Удаляет лишние пробелы из строки и заменяет последовательности пробелов на одиночные пробелы
starts-with(x,y) Проверяет, начинается ли строка с x-y
contains(x,y) Проверяет, содержит ли строка x-y
last() Возвращает последнюю позицию элемента в выборке
position() Возвращает позицию текущего элемента в выборке
name() Возвращает имя текущего элемента
sum() Суммирует значения элементов выборки
string() Преобразует узел в строку
lower-case() Преобразует текст в нижний регистр
@attribute Выбирает значение указанного атрибута
concat() Объединяет две или более строки
string-length() Возвращает длину строки
substring() Возвращает подстроку из строки, начиная с указанной позиции

Кроме основных функций, XPath также предоставляет более сложные математические функции, а также функции работы с датами и временем. Ниже преведины примеры.

Выбрать любой h1-элемент, имеющий текстовое значение Welcome:

//h1[text()='Welcome']

Выбрать любой элемент p, имеющий значение Hello:

//p[contains(text(),'Hello')]

Выбрать любой рисунок с атрибутом src, который начинается со значения logo:

//img[starts-with(@src,'logo')]

Выбрать любой элемент span, который заканчивается значением _title:

//span[ends-with(@id,'_title')]

Оси XPath

Ось в XPath это специальная концепция, которая используется для указания направления движения при поиске элементов в документе. Оси позволяют выбирать элементы, которые относятся к определенным отношениям с другими элементами в дереве. Есть несколько осей, которые можно использовать при создании выражений:

  1. parent, выбирает родителя текущего узла подробнее
  2. ancestor, выбирает всех предков текущего узла подробнее
  3. ancestor-or-self, выбирает всех предков текущего узла и сам текущий узел подробнее
  4. child, выбирает всех прямых потомков текущего узла подробнее
  5. descendant, выбирает всех потомков текущего узла подробнее
  6. following, выбирает все элементы в документе после закрывающего тега текущего узла подробнее
  7. following-sibling, выбирает все элементы одного уровня после текущего узла подробнее
  8. preceding, выбирает все узлы, которые появляются перед текущим узлом, за исключением предков, узлов атрибутов и пространства имен подробнее
  9. preceding-sibling, выбирает все элементы одного уровня до текущего узла подробнее

Синтаксис оси XPath:

Axes::tagName[@attribute='value']

Parent

Выбирает верхний (родительский) узел (по отношению к текущему узлу):

//div[@id='Y2']/parent::*

Выбирет любой элемент, являющийся прямым родительским для div-элемента с id Y2, это B2 в нашем случае.

Ancestor

Выбирает всех предков текущего узла. Иными словами, первый родительский и все старше, то есть «по направлению к корням дерева»:

//div[@id='Y2']/ancestor::div[@id='B2']

Выбирает div-элемент с id B2, который является предком div-элемента с id Y2.

//div[@id='Y2']/ancestor::div[@id='A']

Выбирает div-элемент с id A, являющийся предком div-элемента с id Y2.

Ancestor-or-self

Вибирает все предковые элементы текущего узла, включая и сам текущий узел:

То есть то же самое что Ancestor, и плюс сам этот узел.

Child

Выбирает непосредственные элементы-потомки (но только первые дочерние) текущего узла:

//div[@id='B2']/child::*

Выбирает все элементы, являющиеся прямыми потомками div-элемента с id B2.

//div[@id='B2']/child::div[@id='Y2']

выбор всех div-элементов с id Y2, прямых потомков div-элемента с id B2.

Descendant

Выбрать всех потомков («во всех коленах») текущего узла:

//div[@id='B2']/descendant::*

Выбирает все элементы, которые являются потомками div-элемента с id B2.

//div[@id='B2']/descendant::div[@id='L1']

Выбирает div-элементы-потомки от div-элемента с id L1.

Following

Выбрать все элементы в документе, идущие после закрывающего тега текущего узла. Другими словами, ниже текущего элемента по дереву (на всех уровнях и слоях), но исключая собственных потомков (смотрим рисунок):

//div[@id='B2']/following::*

Выбирает все div-элементы ниже текущего элемента с id B2.

Following-sibling

Все элементы «братского», то есть того же уровня:

//div[@id='B2']/following-sibling::*

Выбирает все элементы на том же уровне что и div-элемент с id B2, и ниже его в дереве.

Preceding

Preceding аналогичен Following, но в обратную сторону, то есть все элементы выше указанного.

//div[@id='B2']/preceding::*

Выбирает все элементы идущие перед div-элементом с id B2.

Preceding-sibling

Аналогично Preceding, но выбирает только на том же уровне и перед указанным, иными словами любой элемент с тем же родителем и на том же уровне.

Логические операторы

В XPath широко применяются логические операторы для указания нескольких условий поиска и сочетания:

  • AND
  • OR
  • NOT

Например:

//input[@type='text' AND @name='username']

Означает выбрать любой input имеющий одновременно атрибут типа со значением text и атрибут имени со значением username.

//a[@href='https://testengineer.ru' OR @class='link']

Означает выбрать любой якорный элемент, имеющий или href-атрибут со значением https://testengineer.ru, или с атрибутом класса со значением link.

//div[NOT(@id)]

Означает выбрать любой div-элемент, не имеющий id-атрибута.

Предикаты или коллекции

Предикаты или коллекции представляют собой конструкции, которые используются для фильтрации элементов и выбора конкретных элементов с помощью определенных условий. Вот несколько примеров использования предикатов:

//a Выберите все элементы в документе
//a[@class='active'] Выберите все элементы, у которых атрибут class равен "active"
//input[@type='checkbox'] Выберите все элементы input, у которых атрибут type равен "checkbox"
//input[@type='text'] Выберите все элементы input с атрибутом type равным "text"
//p[contains(text(), 'Lorem')] Выберите все элементы, у которых текст содержит слово "Lorem"
//div[count(p) > 3] Выберите все элементы, у которых количество дочерних элементов больше 3
//a[starts-with(@href, 'https://')] Выберите все элементы, у которых атрибут href начинается с "https://"
//input[matches(@value, '^\d+$')] Выберите все элементы input, у которых атрибут value содержит только цифры
//p[@value="01/2008"] Выбирает все элементы p, у которых есть атрибут value со значением "01/2008"
//p[@value] Выбирает все элементы p, у которых есть атрибут value
//p/text() Выделит все текстовые узлы внутри всех элементов p
//div[not(p)] Выберите все элементы, у которых не существует дочернего элемента
/div/p[position()<3] Выбирает первые два элемента p, которые являются прямыми потомками элемента div
//tag[position()=1] Выбирает первый элемент с тегом "tag"
/div/ul/li[1] Выбирает первый элемент li, который является прямым потомком элемента ul в div
//li[a] Выделяет элементы li, в которых есть элемент a
//li[last()] Выделяет последний элемент li в документе
//a | //h2 Выделить все элементы a и h2 с помощью оператора объединения |
//tag[@value > 9] Получить узлы tag, value которых больше 9-ти
//div[note[@value > 9]]/а Получить только имена узлов, value которых больше 9-ти
//div[4]/h2[text() = "Текст"] Выделит четвертый элемент div, h2 которого содержит слово: Текст
/div/note[last()] Выбирает последний элемент note, который является прямым потомком элемента div
/div/note[last()-1] Выбирает предпоследний элемент note, который является прямым потомком элемента div
//*[@id] Выберите все элементы с атрибутом id
//div[contains(@class, 'content')]/p Выберите все элементы, которые являются дочерними элементами с классом "content"
//img[contains(@src, 'logo')] Выберите все элементы , у которых атрибут src содержит слово "logo"
//*[@href[contains(text(), '.pdf')]] Выберите все элементы со значением атрибута href, оканчивающимся на .pdf
//*[@data-toggle='modal'] Выберите все элементы с атрибутом data-toggle и значением "modal"
//tag[@attribute>5] Выбирает все элементы с тегом "tag" и атрибутом "attribute", значение которого больше 5
//tag[@attribute="value"] Выбирает все элементы с тегом "tag" и атрибутом "attribute" со значением "value"

Составление пути XPath

Составить формулу можно при помощи консоли разработчика в браузере:

Парсинг HTML в XPath

Используя XPath получим из DOM дерева моего сайта нужный нам объект, мы будем получать со страницы hmarketing.ru призыв к действию:

<?
// создадим запрос на получение страницы сайта
$data = file_get_contents('https://hmarketing.ru');
// создаем конструктор domDocument
$dom = new domDocument;
// загружаем HTML
$dom->loadHTML($data);
// сохраняем полученный HTML
$dom->saveHTML();
// создаем конструктор DomXPath и передаем параметром HTML
$xpath = new DomXPath($dom);
// ищем нужный блок
$xpathData = $xpath->query("//*[@class='col tekst']");
// получаем элемент, их может быть много и тогда нужно использовать цикл
$xpathItem = $xpathData->item(0);
// выводим результат
echo $xpathItem->textContent;
?>
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг