Python re.findall 只返回第一个匹配项

问题描述

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

我想获取字符串中所有标签元素的列表,例如<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','p'] 或至少所有不同的标签值。

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

使用 Python 3.x

解决方法

首先,您需要使您的模式匹配非贪婪(将 .* 切换为 .*?)。您可以在 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','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','p']

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

,

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

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