【问题标题】:Python grouped backreferencesPython 分组反向引用
【发布时间】:2013-09-23 20:26:39
【问题描述】:

我正在清理一些可能源自所见即所得的html 的输出。为了理智,我想去掉一堆空的格式化标签。

例如

<em></em> Here's some text <strong>   </strong> and here's more <em> <span></span></em>

感谢Regular-Expressions.info,我有一个简洁的正则表达式,带有反向引用,可以一次打开一层

# Returns a string minus one level of empty formatting tags
def remove_empty_html_tags(input_string):
    return re.sub(r'<(?P<tag>strong|span|em)\b[^>]*>(\s*)</(?P=tag)>', r'\1', input_string)

但是,我希望能够一次打开 &lt;em&gt; &lt;span&gt;&lt;/span&gt;&lt;/em&gt; 的所有层,并且可能有 5 层以上的嵌套空标签。

有没有办法将 backref 分组为 (?:&lt;?P&lt;tagBackRef&gt;strong|span|em)\b[^&gt;]&gt;(\s)*)+(或其他东西),并在稍后与 (&lt;/(?P=tagBackRef&gt;)+ 一起使用以删除多个嵌套但匹配的空 html 标签?

为了后代:

这可能是XY Question,其中我希望用于我想要的结果的工具不是其他人会选择的工具。 Henry's answer 回答了这个问题,但他和其他所有人都会将您指向一个 html 解析器而不是正则表达式来解析 html。 =)

【问题讨论】:

  • 这就是为什么人们告诉你不要使用正则表达式来解析 HTML。请改用 HTML 解析器。
  • 你需要一个嵌套层的硬上限......并且每个潜在层的正则表达式变得更长(并且更复杂)
  • @MartijnPieters 还有什么,在树上寻找re.match('^\s*$', innerText)
  • @Michael:至少可以使用 BeautifulSoup。

标签: python html regex html-parsing


【解决方案1】:

使用 HTML 解析器更容易做到这一点,例如BeautifulSoup,例如:

from bs4 import BeautifulSoup

soup = BeautifulSoup("""
<body>
    <em></em> Here's some <span><strong>text</strong></span> <strong>   </strong> and here's more <em> <span></span></em>
</body>
""")

for element in soup.findAll(name=['strong', 'span', 'em']):
    if element.find(True) is None and (not element.string or not element.string.strip()):
        element.extract()

print soup

打印:

<html><body>
 Here's some <span><strong>text</strong></span>  and here's more <em> </em>
</body></html>

如您所见,所有内容为空(或仅包含空格)的spanstrongem 标记均已删除。

另见:

【讨论】:

  • 小心,element.string is None 有嵌套元素时;那些可能有文字。
  • @MartijnPieters 谢谢,我已经添加了element.find(True) is None 条件,应该会有所帮助。
  • 谢谢,alecxe。不过,我希望空的&lt;em&gt; &lt;/em&gt; 也会在第一遍被删除。
  • @Michael 这是因为 em 标签内部包含一个 span 标签。这里最简单的解决方案是多次运行“过滤器”代码。
【解决方案2】:

如果您真的不想使用HTML parser,并且您不太关心速度(我假设您不是,或者您不会使用正则表达式清理你的 HTML)你可以修改你已经编写的代码。只需将您的替换放在循环中(或递归;您的偏好)并在您不更改任何内容时返回。

# Returns a string minus all levels of empty formatting tags
def remove_empty_html_tags(input_string):
    matcher = r'<(?P<tag>strong|span|em)\b[^>]*>(\s*)</(?P=tag)>'
    old_string = input_string
    new_string = re.sub(matcher, r'\1', old_string)
    while new_string != old_string:
        old_string = new_string
        new_string = re.sub(matcher, r'\1', new_string)
    return new_string

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    • 2012-08-13
    • 2017-12-23
    相关资源
    最近更新 更多