Pergunta

Comecei a trabalhar em um site cheio de páginas com todo o seu HTML em uma única linha, o que é uma verdadeira dor de ler e trabalhar. Estou procurando uma ferramenta (de preferência uma biblioteca Python) que levará a entrada HTML e retornará o mesmo HTML inalterado, exceto por adicionar linebreaks e recuo apropriado. (Todas as tags, marcação e conteúdo devem ser intocadas.)

A biblioteca não precisa lidar com HTML malformada; Estou passando o HTML através html5lib Primeiro, por isso estará ficando bem formado HTML. No entanto, como mencionado acima, prefiro que isso não mudasse nenhuma marcação real; Eu confio em html5lib e prefiro deixá -lo lidar com o aspecto da correção.

Primeiro, alguém sabe se isso é possível com apenas html5lib? (Infelizmente, a documentação deles parece um pouco escassa.) Caso contrário, que ferramenta você sugeriria? Vi algumas pessoas recomendarem o HTML Tidy, mas não tenho certeza se ele pode ser configurado apenas para mudar o espaço em branco. (Faria alguma coisa, exceto inserir o espaço em branco se fosse passado HTML bem formado para começar?)

Foi útil?

Solução

Algoritmo

  1. Analisar html em alguma representação
  2. Serialize a representação de volta ao HTML

Exemplo analisador html5lib com o BainfolSoup Tree Builder

#!/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()

Resultado:

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

Outras dicas

Eu escolhi a resposta de JF Sebastian porque acho que é a mais simples e, portanto, a melhor, mas estou adicionando outra solução para quem não deseja instalar uma sopa bonita. (Além disso, o lindo construtor de árvores de sopa vai ser descontinuado em html5lib 1.0.) Esta solução foi graças à dica de Amarghosh; Acabei de desenvolver um pouco. Olhando para o html5lib, percebi que ele produzirá um objeto de minidom nativamente, o que significa que eu posso usar a sugestão dele de toprettyxml(). Aqui está o que eu criei:

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

E um exemplo:

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

Por que estou iterando os filhos da árvore, em vez de apenas ligar toprettyxml() sobre dom_tree diretamente? Alguns dos html com os quais estou lidando são na verdade fragmentos html, então está faltando o <head> e <body> Tag. Para lidar com isso, usei o parseFragment() Método, o que significa que eu recebo um documentário em troca (em vez de um documento). Infelizmente, ele não tem um writexml() método (que toprettyxml() chamadas), então eu itero sobre os nós filhos, que têm o método.

Se o HTML estiver realmente bem formado XML, você poderá usar o DOM Parser.

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()

o toprettyxml () O método vamos especificar o caractere de recuo, nova linha e a codificação da saída. Você pode querer verificar o writexml () Método também.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top