掌握LXML非连续文本/ ElementTree的

问题描述:

假设我有这种HTML,从中我需要选择“文本2”使用LXML/ElementTree的:掌握LXML非连续文本/ ElementTree的

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

如果我已经有div元素作为mydiv,那么mydiv.text只返回“text1”。

使用itertext()看起来有问题或麻烦,因为它遍历div下的整个树。

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

+1

这看起来像一个错误。你有没有尝试过使用'findtext(path)'? – 2010-09-18 06:55:43

+2

因为我的回答显然不能回答你的问题,你能否进一步解释你在找什么? – llasram 2010-09-19 09:18:51

好,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'] 
+0

doc.xpath('/ div/text()')[1:2]会给你非第一个文本元素 – shahjapan 2010-09-24 06:51:58

+1

好吧,“一种方式来提取非第一个文本块”包括许多可能性后,你得到所有文本项列表,如'random.choice(div.xpath('./text()')[1:])或set(div.xpath('./ text()')[1: ])。流行()'。但是,由于OP知道足够了解lxml,所以我认为数字列表操作就是小豆。 – 2010-09-24 07:43:35

这样的文本将在您的元素的子元素的tail属性中。如果你的元素是在elem则:

elem[0].tail 

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

正如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的测试,这一点,但它应该与工作了。 (事只有一次,我看到了巴蒂尔Holloway的具体LXML-解决发生在我身上),我只是喜欢LXML因为它有更好的支持HTML的ideosyncracies我通常已经安装了lxml.html.clean

使用node.text_content()让所有节点下面的文本,作为一个字符串。