2013-03-19 13 views
17

.prettify()のカスタムインデント幅を定義する方法はありますか?私はそれがソースから得られるものから -BeautifulSoupのカスタムインデント幅.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) 

インデント幅を指定する方法はありません。

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

1つのスペースの固定長である - 私はそれがdecode_contents()機能であるため、この行のだと思います! (WHY !!)私はindent_level=4を指定してみました、それはちょうどこの、その結果 - 単なる愚かに見える

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

を。 :|

今、私はこれをハックすることができますが、欠けているものがあるかどうか確かめたいだけです。これは基本的な機能でなければならないからです。 : -/

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

+0

HTMLとXMLは非常に深く入れ子になっている傾向があります。私は、80列ウィンドウのようなCrummyの人たちを推測しています。しかし、この機能を要求するバグをメーリングリスト/グループやファイルに投稿したいかもしれません(そして、パッチはかなりシンプルです。そして、ramabodhiはすでにあなたのためにそれを書いています。あなたの電子メール/バグ報告する)。 – abarnert

+0

数年前に誰かが3.2と似たパッチをメーリングリストに投稿したようです。 [こちら](https://groups.google.com/forum/?fromgroups=#!topic/beautifulsoup/B4qryJpJqPY)をご覧ください。 – abarnert

+0

"1スペースの字下げは単なる愚かなようです:|" - ありがとうございました。これはまさに私がこの問題を探しているときに考えていたものです。 – Brandin

答えて

11

私は実際には、可能な限りもっともらしい方法でこれを処理しました。結果を後処理することによって。

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の代わりにprettify_2spaceをmonkeypatched。それは解決策に必須ではないですが、のは、とにかくそれをやらせて、インデントではなく、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.prettifyBeautifulSoup.prettifyの両方にパッチを適用する場合は、同じことを行う必要があります。 (自分で繰り返すのではなく、両方に適用できる汎用ラッパーを作成することもできます)。また、他の方法がある場合は、同じ方法をとってください。prettify

4

私の知る限りでは、この問題のためにいくつかのソリューションが存在するため、この機能は組み込まれていません。 。

あなたはBeautifulSoup 4使用していると仮定すると、ここで私は

打ちでそれを思いついた解決策がある。これは、最小限の変更を必要としますが、異なる状況で異なるようにインデントを必要としない場合、これは結構です。

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 

以前の解決策の別の問題は、テキストの内容は文句を言わない、まだ、完全に一貫して、しかし魅力インデントするということです。より柔軟で一貫性のあるソリューションが必要な場合は、クラスを変更するだけで済みます。

(それはelement.pyにタグクラスに位置しています)飾り立てる機能を検索し、そのように変更します。その後、

#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) 

とタグクラスのデコード方法までスクロールし、次を作ります変更:次に

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

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

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

今BeautifulSoup( '<ルート> <子> <DESC>テキスト</DESC > < /子供> < /ルート>')(Myタブ= 4)を返します.prettify:

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

**ありませんそれがTagクラスを継承するので、BeautifulSoupクラスにパッチを当てる必要があります。パッチタグクラスは、目標を達成するのに十分です。

+0

これはbs4ソースツリーに対するパッチに変換するのが非常に簡単です。これは便利です。 OPは、自分のbzrツリーのフォークを作成し、パッチを適用し、アップストリームのパッチを提出することができます。 – abarnert

+0

ありがとうございます。私はちょうど1人だけがこの年にこれで問題を抱えてパッチを提案したとは信じられませんでしたが、まだ合併されていません。私はすでに可変長を取るように関数を修正しました(ハードコーディングのものは嫌いです)。それはあなたが提案したことをかなり行います。しかし、あなたはこの行 'pretty_print =(indent_levelはNoneではありません)'のために 'indent_level'のために何かを用意する必要があります。' indent_level'のデフォルト値は 'None'であり、動的な変更方法はありませんそれ。 <_ < –