web-dev-qa-db-ja.com

インデントを使用してHTMLをファイルにきれいに印刷する方法

lxml.html を使用してHTMLを生成しています。最終結果を(インデント付きで)HTMLファイルにきれいに印刷したい。それ、どうやったら出来るの?

これは私が今まで試してきたものです(Python and 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>

55
bcosynot

最終的に BeautifulSoup を直接使用しました。 lxml.html.soupparser はHTMLの解析に使用します。

BeautifulSoupには、指定されたとおりの処理を行うprettifyメソッドがあります。適切なインデントとすべてで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
80
bcosynot

私の答えは今は役に立たないかもしれませんが、将来的に他の誰かへの参照として機能するためにここにドロップします。

lxml.html.tostring()は実際、pretty_print=Trueにもかかわらず提供されたHTMLをきれいに出力しません。

ただし、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>
31
Jayesh Bhoot

HTMLをフォーマットされていない文字列として、変数html_string、次のようにbeautifulsoup4を使用して実行できます。

from bs4 import BeautifulSoup
print(BeautifulSoup(html_string, 'html.parser').prettify())
11
AlexG

内部では、lxmllibxml2を使用してツリーをシリアル化して文字列に戻します。タグを閉じた後に改行を追加するかどうかを決定するコードの関連スニペットは次のとおりです。

    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;

そのため、ノードが要素であり、インラインタグではなく、兄弟ノードが後に続くcur->next != NULL)であり、p, pre, paramのいずれでもない場合、改行。

3
samplebias

依存関係をもう1つ追加しても問題ない場合は、 html5print パッケージを使用できます。他のソリューションに勝る利点は、HTMLドキュメントに埋め込まれたCSSとJavaScriptコードの両方を美しくすることです。

それをインストールするには、次を実行します:

pip install html5print

次に、コマンドとして使用できます。

html5-print ugly.html -o pretty.html

またはPython code:

from html5print import HTMLBeautifier
html = '<title>Page Title</title><p>Some text here</p>'
print(HTMLBeautifier.beautify(html, 4))
3
pgmank

BeautifulSoupのprettifyとhtml5printのHTMLBeautifierソリューションの両方を試しましたが、HTMLを生成するために yattag を使用しているので、indent関数を使用する方が適切なようです。 、適切にインデントされた出力を生成します。

from yattag import indent

rawhtml = "String with some HTML code..."

result = indent(
    rawhtml,
    indentation = '    ',
    newline = '\r\n',
    indent_text = True
)

print(result)
2
Vadym Pasko

それを HTML Tidy にパイプするだけではできませんか?シェルから、またはos.system()を介して。

2
tsm

風変わりなHTMLを気にしない場合(たとえば、Netscpae 2.0を使用するクライアントの大群を完全にサポートする必要があるため、<br> の代わりに <br />は必須です)、メソッドをいつでも "xml"に変更できます。これは動作しているようです。これはおそらくlxmlまたはlibxmlのバグですが、その理由はわかりませんでした。

1
Boaz Yaniv

私のコードではなく、どこかで選んだ

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)
1
sherpya