【问题标题】:Improve URL reachable check改进 URL 可达性检查
【发布时间】:2015-01-27 06:59:00
【问题描述】:

我目前正在针对多个 Web 服务器运行 python 脚本。一般任务是找出 cms 内的损坏(外部)链接。到目前为止,脚本运行得很好,但我测试了大约 50 个内部项目,每个项目都有数百个子页面。这以我必须检查的数千个外部链接结束。

出于这个原因,我添加了多线程 - 按照我的意愿提高性能。但问题来了。如果要检查的页面包含指向同一服务器的链接列表(已知问题或要执行的任务的捆绑),它将减慢目标系统的速度。我既不想减慢我自己的服务器,也不想减慢不是我的服务器。

目前我运行最多 20 个线程比等待 0.5 秒,直到“线程位置”准备好使用。为了检查一个 URL 是否损坏,我处理来自 urllib2log 的 urlopen(request) 每次它抛出一个 HTTPError。返回到同一服务器的多个 URL 列表...我的脚本将“淹没”网络服务器 - 由于多线程 - 最多 20 个同时请求。

只是您知道此脚本在哪些维度上运行/URL 必须检查:仅使用 20 个线程会使当前脚本“减慢”仅 4 个项目的运行时间至 45 分钟。这只是检查 .. 下一步将检查损坏的 URL 是否存在 .使用当前脚本向我们展示了服务器监控中响应时间为 1000 毫秒的峰值。

大家都知道如何改进这个脚本吗?或者有没有更好的方法来检查这么多的 URL?如果有 10 个对单个目的地的请求,也许一个计数器会暂​​停线程?

感谢所有建议

【问题讨论】:

  • 您是否以HEAD 开头告诉服务器您只需要状态而不是内容?

标签: python multithreading url urlopen


【解决方案1】:

当我运行爬虫时,我的所有 URL 都按域名优先。基本上,我要抓取的 URL 队列实际上是一个域名队列,每个域名都有一个 URL 列表。

当需要获取下一个要抓取的 URL 时,线程会从队列中提取一个域名并抓取该域列表中的下一个 URL。处理完该 URL 后,线程会将域放在延迟列表中,并从延迟列表中删除延迟已过期的所有域。

延迟列表是一个按过期时间排序的优先级队列。这样我就可以为每个域提供不同的延迟时间。这使我能够支持 robots.txt 的 crawl-delay 扩展。有些域可以让我每秒访问一次他们的服务器。其他人希望请求之间延迟一分钟。

通过这种设置,我从来没有同时使用多个线程访问同一个域,而且我访问它们的频率从来没有超过他们的要求。我的默认延迟大约是 5 秒。这看起来很多,但我的爬虫正在查看数百万个域,所以它从不希望抓取东西。您可能可以减少默认延迟。

如果您不想按域名对 URL 进行排队,您可以做的是维护一个列表(可能是哈希表或 python 等价物),其中包含当前正在被抓取的域名。当您将 URL 出列时,您会根据哈希表检查域,如果域当前正在使用中,则将 URL 放回队列中。比如:

goodUrl = false
while (!goodUrl)
    url = urlqueue.Dequeue();
    lock domainsInUse
        if domainsInUse.Contains(url.domainName)
            urlqueue.Add(url)  // put it back at the end of the queue
        else
            domainsInUse.Add(url.domainName)  
            goodUrl = true

这会起作用,尽管如果队列包含来自同一域的大量 URL,这将是一个很大的 CPU 猪。例如,如果您有 20 个线程并且队列中仅表示 5 个不同的域,那么平均有 15 个线程会持续旋转,寻找要抓取的 URL。

【讨论】:

  • 听起来很聪明。我会试一试:)
【解决方案2】:

如果您只想要状态,请发出 HEAD 请求而不是 urlopen。这将大大减少服务器上的负载。当然还要限制同时请求的数量。

import httplib
from urlparse import urlparse

def is_up(url):
    _, host, path, _, _, _ = urlparse(url)
    conn = httplib.HTTPConnection(host)
    conn.request('HEAD', path)
    return conn.getresponse().status < 400

【讨论】:

  • 您会惊讶于有多少网站不支持 HEAD 请求。
猜你喜欢
  • 2010-12-24
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多