如何在正则表达式中匹配单个和双重html属性?

时间:2019-07-07 16:53:16

标签: python regex beautifulsoup regex-group regex-greedy

我有一个带有两个不同类的html元素。但在某些情况下,我只有一堂课。当有两个类时,它们之间用空格隔开。

"rating-inbtn hide-if-zero-113"
 or 
"rating-inbtn"

如何在正则表达式中匹配两种模式。

作为参考,我想发表一个我的老文章:

<span class="vote-actions">
    <a class="btn btn-default vote-action-good">
        <span class="icon thumb-up black black-hover">&nbsp;</span>
        <span class="rating-inbtn">215</span>
    </a>
    <a class="btn btn-default vote-action-bad">
        <span class="icon thumb-down grey black-hover">&nbsp;</span>
        <span class="rating-inbtn">82</span>
    </a>
</span>

我正在使用此正则表达式提取评分

a = re.findall('rating-inbtn">(.*?)</span>', webpage)
        like_count = a[0]
        dislike_count = a[1]

但是有时span类具有多个属性“ hide-if-zero-113”,那么我该如何处理这种模式?

谢谢

3 个答案:

答案 0 :(得分:2)

也许我遗漏了一些东西,但是您不需要正则表达式来从代码中提取数字:

data = '''<span class="vote-actions">
    <a class="btn btn-default vote-action-good">
        <span class="icon thumb-up black black-hover">&nbsp;</span>
        <span class="rating-inbtn">215</span>
    </a>
    <a class="btn btn-default vote-action-bad">
        <span class="icon thumb-down grey black-hover">&nbsp;</span>
        <span class="rating-inbtn">82</span>
    </a>
</span>'''

from bs4 import BeautifulSoup

soup = BeautifulSoup(data, 'lxml')

print([span.text for span in soup.select('span.rating-inbtn')])

打印:

['215', '82']

答案 1 :(得分:1)

我将扩展给出的其他答案之一。在下面的示例中,您正在查看两个元素都共享同一个单一类,这足以匹配两个元素。您最顶层的示例显示了一个复合类(该元素有多个类名),但是它又共享rating-inbtn的同一类。

soup.select('.rating-inbtn')

其中的“。”是CSS类选择器。

扩展其他答案:

将来,您可以传递以“,”分隔的列表,以匹配多个类别(实际上是多个选择器),例如

soup.select('.rating-inbtn, .otherClass') 

答案 2 :(得分:0)

这取决于您希望添加到表达式中的边界。例如,我们可以开始于:

\s*([a-z0-9-]+)(?:\s+)?([a-z0-9-]+)?\s*

该表达式在this demo的右上角进行了说明,如果您想进一步探索或修改它,在this link中,您可以逐步观察它如何与某些示例输入匹配步骤,如果您愿意的话。


编辑:

要获取这些评分,该表达式可能就足够了:

rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/

Demo

使用re.findall

进行测试
import re

regex = r"rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/"

test_str = ("<span class=\"vote-actions\">\n"
    "    <a class=\"btn btn-default vote-action-good\">\n"
    "        <span class=\"icon thumb-up black black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">215</span>\n"
    "    </a>\n"
    "    <a class=\"btn btn-default vote-action-bad\">\n"
    "        <span class=\"icon thumb-down grey black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">82</span>\n"
    "<span class=\"rating-inbtn\"> 74 </span>\n"
    "<span class=\"rating-inbtn hide-if-zero-113\"> 99 </span>\n"
    "    </a>\n"
    "</span>")

print(re.findall(regex, test_str))

输出

['215', '82', '74', '99']

使用re.finditer

进行测试
import re

regex = r"rating-inbtn[^>]+>\s*([^\s<]+)\s*<\/"

test_str = ("<span class=\"vote-actions\">\n"
    "    <a class=\"btn btn-default vote-action-good\">\n"
    "        <span class=\"icon thumb-up black black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">215</span>\n"
    "    </a>\n"
    "    <a class=\"btn btn-default vote-action-bad\">\n"
    "        <span class=\"icon thumb-down grey black-hover\">&nbsp;</span>\n"
    "        <span class=\"rating-inbtn\">82</span>\n"
    "<span class=\"rating-inbtn\"> 74 </span>\n"
    "<span class=\"rating-inbtn hide-if-zero-113\"> 99 </span>\n"
    "    </a>\n"
    "</span>")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):

    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))

    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1

        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))