【问题标题】:How can I match single and double html attributes in regular expression?如何在正则表达式中匹配单双 html 属性?
【发布时间】:2019-07-07 16:53:16
【问题描述】:

我有一个包含两个不同类的 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”,在这种情况下我该如何处理这种模式?

谢谢

【问题讨论】:

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


    【解决方案1】:

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

    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']
    

    【讨论】:

      【解决方案2】:

      我将扩展给出的其他答案之一。在您的较低示例中,您正在查看两个共享同一个类的元素,这应该足以匹配两个元素。您最上面的示例显示了一个复合类(元素的多个类名),但它再次共享同一类 rating-inbtn

      soup.select('.rating-inbtn')
      

      “.”在哪里是一个 CSS 类选择器。

      扩展其他答案:

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

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

      【讨论】:

        【解决方案3】:

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

        \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)))
        

        【讨论】:

        • 亲爱的@Emma 感谢您的回复。但我是正则表达式的菜鸟。做一些补丁工作。我为我的问题添加了更多背景信息。你能重新检查我的问题吗?
        猜你喜欢
        • 1970-01-01
        • 2010-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-03
        • 2011-04-05
        相关资源
        最近更新 更多