lxml经典:获取文本内容,排除嵌套标签的内容?

3 投票
2 回答
4011 浏览
提问于 2025-04-17 06:23

这应该是个经典的问题,但我在这里找不到答案。我正在用lxml的cssselect来解析以下标签:

<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>

我想要获取这个<li>标签的内容,但不想要里面<span>标签的内容。

目前我有:

stop_list = doc.cssselect('ol#stations li a')
start = stop_list[0].text_content().strip()

但是这样得到的是3 Detroit。我该怎么做才能只得到Detroit呢?

2 个回答

4

对于你的例子,我觉得用XPath会比用CSS更简单、更干净:

>>> xml = '<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>'
>>> root = etree.fromstring(xml)
>>> print( root.xpath('/li/a/text()'))
[' Detroit']

>>> xml = '<li><a href="/stations/1">I <span>FooBar!</span> love <span class="num">3</span> Detroit</a></li>'
>>> root = etree.fromstring(xml)
>>> print( root.xpath('/li/a/text()'))
['I ', ' love ', ' Detroit']

>>> ' '.join([x.strip() for x in root.xpath('/li/a/text()')])
'I love Detroit'
3

itertext 方法是用来获取一个元素里面的文本数据的。比如说,对于你的 <a> 标签,' Detroit' 就是这个迭代器返回的第二个值。如果你的文档结构总是遵循一个固定的格式,你可以跳过一些特定的文本元素,直接获取你需要的内容。

from lxml import html

doc = html.fromstring("""<li><a href="/stations/1"><span class="num">3</span> Detroit</a></li>""")
stop_nodes = doc.cssselect('li a') 
stop_names = []
for start in stop_list:
    node_text = start.itertext()
    node_text.next() # Skip '3'
    stop_names.append(node_text.next().lstrip())
    continue

你可以把 CSS 选择器和 xpath 的 text() 函数结合起来使用,就像在 Zachary 的回答 中提到的那样(如果你对使用 CSS 选择器比 xpath 更熟悉的话):

stop_names = [a.xpath('text()').lstrip() for a in doc.cssselect('li a')]

撰写回答