XPath в сравнении с селекторами CSS
Назначение выражений XPath и селекторов CSS
Да, мы только что сказали, что предполагаем, что вы уже имеете представление о том, что они делают, но если мы ошиблись в предположениях, то позвольте нам просто побаловать наших читателей кратким обзором.
Назначение выражений XPath и селекторов CSS заключается в предоставлении выразительного языка, позволяющего находить и выбирать элементы в XML- и HTML-документах. Предположим, что у нас есть следующая веб-страница:
<!doctype html>
<html>
<head>
<title>What is the DOM ?</title>
<meta charset="utf-8" />
</head><body>
<h1>DOM 101</h1>
<p>Webscraping is awsome !</p>
<p>Here is my <a href="https://www.scrapingbee.com/blog/">blog</a></p>
</body>
</html>
А теперь мы хотим извлечь URL нашего анкорного тега, указывающего на ScrapingBee. Как мы можем это сделать?
Конечно, можно вручную разобрать всю HTML-строку (например, токенизировать все и проверить на наличие <a) или - если уже более изощренно - использовать регулярные выражения (например, <a\s+href="([^"]+)), но все это - ручной разбор строки, а это редко бывает интересно.
Именно в этом случае на помощь приходят селекторы XPath и CSS. В нашем примере мы можем получить доступ к тегу якоря с помощью следующего синтаксиса в XPath и CSS соответственно.

История селекторов XPath и CSS
Обе технологии появились довольно давно. Они появились примерно в середине-конце 90-х годов прошлого века, и хотя во многих отношениях они очень и очень похожи - их можно считать двоюродными братьями или даже сестрами, - тем не менее, они имеют разное происхождение и разные первоначальные цели.
XPath: Хотя границы между HTML и XML, по общему признанию, всегда были несколько подвижны, HTML всегда был ориентирован на работу в Интернете, в то время как XML всегда был в первую очередь форматом структурированных документов для данных. Именно здесь и появился XPath. XPath был представлен одновременно с XML и имел целью предоставить язык запросов для XML. Он должен позволять быстро и легко получать доступ к информации внутри данного XML-документа, независимо от того, где он находится - в Интернете или в известной базе данных XML.
CSS: Селекторы CSS не были самостоятельным изобретением, а являются частью общей экосистемы CSS. Однако они являются ее неотъемлемой частью, поскольку обеспечивают основную функциональность - поиск того самого элемента (элементов), к которому будет применен блок объявления правила. В этом контексте селекторы CSS всегда были очень сильно (и почти исключительно) ориентированы на веб и веб-страницы.
В то время как XPath оставался (в основном) верен своему первоначальному назначению - созданию языка запросов к структурам XML-документов (к которым относится и HTML), CSS-селекторы со временем вышли за рамки использования только для стилизации и превратились в самостоятельную технологию запросов к веб-документам.
Как мы уже говорили, обе технологии практически идентичны по своим возможностям и имеют общие черты синтаксиса, однако между ними все же существует достаточно много различий, а также преимуществ и ограничений. Именно это мы и рассмотрим далее.
Преимущества и ограничения XPath
Вообще говоря, XPath является более сложным языком. Если вы можете реализовать запрос с помощью селекторов CSS, вы можете сделать то же самое с помощью XPath. Обратное не всегда возможно.
Например, одним из основных преимуществ XPath является его способность поддерживать двунаправленное обходное движение по дереву. Вы можете найти определенный элемент, а затем, используя ось parent, выбрать его родителя или даже предков. Несмотря на то, что селекторы CSS предлагают полуэквивалент в виде псевдокласса :has, это все равно далеко не XPath, поскольку он охватывает лишь ограниченный набор случаев использования, а его поддержка браузерами все еще весьма сомнительна.
Несмотря на то, что производительность в данном контексте обычно не играет большой роли, иногда производительность XPath может быть выше, чем у селекторов CSS. Это связано с тем, что некоторые CSS-селекторы используют XPath для внутренних целей и сначала преобразуют свои селекторы в XPath-выражения.
Одним из недостатков XPath, безусловно, является его более многословный синтаксис. Такие вещи, как классы HTML, должны быть указаны в виде атрибутов, в то время как CSS поддерживает их как, скажем так, первоклассных граждан в своем синтаксисе.
Плюсы и минусы
+ Поддержка двунаправленного перемещения по дереву (обращение к родительскому или предковому элементу)
+ Поддержка выбора не только элементов документа (т.е. атрибутов и содержимого)
+ Встроенные функции для различных вариантов использования (например, text(), count())
+ Поддержка абсолютных и относительных путей поиска
- Более подробный синтаксис
Преимущества и ограничения CSS-селекторов
Одним из основных преимуществ CSS-селекторов является их "естественность" в контексте Web. Если вы знакомы с веб-разработкой, то вы сразу же поймете, что такое CSS-селекторы, поскольку уже давно используете их при оформлении страниц.
В отличие от выражений XPath, селекторы CSS прекрасно понимают, что такое идентификаторы и классы HTML, и предоставляют элементы с собственным синтаксисом (например, #id & .class). По этой причине CSS-селектор можно считать чуть менее многословным (a#id против //a[@id="id"]).
К ограничениям можно отнести тот факт, что CSS-селекторы работают только на уровне элементов. То есть, если необходимо извлечь ссылку из тега <a>, то с помощью CSS-селекторов можно найти только все соответствующие теги, а к атрибуту href придется обращаться на втором этапе, вне контекста CSS-селектора (например, tag.getAttribute("href")). XPath выражения позволяют и здесь получить прямой доступ к атрибутам (например, //a/@href).
Еще одним существенным ограничением является нисходящий подход, который означает, что дерево DOM можно обходить только в одном направлении и нельзя выбирать родительские элементы (например, `... для файловых систем). Хотя это, возможно, не самый распространенный вариант использования, все же бывают случаи, когда это может пригодиться, и при использовании селекторов CSS приходится искать какой-то обходной путь.
Плюсы и минусы
+ Веб-разработчики знакомы с синтаксисом
+ Идентификаторы и классы HTML являются гражданами первого класса (синтаксис хэша и точки)
- Можно выбирать только элементы (без атрибутов или содержимого)
- Не поддерживает восходящий обход (доступ к родительскому элементу или элементу-предку)
- Сложнее указать абсолютный путь поиска
Извлечение данных с помощью CSS-селекторов и ScrapingBee
{"title": "h1","subtitle": "#subtitle"}

Использование селекторов XPath и CSS в браузере
Хотя существует множество инструментов (например, https://try.jsoup.org), которые помогут вам в управлении выражениями XPath и CSS-селекторами, на самом деле один такой инструмент уже установлен на вашей машине, той, которой вы пользуетесь в данный момент: это ваш браузер.
Инструменты разработчика в браузерах Chrome и Firefox не только облегчают оценку и отладку выражений XPath и селекторов, но и помогают найти нужные выражения. Просто щелкните правой кнопкой мыши на нужном элементе и выберите пункт Inspect. Теперь у вас должно быть открыто дерево DOM страницы, и вы можете получить доступ к отдельным элементам.
Поиск правильного селектора XPath и CSS с помощью браузера
В нашем примере на сайте example.com мы щелкнули правой кнопкой мыши на ссылке "Подробнее" и теперь имеем контекстное меню со всеми необходимыми опциями. Давайте выберем пункт "Копировать". Здесь выделенные записи будут представлять для нас особый интерес.
Если мы выберем пункт Копировать селектор, то браузер сохранит в буфере обмена путь CSS-селектора элемента, например, следующее выражение:
body > div > p:nth-child(3) > a
Если же мы выберем Copy XPath или Copy full XPath, то браузер сделает то же самое со следующим выражением XPath:
/html/body/div/p[2]/a
В любом случае в буфере обмена должно появиться выражение для данного элемента. Правда, следует иметь в виду, что даже Google и Mozilla, вероятно, не могут творить чудеса (пока), и эти выражения могут быть применимы только для данной страницы, а может быть, и для ее загрузки. Зачастую может потребоваться тонкая настройка выражения.
Тонкая настройка выражений
В двух предыдущих примерах мы использовали абсолютные пути, и они прекрасно работали в нашем контексте, однако всегда есть возможность для оптимизации. Например, учитывая, что у example.com есть только одна единственная ссылка, мы могли бы легко сократить наши выражения до следующих:
# XPath
//a# CSS
a
С одной стороны, к сожалению, это не только не очень разборчиво, но и может не работать при перезагрузке из-за изменения классов HTML.
С другой стороны, к счастью, в данном случае у нас есть очень специфический HTML-элемент, который значительно упростит все дело -> <time>.
Мы просто используем time (или //time для XPath) и получаем "только" тот элемент, который нам нужен. Кавычки, потому что Twitter показывает связанные твиты, и в каждом из них будет элемент <time>, так что убедитесь, что используете только первый.
Однако не только конкретные типы элементов могут помочь нам сузить выражение, мы также должны обращать внимание на HTML-идентификаторы, классы, атрибуты, а иногда даже на содержимое.
IDs должен быть уникальным, поэтому быстрый #myid или (//*[@id="myid"]) позволит получить элемент быстрее и стабильнее, чем абсолютный путь.
Хотя классы не обязательно уникальны, они все равно могут оказать волшебное действие, особенно если, например, поместить их в контекст иерархии документа: h1 > b.price
И последнее, но не менее важное: инструменты devtools также позволяют оценивать выражения XPath и селекторы CSS.
Просто нажмите F12 еще раз, выберите вкладку Elements и нажмите Ctrl/⌘ + F, чтобы открыть окно поиска.
Окно поиска
Здесь можно пробовать различные XPath-выражения и CSS-селекторы и перебирать найденные элементы (если они, конечно, есть).
Довольно удобно для быстрого опробования выражений.
Итог
Мы надеемся, что статья вам понравилась, и вы получили первое представление о том, что представляют собой эти два языка и в чем их сильные и слабые стороны.
Поскольку в этой статье мы старались сосредоточиться на основных различиях между селекторами XPath и CSS, мы не стали углубляться в технические детали синтаксиса элементов каждого языка.


