Python: Как Pretty печатать html в файл
Я использую 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>
Ответы
Ответ 1
В итоге я использовал 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
Ответ 2
Хотя мой ответ может оказаться нецелесообразным сейчас, я отбрасываю его здесь, чтобы служить ссылкой на кого-либо еще в будущем.
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>
Ответ 3
Не могли бы вы просто передать его в HTML Tidy? Либо из оболочки, либо через os.system()
.
Ответ 4
Под капотом 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;
Итак, если node является элементом, это не встроенный тег и , за которым следует сиблинг node (cur->next != NULL
) и не является одним из p, pre, param
, тогда он будет выводить новую строку.
Ответ 5
Если вы не заботитесь о причудливой HTMLness (например, вы должны поддерживать абсолютно поддерживающие те орды клиентов Netscpae 2.0, поэтому наличие <br>
вместо <br />
является обязательным), вы всегда можете изменить свой метод на "xml", который, похоже, работает. Вероятно, это ошибка в lxml или в libxml, но я не мог найти причину этого.
Ответ 6
На самом деле не мой код, я выбрал его где-то
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)
Ответ 7
Если вы храните HTML как неформатированную строку, в переменной html_string
, это можно сделать с помощью beautifulsoup4 следующим образом:
from bs4 import BeautifulSoup
print(BeautifulSoup(html_string, 'html.parser').prettify())