#python #html #selenium #xpath
#python #HTML #селен #xpath
Вопрос:
мои знания о selenium на данный момент немного ограничены, но из того, что я понимаю driver.find_elements_by_xpath() возвращает список webelements. Затем можно перебирать элементы и делать все, что угодно, например, печатать текст. Эта часть проста. Но теперь предположим, что на данной странице я буду искать каждую комбинацию из 3 узлов:
<parent>
<h1>text</h1>
<div class="identifier">more stuff</div>
<h3>text2</h3>
<h1>other text</h1>
<div class="identifier">other more stuff</div>
<h3>other text2</h3>
...
</parent>
Эти 3 узла (здесь h1, div с классом и h3) находятся на одном уровне иерархии, и их там много, поскольку это список. Есть ли способ заставить selenium вернуть их «упакованными»? В этом случае я мог бы убедиться, что собрал правильные данные. То, как я делаю это прямо сейчас, — это получение среднего элемента, а затем предшествующего и следующего родственного элемента с указанным тегом. Но я чувствую, что это в лучшем случае странно.
Спасибо большое.
Комментарии:
1. Лучший способ сделать это, вероятно, включает ссылку родительского элемента на эти родственные элементы. Можете ли вы опубликовать еще немного окружающего HTML? Вы не сможете вернуть эти упакованные файлы прямо из одного поиска, используя Selenium, но вы могли бы написать функцию, которая принимает родительский элемент и возвращает коллекцию из этих трех элементов в виде «пакета».
2. Спасибо, Джефф. Вот что я подумал. Однако есть одна проблема. Единственный родительский элемент содержит кучу моих комбинаций из 3 узлов. Я обновил описание, достаточно ли это отвечает на ваш вопрос?
Ответ №1:
Я не уверен, какой код вы используете для своего подхода, но я бы сделал что-то вроде этого.
headings = driver.find_elements_by_css_selector("parent > h1"))
for i in range(len(headings)):
heading = driver.find_element_by_css_selector("parent > h1:nth-of-type(" i ")"))
identifier = driver.find_element_by_css_selector("parent > div.identifier:nth-of-type(" i ")"))
subheading = driver.find_element_by_css_selector("parent > h3:nth-of-type(" i ")"))
// do something with each element here
Теперь вы можете ссылаться на каждый из элементов.
ПРИМЕЧАНИЕ: предполагается, что каждый из элементов всегда существует. Если вы когда-либо пропускаете h3
и т. Д. этот код будет несоответствовать группам.
Комментарии:
1. спасибо за ваш комментарий, я делаю что-то очень похожее. меня беспокоит именно то, что вы указали, но я предполагаю, что в selenium нет встроенной функциональности для решения этой проблемы.
2. Вы могли бы добавить проверку перед циклом, которая проверяет, что количество h1s, div.identifier и h3 равны. Если это не так, выдайте ошибку… или что-то, чтобы вы знали, что все будет отключено. На данный момент я не знаю, что бы вы сделали. Мне нужно было бы самому увидеть HTML, чтобы попытаться придумать какой-то подход.
3. Да, это в значительной степени то, что я в итоге сделал. Спасибо, что поддержали мой подход. Оффтопик: я видел, как вы использовали css_selectors. До сих пор я в основном использовал XPath. Я провел некоторые повторные исследования и не смог найти веской причины не использовать его (совсем наоборот: например, «contains» не работает с css_selectors) Что вы думаете об этом?
4. Все быстрее, чем XPath … и быстрее я имею в виду доли секунды, но все складывается. Если вы можете найти тот же элемент, но найти его быстрее, почему бы и нет? Я предпочитаю локаторы в таком порядке: идентификатор, селектор CSS, а затем все остальное до XPath. Я использую XPath только тогда, когда мне абсолютно необходимо … используя
text()
илиcontains()
или какую-то странную родительскую / родственную / etc вещь, которую нельзя сделать с помощью селекторов CSS. Я думаю, что многие люди используют XPath из-за Firebug и т. Д. Они могут щелкнуть правой кнопкой мыши и получить XPath. Обычно это приводит к действительно плохим и хрупким XPath, и их следует избегать, но это просто.
Ответ №2:
Ваш подход хорош — просто найдите первый элемент, а затем проверьте, чтобы следующий (и один после) были теми, которые вы ожидаете, в противном случае продолжайте поиск.
Для более сложных случаев, подобных этому, может быть проще извлечь HTML-код тела в виде текста и запустить (более мощное) регулярное выражение для него.
Комментарии:
1. Вы действительно, действительно не хотите использовать регулярное выражение HTML. Я не уверен, что регулярное выражение будет делать в этом случае, чего не могут локаторы. Регулярное выражение, скорее всего, будет действительно сложным и хрупким.
2. Для каждой проблемы, которую пытаются решить с помощью регулярного выражения, он заканчивает двумя новыми 🙂