Подтвердить что ты не робот

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>

4b9b3361

Ответ 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())