【问题标题】:Regex pattern with subpattern exceptions (Python)带有子模式异常的正则表达式模式 (Python)
【发布时间】:2011-05-18 21:34:21
【问题描述】:

我正在使用 BeautifulSoup 从表中提取表数据标签。 TD 具有“a”、“u”、“e”、“available-unavailable”或“unavailable-available”类。 (是的,我知道古怪的类名,但是嘿......)

这是一个例子:

<tr>
  <td class="u">4</td>
  <td class="unavailable-available">5</td>
  <td class="a'>6</td>
  <td class="available-unavailable">7</td>
  <td class="u">8</td>
  ...

我一直在使用包含 re.compile() 的行:

  tab = [int(tag.string) for tag in soup.find('table',{'summary':tableSummary}).findAll("td", attrs = {"class": re.compile('\Aa')})]

我需要提取所有类名为“a”和“不可用-可用”的 td。我一直在尝试一些负面的前瞻性断言,但运气不佳。我会重视任何能够产生正确正则表达式的正则表达式图例......

【问题讨论】:

  • 你真的有 html 与 "a' 条目显示的引号不匹配吗?

标签: python regex web-scraping


【解决方案1】:

我向其他人的 RE 实力低头。但作为 BS+RE 的替代数据点,这里有一个 pyparsing 演绎版(假设那些讨厌的不匹配引号得到修复):

html = """
<tr> 
  <td class="u">4</td> 
  <td class="unavailable-available">5</td> 
  <td class="a">6</td> 
  <td class="available-unavailable">7</td> 
  <td class="u">8</td> 
"""

from pyparsing import makeHTMLTags, withAttribute, oneOf, SkipTo

# define opening and closing tag expressions
td,tdEnd = makeHTMLTags("TD")

# only want opening TD's with certain classes
td.setParseAction(withAttribute(**{'class':oneOf("a unavailable-available")}))

# define overall pattern
patt = td + SkipTo(tdEnd)("contents") + tdEnd

# search for matches
for t in patt.searchString(html):
    print t.dump()

打印:

['TD', ['class', 'unavailable-available'], False, '5', '</TD>']
- class: unavailable-available
- contents: 5
- empty: False
- endTd: </TD>
- startTd: ['TD', ['class', 'unavailable-available'], False]
  - class: unavailable-available
  - empty: False
['TD', ['class', 'a'], False, '6', '</TD>']
- class: a
- contents: 6
- empty: False
- endTd: </TD>
- startTd: ['TD', ['class', 'a'], False]
  - class: a
  - empty: False

对于每个匹配项,您还可以直接访问t.contentst['class'](必须使用dict 语法,因为class 是Python 关键字)。

【讨论】:

    【解决方案2】:

    哈!

    re.compile('^a(?!vail)|^un')
    
    • 匹配所有以 a 开头但不以 'vail' 开头的所有字符以及所有以 'un' 开头的字符。太好了!

    【讨论】:

      【解决方案3】:
      table.findAll('td', attrs = {"class":re.compile(r'(^|\s)(a|unavailable-available)($|\s)')})
      

      这匹配字符串或空格的开头,后跟“a”或“unavailable-available”,然后是空格或字符串结尾。所以它会匹配所有这些类型的东西

      class="a"
      class="a ui-xxx"
      class="ui-xxx a"
      class="ui-xxx a ui-yyy"
      class="unavailable-available"
      class="unavailable-available foo"
      

      【讨论】:

      • +1 表示稳健性和明确搜索的内容。
      • 您必须使用原始字符串,否则\s 将被误解。我冒昧地编辑了您的帖子。
      • @Tim:通常我会记得,但这次我忘了。感谢更新;那样更精确——尽管它不是更精确('\s' == '\\s' == r'\s',试试看)。如果它不起作用,我会注意到的,因为我确实尝试过。
      • 啊,是的,你是对的。由于\s 在字符串中没有特殊含义,因此反斜杠将被视为文字。但是,\b 不会发生这种情况,例如('\b' == '\\b' 返回False)。
      猜你喜欢
      • 2013-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-14
      • 1970-01-01
      • 2012-07-25
      相关资源
      最近更新 更多