我正在使用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>
答案 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)