Получите текст второго элемента с XPath?
<span class='python'>
<a>google</a>
<a>chrome</a>
</span>
Я хочу получить chrome
и работать с этим уже.
q = item.findall('.//span[@class="python"]//a')
t = q[1].text # first element = 0
Я хотел бы объединить его в одно выражение XPath и просто получить один элемент вместо списка.
Я пробовал это, но он не работает.
t = item.findtext('.//span[@class="python"]//a[2]') # first element = 1
И фактический, а не упрощенный HTML-код выглядит следующим образом.
<span class='python'>
<span>
<span>
<img></img>
<a>google</a>
</span>
<a>chrome</a>
</span>
</span>
Ответы
Ответ 1
Я пробовал это, но он не работает.
t = item.findtext('.//span[@class="python"]//a[2]')
Это часто задаваемый вопрос об аббревиатуре //
.
.//a[2]
означает: выберите все a
потомки текущего node, которые являются вторым дочерним элементом a
их родителя. Таким образом, это может выбрать более одного элемента или никакого элемента - в зависимости от конкретного XML-документа.
Проще говоря, оператор []
имеет более высокий приоритет, чем //
.
Если вы хотите, чтобы только один (второй) из всех возвращенных узлов, вы должны использовать скобки для принудительного выбора:
(.//a)[2]
Это действительно выбирает второй a
потомок текущего node.
Для фактического выражения, используемого в вопросе, измените его на:
(.//span[@class="python"]//a)[2]
или изменить его на:
(.//span[@class="python"]//a)[2]/text()
Ответ 2
Я не уверен, в чем проблема...
>>> d = """<span class='python'>
... <a>google</a>
... <a>chrome</a>
... </span>"""
>>> from lxml import etree
>>> d = etree.HTML(d)
>>> d.xpath('.//span[@class="python"]/a[2]/text()')
['chrome']
>>>
Ответ 3
От комментариев:
или упрощение фактического HTML, который я опубликовал, слишком прост.
Вы правы. В чем смысл .//span[@class="python"]//a[2]
? Это будет расширено:
self::node()
/descendant-or-self::node()
/child::span[attribute::class="python"]
/descendant-or-self::node()
/child::a[position()=2]
Окончательно выберите второй a
child (fn:position()
относится к тону child
). Таким образом, ничто не будет выбрано, если ваш документ похож:
<span class='python'>
<span>
<span>
<img></img>
<a>google</a><!-- This is the first "a" child of its parent -->
</span>
<a>chrome</a><!-- This is also the first "a" child of its parent -->
</span>
</span>
Если вы хотите второго из потомков, используйте:
descendant::span[@class="python"]/descendant::a[2]