【问题标题】:Python re.findall returns only first matchPython re.findall 仅返回第一个匹配项
【发布时间】:2021-01-09 03:56:20
【问题描述】:

我对此有点坚持,在这里没有发现类似的问题。

我想获取字符串中所有标签元素的列表,例如, <a> -> a</b> -> b

import re

s = '<p><a href="http://www.quackit.com/html/tutorial/html_links.cfm">Example Link</a></p>'
pat = r'<\s*(\w+)/?\s*.*>'
tags = re.findall(pat, s)
print(tags)

结果我得到['p']。如果我将\w+ 更改为[a-d]+,我只会得到['a']

我希望结果为 ['p', 'a', 'a', 'p'] 或至少所有不同的标签值。

我在这里做错了什么?谢谢!

使用 Python 3.x

【问题讨论】:

    标签: python-3.x regex findall python-re


    【解决方案1】:

    首先,您需要使您的模式匹配非贪婪(将.* 切换为.*?)。您可以在 Python docs 中给出的示例中阅读更多相关信息(他们甚至使用 HTML 标记作为示例!)。

    其次,/? 部分应该在开头,而不是在标签名称\w+ 之后。

    另外,第二个\s* 是多余的,因为.* 也会捕获空格。

    import re
    
    s = '<p><a href="http://www.quackit.com/html/tutorial/html_links.cfm">Example Link</a></p>'
    pat = r'</?\s*(\w+).*?>'
    tags = re.findall(pat, s)
    print(tags)
    

    输出:

    ['p', 'a', 'a', 'p']
    

    对于更通用的解决方案,请考虑改用 BeautifulSoupHTMLParser

    from html.parser import HTMLParser
    
    class HTMLTagParser(HTMLParser):
    
        def handle_starttag(self, tag, attrs):
            tags.append(tag)
    
        def handle_endtag(self, tag):
            tags.append(tag)
    
    s = '<p><a href="http://www.quackit.com/html/tutorial/html_links.cfm">Example Link</a></p>'
    tags = []
    parser = HTMLTagParser()
    parser.feed(s)
    print(tags)
    

    输出:

    ['p', 'a', 'a', 'p']
    

    该方法适用于任意 HTML(因为正则表达式可能会因为您最小化所做的假设而变得混乱)。注意,对于开始标签,handle_starttag 中的 attrs 参数也可用于检索标签的属性,如果需要的话。

    【讨论】:

    • 谢谢,成功了!该字符串只是一个示例,如果这些是自闭合标签,则在标签字符之后也可以有“/”。一个问题:为什么是.*? - 我认为 .* 匹配 0 个或多个任何字符。我真的不明白?在这里。
    • 太好了,我还更新了我的答案以包含使用 Python 模块的替代方案,这是比使用正则表达式更通用和可靠的解决方案。
    • @matt444 它的正则表达式语法使.* 非贪婪。您可以在 Python 文档中阅读更多关于 here 的信息——他们甚至使用 HTML 标记作为示例。
    【解决方案2】:

    使用 or (|) 运算符并写下由运算符分隔的两种模式,它应该可以工作。

    参考这个, How is the AND/OR operator represented as in Regular Expressions?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多