【问题标题】:Python re.findallPython re.findall
【发布时间】:2025-12-02 16:45:02
【问题描述】:

我正在尝试检索所有包含“名称”字段的标签,然后处理整个句子加上名称。 这是我的测试代码:

sourceCode = '<dirtfields name="one" value="stuff">\n<gibberish name="two"\nwewt>'
namesGroup = re.findall('<.*name="(.*?)".*>', sourceCode, re.IGNORECASE | re.DOTALL)

for name in namesGroup:
    print name

哪个输出是:

two

我要寻找的输出是

['<dirtfields name="one" value="stuff">', 'one']
['<gibberish name="two"\nwewt>', 'two']

编辑: 找到了一种方法,感谢 doublesharp 以更简洁的方式获取“名称”值。

namesGroup = re.findall(r'(<.*?name="([^"]*)".*?>)', sourceCode, re.IGNORECASE | re.DOTALL)

将输出:

('<dirtfields name="one" value="stuff">', 'one')
('<gibberish name="two"\nwewt>', 'two')

【问题讨论】:

    标签: python regex python-2.7


    【解决方案1】:

    您的正则表达式有点偏离 - 您匹配的太多(一直到最后一个 &gt;)。由于您只需要在name= 之后的双引号之间输入值,因此请使用以下模式:

    name="([^"]*)"
    
    • name=" 匹配您要查找的属性的第一部分
    • ([^"]*) 基于任何 双引号
    • 的字符创建分组匹配
    • " 匹配 name 属性值后的双引号。

    您的代码将如下所示(在您的模式之前包含 r 是一种很好的形式):

    namesGroup = re.findall(r'name="([^"]*)"', sourceCode, re.IGNORECASE)
    

    【讨论】:

    • 非常感谢 doublesharp。这是一种更简洁的获取方式 =)
    • re.DOTALL 在这里没用。
    • @CasimiretHippolyte 非常正确......啊,剪切和粘贴。为清楚起见将其删除。
    • @Neomind 如果这对您有用,如果您将其标记为答案,我们将不胜感激,谢谢!
    • 这并不是我想要的答案。那个是在我所做的“编辑”中,但无论如何让我了解更多...所以谢谢!
    【解决方案2】:
    (?<=name=")[^"]*
    

    如果您只想匹配名称而没有捕获组,您可以使用:

    re.findall(r'(?<=name=")[^"]*', sourceCode, re.IGNORECASE )
    

    输出: ['one', 'two']

    当然,捕获组也是一种同样可以接受的解决方案。

    【讨论】:

      【解决方案3】:

      很明显,您正在处理HTMLXML 文件并寻找特定属性的一些值。

      如果你继续使用正则表达式而不是合法的文本解析器,你会犯方向错误。

      BeautifulSoup4,我最喜欢的一个,这里有一个非常简短的例子来说明如何使用它:

      from bs4 import BeautifulSoup
      
      sourceCode = '<dirtfields name="one" value="stuff">\n<gibberish name="two"\nwewt>'
      
      soup = BeautifulSoup(sourceCode)
      print soup.prettify()
      print '------------------------'
      for tag in soup.find_all():
          if tag.has_key('name'):
              print tag, tag['name']
      

      现在的输出看起来有点难看(输出甚至是错误的),但这表明beautifulsoup 将如何自动修复您损坏的html 并轻松找到您想要的属性。

      <html>
       <body>
        <dirtfields name="one" value="stuff">
         <gibberish name="two" wewt="">
         </gibberish>
        </dirtfields>
       </body>
      </html>
      ------------------------
      <dirtfields name="one" value="stuff">
      <gibberish name="two" wewt=""></gibberish></dirtfields> one
      <gibberish name="two" wewt=""></gibberish> two
      

      Beautifulsoup 添加到您最喜欢的 * 标签中,您会惊奇地发现它有多好,以及有多少人正在使用更强大的工具做同样的事情!

      【讨论】:

      【解决方案4】:

      这是一种允许在值内使用转义引号并避免(出于性能原因)惰性量词的模式。这就是为什么它有点长但更防水的原因:

      myreg = re.compile(r"""
          < (?: [^n>]+ | \Bn | n(?!ame\s*=) )+   # begining of the tag 
                                                 # until the name attribute
          name \s* = \s* ["']?                   # attribute until the value
          ( (?: [^\s\\"']+ | \\{2} | \\. )* )    # value
          [^>]*>                                 # end of the tag
      """, re.X | re.I | re.S)
      
      namesGroup = myreg.findall(sourceCode)
      

      不过,对于您的情况,使用 BS4 是一个不错的解决方案。

      【讨论】: