繁体   English   中英

如何使用 lxml 从这个 HTML 片段中获取文本?

[英]How can I get the text from this HTML snippet using lxml?

谁能解释为什么这个片段在断言上失败?

from lxml import etree

s = '<div><h2><img />XYZZY</h2></div>'

root = etree.fromstring(s)

elements = root.xpath(".//*[contains(text(),'XYZZY')]")  # Finds 1 element, as expected

for el in elements:
    assert el.text is not None

然后......我怎样才能访问“XYZZY”并将其更改为“ZYX”?

谁能解释为什么这个片段在断言上失败?

因为<h2>元素的文本由 lxml 存储在h2元素的其中一个子元素中。 您可以使用iternext()来获取您要查找的内容。

from lxml import etree
s = '<div><h2><img />XYZZY</h2></div>'
root = etree.fromstring(s)
elements = root.xpath(".//*[contains(text(),'XYZZY')]")
for el in elements:
    el_text = ''.join(el.itertext())
    assert el_text is not None
    print(el_text)

更新:再看一遍之后,发现每个元素都有 3 个相关属性: .tag.text.tail

对于.tail属性,教程中有一小部分对其进行了解释:

<html><body>Hello<br/>World</body></html>

在这里,
标签被文本包围。 这通常称为文档样式或混合内容 XML。 元素通过其 tail 属性支持这一点。 它包含直接跟随元素的文本,直到 XML 树中的下一个元素

这里再次解释了如何填充.tail

LXML 附加尾随文本,它没有包含在它自己的标签内,作为之前标签的.tail属性。

所以我们实际上可以编写以下代码,遍历元素树中的每个元素,并找到文本XYZZY所在的位置:

from lxml import etree
s = '<div><h2><img />XYZZY</h2></div>'
root = etree.fromstring(s)

context = etree.iterwalk(root, events=("start","end"))
for action, elem in context:
    print("%s: %s : [text=%s : tail=%s]" % (action, elem.tag, elem.text, elem.tail))

Output:

start: div : [text=None : tail=None]
start: h2 : [text=None : tail=None]
start: img : [text=None : tail=XYZZY]
end: img : [text=None : tail=XYZZY]
end: h2 : [text=None : tail=None]
end: div : [text=None : tail=None]

所以它位于<img>元素的.tail属性中。

关于你的第二个问题:

然后......我怎样才能访问“XYZZY”并将其更改为“ZYX”?

一种解决方案是遍历元素树,检查每个元素的文本或尾部是否包含字符串,然后替换它:

#!/usr/bin/python3
from lxml import etree
s = '<div><h2><img />XYZZY</h2></div>'
root = etree.fromstring(s)

search_string = "XYZZY"
replace_string = "ZYX"

context = etree.iterwalk(root, events=("start","end"))
for action, elem in context:
    if elem.text and elem.text.strip() == search_string:
        elem.text = replace_string
    elif elem.tail and elem.tail.strip() == search_string:
        elem.tail = replace_string

print(etree.tostring(root).decode("utf-8"))

Output:

<div><h2><img/>ZYX</h2></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM