改进URL可访问检查

时间:2014-11-28 15:23:05

标签: python multithreading url urlopen

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

出于这个原因,我添加了多线程 - 提高了性能,因为这是我的愿望。但问题来了。如果有一个要检查的页面,其中包含指向同一服务器的链接列表(要处理的已知问题或任务的捆绑),则会降低目标系统的速度。我既不想放慢我自己的服务器,也不想减慢我的服务器。

目前我运行最多20个主题而不是等待0.5s 直到"主题位置"准备好了。要检查网址是否损坏,我每次抛出 HTTPError 时都会处理来自 urllib2 日志的urlopen(请求)。回到同一服务器的多个URL列表...我的脚本将" flood"具有多线程原因的Web服务器 - 最多20个同时请求。

只是你知道这个脚本运行的维度/ URL必须检查:只使用20个线程"减慢"将当前脚本仅用于4个项目到45分钟的运行时间。这只是检查..下一步将检查损坏的URL。使用当前脚本向我们显示服务器监视中的一些峰值,响应时间为1000毫秒。

每个人都知道如何改进这个脚本吗?或者有更好的方法来检查这么多的URL?如果有10个请求到一个目的地,可能是一个暂停线程的计数器?

感谢所有建议

2 个答案:

答案 0 :(得分:0)

如果您只想让状态发出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

答案 1 :(得分:0)

当我运行抓取工具时,我的所有网址都按域名划分优先级。基本上,我要抓取的URL队列实际上是一个域名队列,每个域名都有一个URL列表。

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

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

通过这种设置,我永远不会同时使用多个线程打到同一个域,而且我从来没有比他们请求的更频繁地命中它们。我的默认延迟是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。