【问题标题】:Regex quantifiers正则表达式量词
【发布时间】:2014-03-29 22:54:56
【问题描述】:

我是正则表达式的新手,这让我很困惑。

在下面的例子中,我想提取facebook.com/pages/Dr-Morris-Westfried-Dermatologist/176363502456825?id=176363502456825&sk=info。我已经阅读了惰性量词和lookbehinds,但我仍然无法拼凑出正确的正则表达式。我希望facebook.com\/.*?sk=info 能够工作,但它捕获的太多了。你们能帮忙吗?

<i class="mrs fbProfileBylineIcon img sp_2p7iu7 sx_96df30"></i></span><span class="fbProfileBylineLabel"><span itemprop="address" itemscope="itemscope" itemtype="http://schema.org/PostalAddress"><a href="https://www.facebook.com/pages/Dr-Morris-Westfried-Dermatologist/176363502456825?sk=page_map" target="_self">7508 15th Avenue, Brooklyn, New York 11228</a></span></span></span><span class="fbProfileBylineFragment"><span class="fbProfileBylineIconContainer"><i class="mrs fbProfileBylineIcon img sp_2p7iu7 sx_9f18df"></i></span><span class="fbProfileBylineLabel"><span itemprop="telephone">(718) 837-9004</span></span></span></div></div></div><a class="title" href="https://www.facebook.com/pages/Dr-Morris-Westfried-Dermatologist/176363502456825?id=176363502456825&amp;sk=info" aria-label="About Dr. Morris Westfried - Dermatologist">

【问题讨论】:

标签: python regex reluctant-quantifiers


【解决方案1】:

尽管我很喜欢正则表达式,但这是一个 html 解析任务:

>>> from bs4 import BeautifulSoup
>>> html = .... # that whole text in the question
>>> soup = BeautifulSoup(html)
>>> pred = lambda tag: tag.attrs['href'].endswith('sk=info')
>>> [tag.attrs['href'] for tag in filter(pred, soup.find_all('a'))]
['https://www.facebook.com/pages/Dr-Morris-Westfried-Dermatologist/176363502456825?id=176363502456825&sk=info']

【讨论】:

  • 这可能是一种更好的方法,但是,这并不能解释为什么该模式不起作用。
  • @CasimiretHippolyte 问题是“我想提取...”;这就是上面所做的。此外,this 可能是相关的。
  • @CasimiretHippolyte -- 非常感谢正则表达式的解释。我确实将 BeautifulSoup 用于类似的任务
【解决方案2】:

这行得通:)

facebook\.com\/[^>]*?sk=info

Debuggex Demo

只有.* 它会找到第一个 facebook.com,然后继续直到sk=info。由于之间还有另一个facebook.com,因此您将它们重叠。

想要的唯一的东西是&gt;(或&lt;,以及其他字符),所以将anything更改为除了&gt; 之外的任何东西都可以根据需要找到最接近sk=infofacebook.com

是的,对 HTML 使用正则表达式应该只用于基本任务。否则,请使用解析器。

【讨论】:

  • 去调试。有用。 ? 可能不是必需的,但它可以工作。它是[^&gt;]*? 的一部分,这意味着零个或多个而不是&gt; 字符,可能。它不是普通的?,它是所有格修饰语。
  • 还不错;这是不情愿的,不是占有欲的,而是使用它的荣誉。 :)
  • “不情愿”。对。不是所有格。
  • 您建议?sk=info 中的问号实际上是网址的一部分。它不是。这是;sk=info。问号只是为了让前面的正则表达式 ([^&gt;]*) 不情愿。
【解决方案3】:

为什么你的模式不起作用:

您的模式不起作用,因为正则表达式引擎会在字符串中从左到右尝试您的模式。

当正则表达式引擎遇到字符串中的第一个facebook.com\/,并且由于您在之后使用.*?,正则表达式引擎会将所有字符(包括"&gt;)添加到(可能的)匹配结果中或空格)直到找到sk=info(因为. 可以匹配除换行符以外的任何字符)。

这就是为什么 fejese 建议将点替换为 [^"] 或 aliteralmind 建议将其替换为 [^&gt;] 以使模式在字符串中的该位置(第一个)失败。

如果您想处理 html,使用 html 解析器是最简单的方法。但是,对于一次匹配或搜索/替换,请注意,如果 html 解析器提供安全性、简单性,那么它会在性能方面付出代价,因为您需要为单个任务加载文档的整个树。

【讨论】:

    【解决方案4】:

    问题是您有另一个 facebook.com 部分。您可以限制 .* 不匹配 " 所以它需要保持在一个属性内:

    facebook\.com\/[^"]*;sk=info
    

    【讨论】:

    • 用字面问号,是不行的。阅读我的答案下的 cmets。
    猜你喜欢
    • 2013-12-05
    • 2011-10-12
    • 2012-01-23
    • 2016-03-20
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多