Как я могу добавить непротиворечивые пробелы в существующий HTML, используя Python? - PullRequest
3 голосов
/ 17 февраля 2010

Я только начал работать над веб-сайтом, на котором полно страниц со всем их HTML-кодом в одной строке, что очень трудно читать и работать с ним.Я ищу инструмент (предпочтительно библиотеку Python), который будет принимать ввод HTML и возвращать тот же HTML без изменений, за исключением добавления разрывов строк и соответствующих отступов.(Все теги, разметка и содержимое должны быть нетронутыми.)

Библиотека не должна обрабатывать искаженный HTML;Сначала я передаю HTML через html5lib , поэтому он будет получать правильно сформированный HTML.Однако, как упоминалось выше, я бы предпочел, чтобы это не изменило саму фактическую разметку;Я доверяю html5lib и предпочел бы, чтобы он обрабатывал аспект корректности.

Во-первых, кто-нибудь знает, возможно ли это только с html5lib?(К сожалению, их документация кажется немного скудной.) Если нет, какой инструмент вы бы предложили?Я видел, как некоторые люди рекомендуют HTML Tidy, но я не уверен, что его можно настроить только для изменения пробелов.(Будет ли что-нибудь делать, кроме вставки пробелов, если для начала ему был передан правильно сформированный HTML?)

Ответы [ 3 ]

2 голосов
/ 17 февраля 2010

Алгоритм

  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>
2 голосов
/ 18 февраля 2010

Я выбрал ответ Дж. Ф. Себастьяна, потому что я думаю, что он самый простой и, следовательно, лучший, но я добавляю другое решение для тех, кто не хочет устанавливать Beautiful Soup.(Кроме того, в html5lib 1.0 сборщик дерева Beautiful Soup будет устаревшим .) Это решение было благодаря совету Амаргоша;Я только немного уточнил.Глядя на html5lib, я понял, что он будет выводить объект минидома изначально, что означает, что я могу использовать его предложение 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>

Почему я перебираю дочерние элементы дерева, а не просто вызываю toprettyxml() на dom_tree напрямую?Часть HTML-кода, с которым я имею дело, на самом деле является фрагментами HTML, поэтому в нем отсутствуют теги <head> и <body>.Чтобы справиться с этим, я использовал метод parseFragment(), что означает, что я получаю взамен DocumentFragment (а не Document).К сожалению, у него нет метода writexml() (который вызывает toprettyxml()), поэтому я перебираю дочерние узлы, у которых есть метод.

1 голос
/ 17 февраля 2010

Если 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 () .

...