【问题标题】:What's the fastest way to test the validity of a large number of well-formed URLs测试大量格式正确的 URL 有效性的最快方法是什么
【发布时间】:2010-10-08 11:34:26
【问题描述】:

我的项目需要我验证大量的 Web URL。这些 URL 是由我无法控制的非常不可靠的过程捕获的。所有 URL 都已经过正则表达式验证,并且已知格式正确。我也知道他们都有有效的 TLD

我希望能够快速过滤这些 URL,以确定其中哪些是不正确的。在这一点上,我不在乎页面上有什么内容 - 我只想尽快知道哪些页面无法访问(例如,产生 404 错误)。

鉴于其中有很多我不想下载整个页面,只是HTTP头然后从头的内容中很好地猜测该页面是否可能存在。

可以吗?

【问题讨论】:

  • 请注意,这类问题不需要是社区 wiki。 CW 用于更多讨论的问题。如果您的理想答案是代码,就像这里的情况一样,您不必将其设为 wiki。

标签: python http


【解决方案1】:

执行类似工作的 Python 程序(对于存储在 del.icio.us 的 URL 列表)是 disastrous

而且,是的,它使用 HEAD 而不是 GET,但请注意一些(不是 HTTP 标准)服务器为 HEAD 和 GET 发送不同的结果:Python 环境 Zope 是典型的罪魁祸首。(此外,在某些情况下,网络问题,例如阻止 ICMP 的隧道 + 损坏的防火墙,阻止大数据包通过,因此 HEAD 工作而不是 GET。)

【讨论】:

    【解决方案2】:

    这可能会帮助您开始。文件 sitelist.txt 包含一个 URI 列表。您可能必须安装 httplib2,强烈推荐。我在每个请求之间设置了一个睡眠,因此如果您在同一个站点上有多个 URI,您的客户端将不会因滥用资源而被列入黑名单。

       import httplib2
       import time
    
       h = httplib2.Http(".cache")
    
       f = open("sitelist.txt", "r")
       urllist = f.readlines()
       f.close()
    
       for url in urllist:
          # wait 10 seconds before the next request - be nice with the site
          time.sleep(10)
          resp= {}
          urlrequest = url.strip()
          try:
             resp, content = h.request(urlrequest, "HEAD")
             if resp['status'] == "200":
                print url, "200 - Good"
             else:
                print url, resp['status'], " you might want to double check"
          except:
             pass
    

    【讨论】:

      【解决方案3】:

      这是twisted 的一个小例子。您可以使用一些并发工具来减慢它的速度,否则,它几乎会一次完成所有操作。

      Twisted 绝对是我最喜欢 python 的地方。 :)

      【讨论】:

        【解决方案4】:

        使用httpliburlparse

        def checkURL(url):
            import httplib
            import urlparse
        
            protocol, host, path, query, fragment = urlparse.urlsplit(url)
        
            if protocol == "http":
                conntype = httplib.HTTPConnection
            elif protocol == "https":
                conntype = httplib.HTTPSConnection
            else:
                raise ValueError("unsupported protocol: " + protocol)
        
            conn = conntype(host)
            conn.request("HEAD", path)
            resp = conn.getresponse()
            conn.close()
        
            if resp.status < 400:
                return true
        
            return false
        

        【讨论】:

          【解决方案5】:

          您可以尝试发送 HTTP HEAD 请求,而不是为每个 URL 发送 HTTP GET 请求。它们在this document 中进行了描述。

          【讨论】:

            【解决方案6】:

            要真正做到这一点,您还可以使用eventlet,它使用非阻塞 IO 来加快速度。

            你可以使用这样的头部请求:

            from eventlet import httpc
            try:
                res = httpc.head(url)
            except httpc.NotFound:
                # handle 404
            

            然后您可以将其放入一些简单的脚本中,例如that example script here。这样,您应该可以通过使用协程池获得相当多的并发性。

            【讨论】:

            • 谢谢 MrTopf - 嘿记得我...我们是在 Plone conf 上认识的,还是多年前的 pycon?谢谢。
            • 是的,我记得你,很可能是在哥德堡的 EuroPython。我想我们也曾在某个时候在伦敦见过面。希望它对你有用:-)
            • 那么这实际上是被 2ndlife 使用的吗?你现在是那家公司的员工吗?是的——那是哥德堡! :-)
            • 是的,它被用于第二人生,并在那里进一步发展。与此同时,多诺万离开了林登实验室,并正在独自研究。不,我不是 LL 员工,但我与他们一起致力于标准化虚拟世界协议。
            • 重定向的处理可能值得一提。
            【解决方案7】:

            我假设您想根据您的标签在 Python 中执行此操作。在这种情况下,我会使用 httplib。或者,以某种方式按主机对 URL 进行分组,以便您可以在一个连接中为具有相同主机的那些 URL 发出多个请求。使用 HEAD 请求。

            conn = httplib.HTTPConnection("example.com")
            conn.request("HEAD", "/index.html")
            resp = conn.getresponse()
            print resp.status
            

            【讨论】:

              【解决方案8】:

              只需将 HTTP HEAD 请求发送到this question 接受的答案中。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-12-14
                • 1970-01-01
                • 2012-12-31
                • 1970-01-01
                • 2012-05-29
                • 1970-01-01
                • 2019-06-13
                相关资源
                最近更新 更多