使用XPATH,选择无文本兄弟姐妹的节点



我想用python3和LXML提供的HTML Parser提取一些HTML元素。

考虑此html:

<!DOCTYPE html>
<html>
  <body>
    <span class="foo">
      <span class="bar">bar</span>
      foo
    </span>
  </body>
</html>

考虑此程序:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from lxml import html
tree = html.fromstring('html from above')
bars = tree.xpath("//span[@class='bar']")
print(bars)
print(html.tostring(bars[0], encoding="unicode"))

在浏览器中,查询选择器" span.bar"仅选择跨度元素。这就是我想要的。但是,以上程序产生:

[<Element span at 0x7f5dd89a4048>]
<span class="bar">bar</span>foo

看来我的XPATH实际上并不像查询选择器一样行为,并且在跨度元素旁边拾取了同级文本节点。如何调整XPath仅选择条元素,而不是文本" foo"?

请注意,lxml中的XML树模型(以及标准模块xml.etree中(具有tail的概念。因此, ag.a following-sibling of 元素的 ag.a 将作为该元素的 tail存储。因此,您的XPath正确返回span元素,但是根据树模型,它具有tail,该元素包含文本" foo"。

作为解决方法,假设您不想进一步使用树模型,只需在打印之前清除tail

>>> bars[0].tail = ''
>>> print(html.tostring(bars[0], encoding="unicode"))
<span class="bar">bar</span>

最新更新