如何使用缩进将HTML打印到文件中

时间:2011-05-27 09:09:22

标签: python html lxml pretty-print

我正在使用lxml.html生成一些HTML。我想打印(带缩进)我的最终结果到一个html文件。我该怎么做?

这是我迄今为止所尝试过的(我对Python和lxml相对较新):

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>

9 个答案:

答案 0 :(得分:78)

我最终直接使用BeautifulSoup。这是lxml.html.soupparser用于解析HTML的东西。

BeautifulSoup有一种美化方法,可以完全按照它的说法进行操作。它用适当的缩进和一切来美化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

答案 1 :(得分:31)

虽然我的答案现在可能没什么用,但是我将它放在这里作为未来其他人的参考。

事实上,

lxml.html.tostring()并不能完全打印提供的HTML,尽管pretty_print=True

然而,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>

答案 2 :(得分:11)

如果将HTML存储为无格式字符串,则在变量html_string中,可以使用beautifulsoup4完成,如下所示:

from bs4 import BeautifulSoup
print(BeautifulSoup(html_string, 'html.parser').prettify())

答案 3 :(得分:3)

在幕后,lxml使用libxml2将树序列化为字符串。以下是相关的代码片段,用于确定在关闭代码后是否附加换行符:

    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之一,那么它将输出换行符。

答案 4 :(得分: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))

答案 5 :(得分:2)

难道你不能把它管道插入HTML Tidy吗?来自shell或os.system()

答案 6 :(得分: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)

答案 7 :(得分:1)

如果您不关心古怪的HTML(例如,您必须支持绝对支持那些使用Netscpae 2.0的客户群,那么必须使用<br>代替<br />),您可以随时将您的方法更改为“xml”,这似乎有效。这可能是lxml或libxml中的一个错误,但我找不到它的原因。

答案 8 :(得分:1)

不是我的代码,我在某处选择了

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)
相关问题