如何使用缩进将 HTML 漂亮地打印到文件中
Posted
技术标签:
【中文标题】如何使用缩进将 HTML 漂亮地打印到文件中【英文标题】:How to Pretty Print HTML to a file, with indentation 【发布时间】:2011-09-03 06:05:59 【问题描述】:我正在使用lxml.html 生成一些 HTML。我想将我的最终结果漂亮地打印(带有缩进)到一个 html 文件中。我该怎么做?
这是我到目前为止所尝试和得到的
import lxml.html as lh
from lxml.html import builder as E
sliderRoot=lh.Element("div", E.CLASS("scroll"), style="overflow-x: hidden; overflow-y: hidden;")
scrollContainer=lh.Element("div", E.CLASS("scrollContainer"), style="width: 4340px;")
sliderRoot.append(scrollContainer)
print lh.tostring(sliderRoot, pretty_print = True, method="html")
如您所见,我使用的是pretty_print=True
属性。我认为这会给出缩进的代码,但它并没有真正帮助。这是输出:
<div style="overflow-x: hidden; overflow-y: hidden;" class="scroll"><div style="width: 4340px;" class="scrollContainer"></div></div>
【问题讨论】:
【参考方案1】:我最终直接使用了BeautifulSoup。这是 lxml.html.soupparser 用于解析 HTML 的东西。
BeautifulSoup 有一个 prettify 方法,它完全按照它所说的做。它用适当的缩进和一切美化 HTML。
BeautifulSoup 不会修复 HTML,因此损坏的代码仍然损坏。但在这种情况下,由于代码是由 lxml 生成的,因此 HTML 代码至少在语义上应该是正确的。
在我的问题中给出的示例中,我必须这样做:
from BeautifulSoup import BeautifulSoup as bs
root = lh.tostring(sliderRoot) #convert the generated HTML to a string
soup = bs(root) #make BeautifulSoup
prettyHTML = soup.prettify() #prettify the html
【讨论】:
谢谢,但值得一提的是,如果对某人很重要,嵌入到 html 的js
不会美化。
在版本 4 中将第一行更改为 from bs4 import BeautifulSoup as bs
如果您只想从字符串中美化 html,请参阅下面 AlexG 的回答。
小心prettify
,因为它改变了文档语义:“由于它添加了空格(以换行符的形式),prettify()
改变了 HTML 文档的含义,不应该用于重新格式化一个。prettify()
的目标是帮助您直观地了解您使用的文档的结构。"【参考方案2】:
我尝试了 BeautifulSoup 的 prettify
和 html5print 的 HTMLBeautifier
解决方案,但由于我使用 yattag 生成 HTML,因此使用它的 indent
函数似乎更合适,它可以产生很好的缩进输出。
from yattag import indent
rawhtml = "String with some HTML code..."
result = indent(
rawhtml,
indentation = ' ',
newline = '\r\n',
indent_text = True
)
print(result)
【讨论】:
【参考方案3】:如果再添加一个依赖不成问题,您可以使用html5print 包。与其他解决方案相比,它的优势在于它还美化了嵌入在 HTML 文档中的 CSS 和 javascript 代码。
要安装它,请执行:
pip install html5print
然后,您可以将其用作命令:
html5-print ugly.html -o pretty.html
或作为 Python 代码:
from html5print import HTMLBeautifier
html = '<title>Page Title</title><p>Some text here</p>'
print(HTMLBeautifier.beautify(html, 4))
【讨论】:
这会安装其他几个依赖项,包括 beautifulsoup4【参考方案4】:如果您将 HTML 存储为未格式化的字符串,在变量 html_string
中,可以使用 beautifulsoup4 来完成,如下所示:
from bs4 import BeautifulSoup
print(BeautifulSoup(html_string, 'html.parser').prettify())
【讨论】:
【参考方案5】:虽然我的回答现在可能没有帮助,但我将其放在这里以作为将来其他人的参考。
lxml.html.tostring()
事实上,尽管有pretty_print=True
,它并不能很好地打印提供的 HTML。
但是,lxml.html
- lxml.etree
的“兄弟”运行良好。
所以可以如下使用它:
from lxml import etree, html
document_root = html.fromstring("<html><body><h1>hello world</h1></body></html>")
print(etree.tostring(document_root, encoding='unicode', pretty_print=True))
输出是这样的:
<html>
<body>
<h1>hello world</h1>
</body>
</html>
【讨论】:
pretty_print
标志仅在使用method='xml'
调用etree.tostring
时有效,这是默认设置。所以,我们在这里处理 XHTML。
这是一个很好的答案,因为它不使用任何外部依赖项。但是,如果包含 HTML 的字符串有回车,etree.tostring
什么都没有,并且至少在 Python 2.7.10 上返回其输入,不变......一旦你知道,替换回车是一件简单的事情,但是你不知道会浪费很多时间。
这很棒,因为它只提供了选项卡的解决方案。这不会以其他方式更改 HTML,例如 BeautifulSoup 解决方案。
不!这就是为什么。 etree.tostring 会将 "" 缩短为 "",这是不允许的。【参考方案6】:
在后台,lxml
使用libxml2
将树序列化回字符串。下面是相关的sn-p代码,判断关闭标签后是否追加换行符:
xmlOutputBufferWriteString(buf, ">");
if ((format) && (!info->isinline) && (cur->next != NULL))
if ((cur->next->type != HTML_TEXT_NODE) &&
(cur->next->type != HTML_ENTITY_REF_NODE) &&
(cur->parent != NULL) &&
(cur->parent->name != NULL) &&
(cur->parent->name[0] != 'p')) /* p, pre, param */
xmlOutputBufferWriteString(buf, "\n");
return;
所以如果一个节点是一个元素,不是一个内联标记并且后跟一个兄弟节点(cur->next != NULL
)并且不是p, pre, param
之一,那么它将输出一个换行符.
【讨论】:
【参考方案7】:不是我的代码,是我在某处挑选的
def indent(elem, level=0):
i = '\n' + level * ' '
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + ' '
if not elem.tail or not elem.tail.strip():
elem.tail = i
for elem in elem:
indent(elem, level+1)
if not elem.tail or not elem.tail.strip():
elem.tail = i
else:
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
我使用它:
indent(page)
tostring(page)
【讨论】:
【参考方案8】:你不能直接把它输入HTML Tidy吗?从 shell 或通过os.system()
。
【讨论】:
我最初想使用 HTML Tidy,但我的代码有点古怪,而整洁最终却对它造成了破坏。决定改用 BeautifulSoup。像魅力一样工作。 HTML Tidy 更正您的 HTML 可以break things。如果您忘记了 HTML Tidy 正在处理结果(我知道我在说什么),那么很难找到此类错误... 比这里的 2011 年 cmets 更近,请参阅这个 2018 年问题的答案:***.com/questions/50380799/…。 “该库已损坏和/或不适用于 python 3.5。”可能会节省一些时间...【参考方案9】:如果您不关心古怪的 HTML(例如,您必须绝对支持那些使用 Netscpae 2.0 的客户端,因此必须使用 <br>
而不是 <br />
),您可以随时将您的方法更改为“xml”,这似乎工作。这可能是lxml或libxml中的一个错误,但我找不到它的原因。
【讨论】:
设置方法为xml时,如果标签没有子元素,则不生成结束标签。例如,在有问题的示例中,内部 div 将没有结束标记。我真的不知道为什么。我最终使用 BeautifulSoup 来获得正确的输出。以上是关于如何使用缩进将 HTML 漂亮地打印到文件中的主要内容,如果未能解决你的问题,请参考以下文章