【问题标题】:How to re.findall() using `daringfireball`'s regex?如何使用 `daringfireball` 的正则表达式 re.findall()?
【发布时间】:2013-09-10 09:03:21
【问题描述】:

我使用下面的代码使用daringfireball的正则表达式http://daringfireball.net/2010/07/improved_regex_for_matching_urls从html页面中提取url,即

(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s!()[]{};:'".,?«»“”'']))`

正则表达式的效果非常好,但使用re.findall() 几乎要花很长时间。无论如何,我可以快速获得 all html 中的网址吗?

import urllib, re

seed = "http://web.archive.org/web/20100412111652/http://app.singaporeedu.gov.sg/asp/index.asp"

page = urllib.urlopen(seed).read().decode('utf8')
#print page

pattern = r'''(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))'''

match = re.search(pattern,page)
print match.group(0)

matches = re.findall(pattern,page) # this line takes more than 3 mins on my i3 laptop
print matches

【问题讨论】:

    标签: python regex url web-crawler


    【解决方案1】:

    是的。根本不使用正则表达式。使用 HTML 解析器,例如 BeautifulSoup。这就是他们的目的。

    >>> from bs4 import BeautifulSoup as BS
    >>> import urllib2
    >>> seed = "http://web.archive.org/web/20100412111652/http://app.singaporeedu.gov.sg/asp/index.asp"
    >>> soup = BS(urllib2.urlopen(seed))
    >>> print soup.find_all('a')
    

    【讨论】:

    • 但是其他&lt;x&gt;...&lt;\x&gt;的网站会丢失。
    • @2er0 如果您愿意,可以搜索它们。我不确定您的预期输出是什么。您确实要求提供所有链接:p
    • 这有点野心,但它试图在一个 html 页面中找到所有可能的 url =)
    • @2er0 使用正则表达式的结果是什么?我会尝试复制它,但这可能很难
    • 实际上他的正则表达式似乎捕捉到的不仅仅是 url,还有很多噪音(非 url),但它似乎捕捉到了所有可能的 url。这是 20 多分钟,它仍在运行......我已经切换到这样做for line in page.split(): match = re.search(pattern,line) if match and "." in match.group(0): print match.group(0)
    【解决方案2】:

    你只想要一个页面中的所有 url 吗?像这样的简单正则表达式还不够吗?

    <a[^>]*href="([^"]+)"[^>]*>
    

    【讨论】:

    • 这将给出&lt;a href=...&gt;,文本中存在的url怎么样? &lt;a href&gt; 只在超链接中给出 url
    • @2er0 所有的网址都是以 http 还是 https 开头?所以你可以使用类似 (https?:\/\/[^\s"]+) 之类的东西。但更好的是对 url 中的所有有效字符使用完整的正则表达式,而不是我的简化 [^\s" ]。但我猜你现在已经解决了你的问题?
    猜你喜欢
    • 2021-09-30
    • 2012-02-18
    • 2023-03-25
    • 2012-06-19
    • 2020-05-16
    • 2014-10-27
    • 2018-10-12
    • 1970-01-01
    • 2017-08-27
    相关资源
    最近更新 更多