30

関数のカスタム インデント幅を定義する方法はあります.prettify()か? ソースから得られるものから-

def prettify(self, encoding=None, formatter="minimal"):
    if encoding is None:
        return self.decode(True, formatter=formatter)
    else:
        return self.encode(encoding, True, formatter=formatter)

インデント幅を指定する方法はありません。関数のこの行が原因だと思いdecode_contents()ます-

s.append(" " * (indent_level - 1))

1スペースの固定長を持っています! (なぜ!!) を指定indent_level=4してみましたが、結果は次のようになりました -

    <section>
     <article>
      <h1>
      </h1>
      <p>
      </p>
     </article>
    </section>

それはただの愚かに見えます。:|

これでハッキングできますが、足りないものがあるかどうかを確認したいだけです。これは基本的な機能であるべきだからです。:-/

HTML コードをきれいにする良い方法があれば教えてください。

4

3 に答える 3

26

私は実際に、可能な限り最もハックな方法で、結果を後処理することで、これを自分で処理しました。

r = re.compile(r'^(\s*)', re.MULTILINE)
def prettify_2space(s, encoding=None, formatter="minimal"):
    return r.sub(r'\1\1', s.prettify(encoding, formatter))

実際、クラスprettify_2spaceの代わりにモンキーパッチを適用しprettifyました。これはソリューションにとって必須ではありませんが、とにかく実行して、インデント幅を 2 ​​にハードコーディングする代わりにパラメーターにしましょう。

orig_prettify = bs4.BeautifulSoup.prettify
r = re.compile(r'^(\s*)', re.MULTILINE)
def prettify(self, encoding=None, formatter="minimal", indent_width=4):
    return r.sub(r'\1' * indent_width, orig_prettify(self, encoding, formatter))
bs4.BeautifulSoup.prettify = prettify

そう:

x = '''<section><article><h1></h1><p></p></article></section>'''
soup = bs4.BeautifulSoup(x)
print(soup.prettify(indent_width=3))

…与えます:

<html>
   <body>
      <section>
         <article>
            <h1>
            </h1>
            <p>
            </p>
         </article>
      </section>
   </body>
</html>

Tag.prettify明らかに、と同様にパッチを適用したい場合BeautifulSoup.prettifyは、そこで同じことを行う必要があります。(自分で繰り返すのではなく、両方に適用できる汎用ラッパーを作成することをお勧めします。) そして、他のprettify方法がある場合は、同じことを扱います。

于 2013-03-20T01:06:34.630 に答える
6

私の知る限り、この問題にはいくつかの解決策があるため、この機能は組み込まれていません。

あなたがBeautifulSoup4を使用していると仮定して、これが私が思いついた解決策です

ハードコーディングします。これには最小限の変更が必要です。さまざまな状況でインデントを変える必要がない場合は、これで問題ありません。

myTab = 4 # add this
if pretty_print:
   # space = (' ' * (indent_level - 1))
    space = (' ' * (indent_level - myTab))
    #indent_contents = indent_level + 1
    indent_contents = indent_level + myTab 

以前のソリューションのもう1つの問題は、テキストコンテンツが完全に一貫してインデントされないことですが、それでも魅力的です。より柔軟で一貫性のあるソリューションが必要な場合は、クラスを変更するだけです。

prettify関数を見つけて、そのように変更します(element.pyのTagクラスにあります)。

#Add the myTab keyword to the functions parameters (or whatever you want to call it), set it to your preferred default.
def prettify(self, encoding=None, formatter="minimal", myTab=2): 
    Tag.myTab= myTab # add a reference to it in the Tag class
    if encoding is None:
        return self.decode(True, formatter=formatter)
    else:
        return self.encode(encoding, True, formatter=formatter)

次に、Tagクラスのdecodeメソッドまで上にスクロールして、次の変更を加えます。

if pretty_print:
    #space = (' ' * (indent_level - 1))
    space = (' ' * (indent_level - Tag.myTab))
    #indent_contents = indent_level + Tag.myTab 
    indent_contents = indent_level + Tag.myTab

次に、Tagクラスのdecode_contentsメソッドに移動し、次の変更を行います。

#s.append(" " * (indent_level - 1))
s.append(" " * (indent_level - Tag.myTab))

これで、BeautifulSoup('<root> <child> <desc> Text </ desc> </ child> </ root>')。prettify(myTab = 4)は次を返します。

<root>
    <child>
        <desc>
            Text
        </desc>
    </child>
</root>

** Tagクラスを継承するため、BeautifulSoupクラスにパッチを適用する必要はありません。タグクラスにパッチを適用することで、目標を達成するのに十分です。

于 2013-03-20T00:59:57.057 に答える