如何用Python为现有HTML添加一致的空白?

3 投票
3 回答
688 浏览
提问于 2025-04-15 19:23

我刚开始做一个网站,里面的所有页面都是一整行的HTML,这让人看起来很费劲,也不方便操作。我在找一个工具(最好是Python库),可以把HTML输入进来,然后返回相同的HTML,只是在合适的地方加上换行和缩进。(所有的标签、标记和内容都不应该被改变。)

这个库不需要处理格式不正确的HTML;我会先用html5lib来处理HTML,这样它得到的就是格式正确的HTML。不过,正如上面提到的,我希望它不要改变任何实际的标记;我相信html5lib,宁愿让它来处理格式正确的问题。

首先,有人知道仅用html5lib能做到这一点吗?(不幸的是,他们的文档似乎有点简陋。)如果不行,你会推荐什么工具?我看到有些人推荐HTML Tidy,但我不确定它是否可以配置成只改变空白部分。(如果传入的是格式正确的HTML,它会做其他事情吗?)

3 个回答

1

如果你的HTML确实是格式正确的XML,那么你可以使用DOM解析器。

from xml.dom.minidom import parse, parseString

#if you have html string in a variable
html = parseString(theHtmlString)

#or parse the html file
html = parse(htmlFileName)

print html.toprettyxml()

toprettyxml()这个方法可以让你设置输出的缩进、换行符和编码方式。你也可以看看writexml()这个方法。

2

我选择了J.F. Sebastian的回答,因为我觉得它是最简单的,也是最好的。不过,我还想提供另一个解决方案,适合那些不想安装Beautiful Soup的人。(另外,Beautiful Soup的树构建器将在html5lib 1.0中被弃用。)这个解决方案得益于Amarghosh的提示,我只是稍微扩展了一下。看了html5lib后,我意识到它会原生输出一个minidom对象,这意味着我可以使用他的建议,调用toprettyxml()。这是我想到的:

from html5lib import HTMLParser, treebuilders
from cStringIO import StringIO

def tidy_html(text):
  """Returns a well-formatted version of input HTML."""

  p = HTMLParser(tree=treebuilders.getTreeBuilder("dom"))
  dom_tree = p.parseFragment(text)

  # using cStringIO for fast string concatenation
  pretty_HTML = StringIO()

  node = dom_tree.firstChild
  while node:
    node_contents = node.toprettyxml(indent='  ')
    pretty_HTML.write(node_contents)
    node = node.nextSibling

  output = pretty_HTML.getvalue()
  pretty_HTML.close()
  return output

还有一个例子:

>>> text = """<b><i>bold, italic</b></i><div>a div</div>"""
>>> tidy_html(text)
<b>
  <i>
    bold, italic
  </i>
</b>
<div>
  a div
</div>

我为什么要遍历树的子节点,而不是直接在dom_tree上调用toprettyxml()呢?因为我处理的一些HTML实际上是HTML片段,所以缺少了<head><body>标签。为了解决这个问题,我使用了parseFragment()方法,这样我得到的是一个DocumentFragment(而不是一个Document)。不幸的是,它没有writexml()这个方法(而toprettyxml()会调用这个方法),所以我只能遍历子节点,因为子节点是有这个方法的。

2

算法

  1. 将HTML解析成某种表示形式
  2. 再把这种表示形式转换回HTML

示例 使用html5lib解析器和BeautifulSoup树构建器

#!/usr/bin/env python
from html5lib import HTMLParser, treebuilders

parser = HTMLParser(tree=treebuilders.getTreeBuilder("beautifulsoup"))

c = """<HTML><HEAD><TITLE>Title</TITLE></HEAD><BODY>...... </BODY></HTML>"""

soup = parser.parse(c)
print soup.prettify()

输出:

<html>
 <head>
  <title>
   Title
  </title>
 </head>
 <body>
  ......
 </body>
</html>

撰写回答