簡體   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