lxml经典:获取文本内容,排除嵌套标签的内容?
这应该是个经典的问题,但我在这里找不到答案。我正在用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')]