【问题标题】:Using XPath, select node without text sibling使用 XPath,选择没有文本兄弟的节点
【发布时间】:2018-08-06 00:47:07
【问题描述】:

我想用python3和lxml提供的HTML解析器提取一些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”仅选择 span 元素。这就是我所渴望的。但是,上面的程序会产生:

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

看起来我的 XPath 实际上并不像查询选择器一样,并且在 span 元素旁边拾取同级文本节点。如何调整 XPath 以仅选择 bar 元素,而不选择文本“foo”?

【问题讨论】:

    标签: python-3.x xpath lxml.html


    【解决方案1】:

    注意lxml(以及标准模块xml.etree)中的XML 树模型具有tail 的概念。因此,位于之后的文本节点也就是 following-sibling of 元素将被存储为该元素的 tail。所以你的 XPath 正确地返回了 span 元素,但根据树模型,它有 tail 包含文本“foo”。

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

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

    【讨论】:

    • tail 的概念令人讨厌地与基于 XML 和 XPath 的正常期望相冲突,但这是一个非常有用的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多