【问题标题】:Python regex: Difference between (.+) and (.+?)Python 正则表达式:(.+) 和 (.+?) 之间的区别
【发布时间】:2014-07-10 03:34:38
【问题描述】:

我是 regex 和 Python 的 urllib 的新手。我浏览了一个关于网络抓取的在线教程,它有以下代码。在研究了正则表达式之后,在我看来我可以在我的正则表达式中使用 (.+) 而不是 (.+?) ,但是我错了。我最终打印出比我想要的更多的 html 代码。我以为我掌握了正则表达式,但现在我很困惑。请向我解释这两个表达式之间的区别以及为什么它会抓取这么多的 html。谢谢!

ps。这是一个星巴克股票报价刮板。

import urllib
import re

url = urllib.urlopen("http://finance.yahoo.com/q?s=SBUX")
htmltext = url.read()
regex = re.compile('<span id="yfs_l84_sbux">(.+?)</span>')
found = re.findall(regex, htmltext)

找到打印件

【问题讨论】:

标签: python regex urllib


【解决方案1】:

.+ 是贪婪的——它匹配直到它无法匹配,并且只返回所需的数量。

.+? 不是——它一有机会就停下来。

例子:

假设你有这个 HTML:

<span id="yfs_l84_sbux">foo bar</span><span id="yfs_l84_sbux2">foo bar</span>

这个正则表达式匹配整个事情:

<span id="yfs_l84_sbux">(.+)<\/span>

它一直到最后,然后“返回”一个 &lt;/span&gt;,但其余的正则表达式匹配最后一个 &lt;/span&gt;,因此完整的正则表达式匹配整个 HTML 块。

但是这个正则表达式停在第一个&lt;/span&gt;:

<span id="yfs_l84_sbux">(.+?)<\/span>

【讨论】:

  • 你太棒了!易于理解的解释。也许你也可以向我解释一下。为什么在我的例子中,re.search 返回一个看起来很奇怪的字符串,而 re.findall 给了我我真正想要的数据?
  • 您可能会发现this answer 很有帮助。 findall 返回捕获的组列表,而 search 返回匹配的所有内容。在您的情况下,这包括 HTML 标签。我是 Python 的初学者,但我相信如果你从正则表达式中删除括号,你会从这两种方法中得到相同的结果。
【解决方案2】:

? 是一个非贪婪修饰符。 * 默认情况下是一个贪婪的重复操作符——它会吞噬它所能做的一切;当被? 修改时,它变得不贪婪,并且只会吃掉满足它的东西。

因此

<span id="yfs_l84_sbux">want</span>text<span id="somethingelse">dontwant</span>

.*?&lt;/span&gt; 将吃掉want,然后点击&lt;/span&gt; - 这满足了. 重复最少的正则表达式,导致&lt;span id="yfs_l84_sbux"&gt;want&lt;/span&gt; 成为匹配项。然而,.* 会尝试看看它是否能吃得更多——它会去寻找另一个 &lt;/span&gt;,其中 .*?want&lt;/span&gt;text&lt;span id="somethingelse"&gt;dontwant 匹配,从而得到你所得到的——比你想要的要多得多。

【讨论】:

  • *? OP实际上使用+
  • 多哈。嗯,同样的道理。
【解决方案3】:

(.+) 很贪心。它尽其所能,并在需要时回馈。

(.+?) 不贪心。尽可能少。

见:

delegate

[delegate] /^(.+)e/
[de]legate /^(.+?)e/

此外,比较“正则表达式调试器日志”herehere 将向您展示 ungreedy 修饰符更有效的作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-01
    • 2013-09-18
    • 2016-11-18
    • 2012-02-22
    • 2023-04-07
    • 1970-01-01
    • 2013-12-17
    • 1970-01-01
    相关资源
    最近更新 更多