【问题标题】:remove line breaks and spaces around span elements with python regex使用 python regex 删除 span 元素周围的换行符和空格
【发布时间】:2019-09-21 13:09:12
【问题描述】:

使用 BeautifulSoup 的美化后,我想从 span 周围删除换行符和缩进,也许还有其他内联标签。

例如,我目前有这样的事情:

>>> import bs4
>>> html = "<div><p>I don't want this <span>span element</span> on it's one line.</p></div>"
>>> soup = bs4.BeautifulSoup(html, "html.parser")
>>> soup.prettify()
"<div>\n <p>\n  I don't want this\n  <span>\n   span element\n  </span>\n  on its one line.\n </p>\n</div>"
>>> print(soup.prettify())
<div>
 <p>
  I don't want this
  <span>
   span element
  </span>
  on it's one line.
 </p>
</div>

我可以使用什么正则表达式来删除 span 标签周围的缩进空格和换行符,以便我最终得到这个:

<div>
 <p>
  I don't want this <span>span element</span> on its one line.
 </p>
</div>

【问题讨论】:

  • 不太好,但如果它总是以这种方式显示,您可以使用soup.prettify().replace("\n &lt;span&gt;\n ", " &lt;span&gt;").replace("\n &lt;/span&gt;\n ", "&lt;/span&gt;")
  • 重复的建议仍然将跨度放在自己的行上。不过感谢您的建议。我正在尝试修改它以获得我想要的结果。

标签: python regex beautifulsoup


【解决方案1】:

我知道这已经很老了,Mohamed 已经提供了一个出色的答案。但是,我想添加它。

虽然这很好用,但我发现它错过了在标签之前或之后有换行符的标签(但不是两者都有)。我认为这是由于 [ \n]+ 中的 '+' 字符,它表示匹配一个或多个 \n 或空格(因此,如果标签之前和之前都没有一个或多个空格或换行符之后,它将不匹配)。我使用了他的方法,但将其切换为以下内容:

# removing space before and after <span> tag
html = re.sub('\s*<span>\s*','<span>', html)

# removing space before and after </span> tag
html = re.sub('\s*</span>\s*','</span>', html)

\s 将匹配任何空白字符(空格、制表符、换行符等),* 表示匹配其中的 0 个或多个(因此,如果仅在标签的一侧有空白字符,它仍然会匹配)

此外,如果您的任何元素具有属性(即&lt;span class="myclass"&gt;),您还需要做一些额外的事情:

'''
[^>]* says match 0 or more of any characters OTHER than >,
so you'd match: <span>, <span class="a">, <span style="display:hidden;">, etc...)
(the parens around it, store it in a capture class,
so it can be inserted in the replacement.)
'''
tag_regex = re.compile('\s*<span([^>]*)>\s*')
'''
the \1 inserts what was captured by the regex
(the [^>*], our attributes, if any) in to the replacement text. 
''' 
html = tag_regex.sub('<span\\1>', html)

# removing space before and after </span> tag
html = re.sub('\s*</span>\s*','</span>', html)

将所有这些放在适用于任何标签的 Mohamed 通用函数中,我们得到:

import re
from bs4 import BeautifulSoup

def prettify_output(html, tag):
    reg_tag = re.compile(f'\s*<{tag}([^>]*)>\s*')
    html = reg_tag.sub(f'<{tag}\\1>', html)
    html = re.sub(f'\s*</{tag}>\s*',f'</{tag}>', html)
    return html

html = BeautifulSoup("<body><div><div><span class='a'>dont</span><span class='b'>split me!</span></div></div></body>", 'html.parser')
html = html.prettify() # or however you call BeautifulSoup's prettify
html = prettify_output(html, 'span')

产生输出:

<body>
 <div>
  <div><span class="a">dont</span><span class="b">split me!</span></div>
 </div>
</body>

一项改进是保留&lt;span *stuff*&gt; 之前和&lt;/span&gt; 之后的换行符,除非它们嵌套在其他跨度之间/旁边(这将使美化换行符保持在&lt;div&gt;&lt;span class="a"&gt; 之间,以及之间&lt;/span&gt;&lt;/div&gt; 标记 - 目前该函数将它们删除,因为它正在删除这些标记之前和之后的所有空白字符。)

【讨论】:

    【解决方案2】:

    看看这个:

    import re
    
    html = '''
        <div>
            <p>
                I don't want this
                <span>
                    span element
                </span>
                on it's one line.
            </p>
        </div>
    '''
    
    soup = bs4.BeautifulSoup(html)
    
    ## getting prettified output 
    html = soup.prettify()
    
    
    # removing \n and space before and after <span> tag
    html = re.sub('[ \n]+<span>[ \n]+','<span>', html)
    
    # removing \n and space before and after </span> tag
    html = re.sub('[ \n]+</span>[ \n]+','</span>', html)
    
    

    执行print(html) 会得到以下输出:

    <div>
       <p>
           I don't want this<span>span element</span>on it's one line.
       </p>
    </div>
    

    你可以为不同的标签创建一个函数:

    import re
    
    def prettify_output(html, tag):
        html = re.sub(f'[ \n]+<{tag}>[ \n]+',f'<{tag}>', html)
        html = re.sub(f'[ \n]+</{tag}>[ \n]+',f'</{tag}>', html)
        return html
    
    ## call 
    html = prettify_output(html, 'span')
    

    【讨论】:

      猜你喜欢
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      相关资源
      最近更新 更多