我正在尝试使用ruby Thread
处理给定一系列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
end
sites
是网址数组。
相同的程序,但顺序工作正常:
sites.each { |site|
web = open(site) { |i| i.read }
new_md5 << Digest::MD5.hexdigest(web)
}
有什么问题?
答案 0 :(得分:2)
唉。您要为每个必须处理的站点打开一个帖子吗?如果您有10,000个站点怎么办?
相反,设置线程数限制,并将sites
转换为Queue,让每个线程删除一个站点,处理它并获取另一个站点。如果队列中没有其他站点,则线程可以退出。
Queue文档中的示例将帮助您入门。
使用后备数据库来跟踪上次处理页面的时间,而不是使用get
和总是检索整个正文。使用head
检查页面是否已更新。如果有,则然后执行get
。这将减少您及其带宽和CPU使用率。这一切都是为了成为一个优秀的网络公民,并与其他人的玩具玩得很好。如果你不好玩,他们可能不会再让你玩了。
我写了数百个蜘蛛和网站分析器。我建议您应该始终拥有一个支持数据库,并使用它来跟踪您将要阅读的网站,上次阅读时的网站,上次尝试获取网页时是否上升或下降,以及你有多少次试图联系他们而且他们失败了。 (最后一个是你不要把你的代码头撞到墙上试图到达死亡/下降的网站。)
我有一个75线程的应用程序读取页面。每个线程都将他们的发现写入数据库,如果需要处理页面,则将HTML写入另一个表中的记录。然后,一个应用程序读取该表并进行处理。单个应用程序很容易保持领先75个线程,因为他们正在处理慢速互联网。
使用后端数据库的一大优势是,您的代码可以关闭,并且如果您正确编写它,它将在同一位置接收,即下一个要处理的站点。您可以将其扩展为在多个主机上轻松运行。
关于无法找到主持人:
我在您的代码中看到的一些内容:
其中任何一个都可以解释为什么使用open
有效但你的代码没有。 (我假设你将OpenURI与你的单线程代码一起使用,虽然你没有显示它,因为open
本身并不知道如何处理URL。)
一般情况下,我建议使用Typhoeus and Hydra并行处理大量网站。 Typhoeus也会为您处理重定向,同时允许您使用head
个请求。您还可以设置同时处理多少请求(并发)并自动处理重复请求(memoization),这样冗余的URL就不会被篡改。