首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与Ruby并发处理网页

与Ruby并发处理网页
EN

Stack Overflow用户
提问于 2014-12-06 02:21:48
回答 1查看 38关注 0票数 0

我正在尝试使用ruby Thread处理给定URL数组的不同页面的内容。但是,当尝试打开URL时,我总是得到这样的错误:#<SocketError: getaddrinfo: Name or service not known>

这就是我想要做的:

代码语言:javascript
复制
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是URL的数组。

同样的程序,但顺序运行良好:

代码语言:javascript
复制
sites.each { |site|
    web = open(site) { |i| i.read }
    new_md5 << Digest::MD5.hexdigest(web)
}

有什么问题吗?

EN

回答 1

Stack Overflow用户

发布于 2014-12-06 02:54:07

呃。你要为你要处理的每个站点打开一个线程吗?如果你有10,000个站点呢?

相反,设置线程数量的限制,并将sites转换为Queue,并让每个线程删除一个站点,处理它并获得另一个站点。如果队列中没有更多的站点,则线程可以退出。

队列文档中的示例将帮助您入门。

不要使用get并总是检索整个正文,而是使用一个后台数据库来跟踪上次处理页面的时间。使用head检查页面自那以后是否已更新。如果有,则执行get。这将减少您和他们的带宽和CPU使用率。这一切都是关于成为一个好的网络公民,并友好地玩别人的玩具。如果你不好好玩,他们可能不会再让你和他们玩了。

我已经写了上百个爬虫和站点分析器。我建议你应该总是有一个备份数据库,并使用它来跟踪你将要阅读的网站,你最后一次阅读它们的时间,它们在你最后一次尝试获取页面时是否处于打开或关闭状态,以及你试图访问它们但它们关闭了多少次。(最后一个是这样你就不会把代码的头撞到墙上,试图到达死/停的站点。)

我有一个75线程的应用程序,可以阅读页面。每个线程将其查找结果写入数据库,如果需要处理某个页面,则将该HTML写入另一个表中的记录。然后,一个单独的应用程序读取该表并进行处理。对于一个单独的应用程序来说,保持75个线程的领先是很容易的,因为他们正在处理缓慢的互联网。

使用后端数据库的最大好处是,您的代码可以关闭,如果编写正确,它将在同一地点重新开始,即下一个要处理的站点。您也可以轻松地将其扩展为在多个主机上运行。

关于无法找到主机的问题:

我在你的代码中看到了一些东西:

  • 你不是在处理重定向。
  • 请求是发送到端口443,而不是80,所以Net::HTTP不会乐意尝试使用非Following Redirection到SSL端口中。请参阅"Using Net::HTTP.get for an https url",其中讨论了如何打开SSL。

这两种方法都可以解释为什么使用open可以工作,但是您的代码不能。(我假设您将OpenURI与单线程代码结合使用,尽管您没有显示它,因为open本身并不知道如何处理URL。)

一般来说,我建议使用Typhoeus and Hydra来并行处理大量站点。Typhoeus还将为您处理重定向,并允许您使用head请求。您还可以设置同时处理多少个请求(并发),并自动处理重复的请求(memoization),这样冗余的URL就不会受到冲击。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27322294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档