Pull to refresh

Примеры xpath-запросов к html

Reading time 4 min
Views 525K
Xpath — это язык запросов к элементам xml или xhtml документа. Также как SQL, xpath является декларативным языком запросов. Чтобы получить интересующие данные, необходимо всего лишь создать запрос, описывающий эти данные. Всю «черную» работу за вас выполнит интерпретатор языка xpath.
Очень удобно, не правда ли? Давайте посмотри какие возможности предлагает xpath для доступа к узлам веб-страниц.

Создание запроса к узлам веб-страниц


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

Для лабораторной нам понадобятся:
— веб-страница xhtml;
— браузер Mozilla Firefox с дополнениями;
firebug;
firePath;
(вы можете использовать любой другой браузер с визуальной поддержкой xpath)
— немного времени.

В качестве веб-страницы для проведения эксперимента предлагаю главную страницу сайта консорциума всемирной паутины ('http://w3.org'). Именно эта организация разрабатывает языки xquery(xpath), спецификацию xhtml и многие другие стандарты интернета.

Задача

Получить из xhtml-кода главной страницы w3.org информацию о конференциях консорциума при помощи запросов xpath.
Приступим к написанию xpath запросов.


Первый Xpath запрос

Открываем закладку Firepath в FireBug, выделяем с селектором элемент для анализа, нажимаем: Firepath создал xpath запрос к выбранному элементу.

Если вы выделили заголовок первого события, то запрос будет таким:

.//*[@id='w3c_home_upcoming_events']/ul/li[1]/div[2]/p[1]/a

После удаления лишних индексов запрос станет соответствовать всем элементам типа «заголовок».

.//*[@id='w3c_home_upcoming_events']/ul/li/div/p/a

Firepath подсвечивает элементы, которые соответствуют запросу. Вы можете в реальном времени увидеть, какие узлы документа соответствуют запросу.



Идем дальше. Создаем запросы для поиска мест проведения конференций и их спонсоров либо с помощью селектора, либо модифицировав первый запрос.

Запрос для получения информации о местах проведения конференций:
.//*[@id='w3c_home_upcoming_events']/ul/li/div/p[2]

Так мы получим список спонсоров:
.//*[@id='w3c_home_upcoming_events']/ul/li/div/p[3]

Синтаксис xpath


Давайте вернемся к созданным запросам и разберемся в том, как они устроены.
Рассмотрим подробно первый запрос



В этом запросе я выделил три части для демонстрации возможностей xpath. (Деление на части уловное)

Первая часть
.// — рекурсивный спуск на ноль или более уровней иерархии от текущего контекста. В нашем случае текущий контекст это корень документа

Вторая часть
* — любой элемент,
[@id='w3c_home_upcoming_events'] – предикат, на основе которого осуществляем поиск узла, имеющего атрибут id равным 'w3c_home_upcoming_events'. Идентификаторы элементов XHTML должны быть уникальны. Поэтому запрос «любой элемент с конкретным ID» должен вернуть единственный искомый нами узел.

Мы можем заменить * на точное имя узла div в этом запросе
div[@id='w3c_home_upcoming_events']

Таким образом, мы спускаемся по дереву документа до нужного нам узла div[@id='w3c_home_upcoming_events']. Нас абсолютно не волнует, из каких узлов состоит DOM-дерево и сколько уровней иерархии осталось выше.

Третья часть
/ul/li/div/p/a –xpath-путь до конкретного элемента. Путь состоит из шагов адресации и условия проверки узлов (ul, li и т.д.). Шаги разделяются символом " /"(косая черта).

Коллекции xpath

Не всегда удается получить доступ к интересующему узлу с помощью предиката или шагов адресации. Очень часто на одном уровне иерархии находится насколько узлов одинакового типа и необходимо выбрать «только первые» или «только вторые» узлы. Для таких случаев предусмотрены коллекции.

Коллекции xpath позволяют получить доступ к элементу по его индексу. Индексы соответствуют тому порядку, в котором элементы были представлены в исходном документе. Порядковый номер в коллекциях отсчитывается от единицы.

Исходя из того, что «место проведения» всегда второй параграф после «названия конференции», получаем следующий запрос:
.//*[@id='w3c_home_upcoming_events']/ul/li/div/p[2]
Где p[2] – второй элемент в наборе для каждого узла списка /ul/li/div.

Аналогично список спонсоров мы можем получить запросом:
.//*[@id='w3c_home_upcoming_events']/ul/li/div/p[3]

Некоторые функции хpath

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

last():
Возвращает последний элемент коллекции.
Запрос ul/li/div/p[last()] — возвратит последние параграфы для каждого узла списка «ul».
Функция first() не предусмотрена. Для доступа к первому элементу используйте индекс «1».

text():
Возвращает тестовое содержание элемента.
.//a[text() = 'Archive'] – получаем все ссылки с текстом «Archive».

position() и mod:
position() — возвращает позицию элемента в множестве.
mod — остаток от деления.

Комбинацией данных функций можем получить:
— не четные элементы ul/li[position() mod 2 = 1]
— четные элементы: ul/li[position() mod 2 = 0]

Операции сравнения
  • < — логическое «меньше»
  • > — логическое «больше»
  • <= — логическое «меньше либо равно»
  • >= — логическое «больше либо равно»

ul/li[position() > 2] , ul/li[position() <= 2] — элементы списка начиная с 3го номера и наоборот.

Полный список функций

Самостоятельно


Попробуйте получить:
— четные URL ссылки из левого меню «Standards»;
— заголовки всех новостей, кроме первой с главной страницы w3c.org.

Xpath в PHP5


	$dom = new DomDocument();
	$dom->loadHTML( $HTMLCode );

	$xpath = new DomXPath( $dom );

	$_res = $xpath->query(".//*[@id='w3c_home_upcoming_events']/ul/li/div/p/a");

	foreach( $_res => $obj ) {
                echo 'URL: '.$obj->getAttribute('href');
		echo $obj->nodeValue;
        }


В заключение


На простом примере мы увидели возможности xpath для доступа к узлам веб-страниц.
Xpath является отраслевым стандартом для доступа к элементам xml и xhtml, xslt преобразований.
Вы можете применять его для парсинга любой html-страницы. В случае если исходный html-код содержит значительные ошибки в разметке пропустите его через tidy. Ошибки будут исправлены.

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

Ресурсы


Firepath дополнение Mozzilla Firefox
Краткая аннотация языка в википедии
Xороший справочник по xpath. Не обращайте внимание на то, что он для NET Framework. Xpath во всех средах работает одинаково, за исключением пары специфичных функций
Cпецификация xpath 1.0
Cпецификация xpath 1.0 на русском
XQuery 1.0 and XPath 2.0
Tidy
PHP5 tidy::repairFile
Tags:
Hubs:
+53
Comments 47
Comments Comments 47

Articles