BeautifulSoup .prettify()的自定义缩进宽度

Bib*_*ath 27 python code-formatting indentation 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)
Run Code Online (Sandbox Code Playgroud)

无法指定缩进宽度.我认为这是因为功能中的这一行decode_contents()-

s.append(" " * (indent_level - 1))
Run Code Online (Sandbox Code Playgroud)

其中固定长度为1个空格!(为什么!!)我尝试指定indent_level=4,这只是导致 -

    <section>
     <article>
      <h1>
      </h1>
      <p>
      </p>
     </article>
    </section>
Run Code Online (Sandbox Code Playgroud)

这看起来简直是愚蠢的.:|

现在,我可以解决这个问题,但我只是想确定是否有任何我遗漏的东西.因为这应该是一个基本功能.: - /

如果你有更好的方法来美化HTML代码,请告诉我.

aba*_*ert 19

我实际上是以最可能的方式处理这个问题:通过后处理结果.

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))
Run Code Online (Sandbox Code Playgroud)

实际上,我在班上prettify_2space代替了monkeypatched 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
Run Code Online (Sandbox Code Playgroud)

所以:

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

......给出:

<html>
   <body>
      <section>
         <article>
            <h1>
            </h1>
            <p>
            </p>
         </article>
      </section>
   </body>
</html>
Run Code Online (Sandbox Code Playgroud)

显然,如果要修补Tag.prettify,以及BeautifulSoup.prettify,你必须做同样的事情出现.(您可能希望创建一个可以应用于两者的通用包装器,而不是重复自己.)如果有任何其他prettify方法,同样的交易.


saa*_*aaj 12

Beautiful Soup 有输出格式化程序bs4.formatter.HTMLFormatter允许指定indent.

>>> import bs4
>>> s = '<section><article><h1></h1><p></p></article></section>'
>>> formatter = bs4.formatter.HTMLFormatter(indent=2)
>>> print(bs4.BeautifulSoup(s, 'html.parser').prettify(formatter=formatter))
<section>
  <article>
    <h1>
    </h1>
    <p>
    </p>
  </article>
</section>
Run Code Online (Sandbox Code Playgroud)

您还可以通过pyfil从命令行使用它(例如与 Geany 的“将选择发送到”功能集成):

pyfil 'bs4.BeautifulSoup(stdin, "html.parser").prettify(formatter=bs4.formatter.HTMLFormatter(indent=2))'
Run Code Online (Sandbox Code Playgroud)


Try*_*ass 5

据我所知,此功能不是内置的,因为针对此问题有很多解决方案。

假设您正在使用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 
Run Code Online (Sandbox Code Playgroud)

先前解决方案的另一个问题是文本内容不会被完全一致地缩进,但是仍然具有吸引力。如果您需要更灵活/一致的解决方案,则只需修改类。

找到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)
Run Code Online (Sandbox Code Playgroud)

然后向上滚动到Tag类中的解码方法并进行以下更改:

if pretty_print:
    #space = (' ' * (indent_level - 1))
    space = (' ' * (indent_level - Tag.myTab))
    #indent_contents = indent_level + Tag.myTab 
    indent_contents = indent_level + Tag.myTab
Run Code Online (Sandbox Code Playgroud)

然后转到Tag类中的decode_contents方法并进行以下更改:

#s.append(" " * (indent_level - 1))
s.append(" " * (indent_level - Tag.myTab))
Run Code Online (Sandbox Code Playgroud)

现在BeautifulSoup('<root> <child> <desc> Text </ desc> </ child> </ root>')。prettify(myTab = 4)将返回:

<root>
    <child>
        <desc>
            Text
        </desc>
    </child>
</root>
Run Code Online (Sandbox Code Playgroud)

**无需修补BeautifulSoup类,因为它继承了Tag类。修补Tag类足以实现目标。