4

假设我有这种 HTML,我需要使用 lxml/ElementTree 从中选择“text2”:

<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>

如果我已经将 div 元素作为 mydiv,则 mydiv.text 仅返回“text1”。

使用 itertext() 充其量似乎是有问题或麻烦的,因为它会遍历 div 下的整个树。

是否有任何简单/优雅的方法可以从元素中提取非第一个文本块?

4

4 回答 4

13

嗯,lxml.etree 提供了完整的 XPath 支持,它允许您处理文本项:

>>> import lxml.etree
>>> fragment = '<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>'
>>> div = lxml.etree.fromstring(fragment)
>>> div.xpath('./text()')
['text1', 'text2', 'text3']
于 2010-09-23T21:45:30.860 回答
6

此类文本将位于tail元素子元素的属性中。如果您的元素在其中elem

elem[0].tail

会给你元素中第一个孩子的尾部文本,在你的情况下,"text2"你正在寻找。

于 2010-09-10T10:58:06.540 回答
4

正如 llasram 所说,任何不在text属性中的文本都将在tail子节点的属性中。

例如,这是提取节点中所有文本块(第一个和其他)的最简单方法:

html = '<div>text1<span>childtext1</span>text2<span>childtext2</span>text3</div>'

import lxml.html    # ...or lxml.etree as appropriate
div = lxml.html.fromstring(html)

texts = [div.text] + [child.tail for child in div]
# Result: texts == ['text1', 'text2', 'text3']
# ...and you are guaranteed that div[x].tail == texts[x+1]
# (which can be useful if you need to access or modify the DOM)

如果您宁愿牺牲该关系以防止texts可能包含空字符串,则可以改用它:

texts = [div.text] + [child.tail for child in div if child.tail]

我没有用普通的旧 stdlib ElementTree 测试过这个,但它也应该适用。(当我看到 Shane Holloway 的 lxml 特定解决方案时,我才想到这一点)我只是更喜欢 LXML,因为它对 HTML 的 ideosyncracies 有更好的支持,而且我通常已经安装了它lxml.html.clean

于 2010-09-19T19:37:51.317 回答
1

用于node.text_content()将节点下的所有文本作为单个字符串获取。

于 2012-10-30T07:39:30.633 回答