与Ruby同时处理网页

时间:2014-12-05 18:21:48

标签: ruby concurrency parallel-processing

我正在尝试使用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)
}

有什么问题?

1 个答案:

答案 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就不会被篡改。