我正在尝试使用ruby Thread处理给定URL数组的不同页面的内容。但是,当尝试打开URL时,我总是得到这样的错误:#<SocketError: getaddrinfo: Name or service not known>
这就是我想要做的:
sites.each do |site|
threads << Thread.new(site) do |url|
puts url
#web = open(url) { |i| i.read } # same issue opening the web this way
web = Net::HTTP.new(url, 443).get('/', nil)
lock.synchronize do
new_md5[sites_hash[url]] = Digest::MD5.hexdigest(web)
end
end
endsites是URL的数组。
同样的程序,但顺序运行良好:
sites.each { |site|
web = open(site) { |i| i.read }
new_md5 << Digest::MD5.hexdigest(web)
}有什么问题吗?
发布于 2014-12-06 02:54:07
呃。你要为你要处理的每个站点打开一个线程吗?如果你有10,000个站点呢?
相反,设置线程数量的限制,并将sites转换为Queue,并让每个线程删除一个站点,处理它并获得另一个站点。如果队列中没有更多的站点,则线程可以退出。
队列文档中的示例将帮助您入门。
不要使用get并总是检索整个正文,而是使用一个后台数据库来跟踪上次处理页面的时间。使用head检查页面自那以后是否已更新。如果有,则执行get。这将减少您和他们的带宽和CPU使用率。这一切都是关于成为一个好的网络公民,并友好地玩别人的玩具。如果你不好好玩,他们可能不会再让你和他们玩了。
我已经写了上百个爬虫和站点分析器。我建议你应该总是有一个备份数据库,并使用它来跟踪你将要阅读的网站,你最后一次阅读它们的时间,它们在你最后一次尝试获取页面时是否处于打开或关闭状态,以及你试图访问它们但它们关闭了多少次。(最后一个是这样你就不会把代码的头撞到墙上,试图到达死/停的站点。)
我有一个75线程的应用程序,可以阅读页面。每个线程将其查找结果写入数据库,如果需要处理某个页面,则将该HTML写入另一个表中的记录。然后,一个单独的应用程序读取该表并进行处理。对于一个单独的应用程序来说,保持75个线程的领先是很容易的,因为他们正在处理缓慢的互联网。
使用后端数据库的最大好处是,您的代码可以关闭,如果编写正确,它将在同一地点重新开始,即下一个要处理的站点。您也可以轻松地将其扩展为在多个主机上运行。
关于无法找到主机的问题:
我在你的代码中看到了一些东西:
这两种方法都可以解释为什么使用open可以工作,但是您的代码不能。(我假设您将OpenURI与单线程代码结合使用,尽管您没有显示它,因为open本身并不知道如何处理URL。)
一般来说,我建议使用Typhoeus and Hydra来并行处理大量站点。Typhoeus还将为您处理重定向,并允许您使用head请求。您还可以设置同时处理多少个请求(并发),并自动处理重复的请求(memoization),这样冗余的URL就不会受到冲击。
https://stackoverflow.com/questions/27322294
复制相似问题