【问题标题】:Why is this Python regex negative look ahead not working?为什么这个 Python 正则表达式否定前瞻不起作用?
【发布时间】:2014-12-20 23:13:25
【问题描述】:

我正在尝试使用 BeautifulSoup 收集一组具有非常具体标准的 URL。我要收集的 URL 必须包含 /b-\d+(/b- 后跟一系列数值)。但是,我想忽略所有包含 View%20All 的 URL,即使其中包含 /b-\d+。 以下是 URL 示例:

1. http://www.foo.com/bar/b-12312903?sName=View%20All
2. http://www.foo.com/bar/b-832173712873?sName=View%20All
3. http://www.foo.com/bar/b-1208313109283129
4. http://www.foo.com/bar/b-2198123371239489?adCell=W3

鉴于上述示例,我要收集的有效 URL 是 #3 和 #4。我尝试使用不同的否定前瞻正则表达式,但它们对我不起作用:

{"href" : re.compile(r"\/b-\d+.+(?!View\%20All)")}
{"href" : re.compile(r"^.+\/b-\d+.+(?!View\%20All$)")}

谁能告诉我我做错了什么?

【问题讨论】:

    标签: python regex regex-lookarounds


    【解决方案1】:
    {"href" : re.compile(r"\/b-\d+.+(?!View\%20All)")}
    {"href" : re.compile(r"^.+\/b-\d+.+(?!View\%20All$)")}
    

    你哪里错了?

    当我们给出(?!View\%20All) 时,它断言View\%20All 不能在前面的模式.+ 之后立即匹配

    实际上这意味着向前看总是正确的

    为了说明,让我们检查每个模式匹配的内容

    http://www.foo.com/bar/b-12312903?sName=View%20All

    /b- 很明显

    \d 匹配 12312903

    现在问题来了,

    .+ 匹配任何使得否定断言(?!View\%20All) 成功的东西。

    也就是说

    . 匹配 ?s 未匹配的字符串是 sName=View%20All 与开头位置的 (?!View\%20All) 不匹配 s因此总是成功匹配第 1 行和第 2 行

    demo 以获得清晰的图像。

    修复??

    当使用环视断言时,固定检查开始的位置

    说使用像这样的正则表达式

    (\/b-\d+)(\?|$)(?!sName=View\%20All)
    

    将匹配 3 和 4 作为

    http://regex101.com/r/aS5yS2/1

    字符串中的? 或$ 修复了否定断言开始的位置。

    【讨论】:

      【解决方案2】:
      ^.*?/b-\d+(?:(?!View%20All).)*$
      

      Demo

      或者更快

      ^.+?/b-\d+(?:[^V]+|V(?!iew%20All))*$
      

      【讨论】:

      • 我不明白为什么“。”最后还需要哇。那个演示很棒
      猜你喜欢
      • 1970-01-01
      • 2014-03-31
      • 1970-01-01
      • 2018-06-28
      • 1970-01-01
      • 2011-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多