使用 lxml etree 将 html 标签打印为字符串

Print html tags as string using lxml etree

我想像 soup.find_all() 一样打印整个标签,但使用 lxml etree。在 lxml 中 它打印出标签名称而不是我想用于比较目的的整个标签。谢谢。

代码:

from bs4 import BeautifulSoup
from lxml import etree

doc = "<p><a></a><a></a>Printable Text"
soup = BeautifulSoup(doc, "lxml")
root = etree.fromstring(str(soup))

tree = etree.ElementTree(root)
for e in tree.iter():
    print(e.tag)
    print("--------------")

输出:

html
--------------
body
--------------
p
--------------
a
--------------
a
--------------

预期输出:

<html><body><p><a></a><a></a>Printable Text</p></body></html>
--------------
<body><p><a></a><a></a>Printable Text</p></body>
--------------
<p><a></a><a></a>Printable Text</p>
--------------
<a></a>
--------------
<a></a>
--------------

你真的不需要用 beautifulsoup 解析你的 doc(请注意,在你的问题中你没有包含结束 <p> 标签),然后用lxml,最后用 ElementTree 包装它。但是,如果您 want/need 坚持这一点,您可以通过将 for 循环从

更改为接近(但不是 100%)的预期输出
for e in tree.iter():
    print(e.tag)
    

to(正如@mzjn 在评论中提到的):

for e in tree.iter():
    print(etree.tostring(e).decode())
    

如果您want/can跳过 ElementTree 步骤,您可以使用 xpath 获得相同的输出:

for e in root.xpath('//*'):
    print(etree.tostring(e).decode())
    

无论哪种情况,输出都是

<html><body><p><a/><a/>Printable Text</p></body></html>
<body><p><a/><a/>Printable Text</p></body>
<p><a/><a/>Printable Text</p>
<a/>
<a/>Printable Text

如果您 can/want 完全跳过 lxml 部分,您可以通过使用 css 选择器直接从 soup 打印来获得准确的预期输出:

for s in soup.select('*'):
    print(s)

输出:

<html><body><p><a></a><a></a>Printable Text</p></body></html>
<body><p><a></a><a></a>Printable Text</p></body>
<p><a></a><a></a>Printable Text</p>
<a></a>
<a></a>