2014-12-05 61 views
0

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

这是我正在试图做到这一点:

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的数组。

同样的程序,但连续的作品好吗:

sites.each { |site| 
    web = open(site) { |i| i.read } 
    new_md5 << Digest::MD5.hexdigest(web) 
} 

什么问题?

+1

呃。你打算为每个你必须处理的网站打开一个线程?如果你有10,000个网站呢?设置线程数量的限制,并将'sites'变成队列,并让每个线程删除一个站点,处理它并获得另一个站点。如果队列中没有更多站点,则该线程可以退出。 – 2014-12-05 18:43:15

+0

我有java中的并发经验,这里列表只有5个线程......我只想知道为什么我在打开web时遇到这个问题 – dabadaba 2014-12-05 18:44:53

+0

Ruby的哪个版本? – 2014-12-05 19:05:24

回答

2

呃。你打算为每个你必须处理的网站打开一个线程?如果你有10,000个网站呢?

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

Queue文档中的示例将帮助您开始。

而不是使用get始终检索整个正文,使用后备数据库跟踪上次处理页面的时间。使用head来检查页面是否自此更新。如果有,然后做一个get。这将减少您的带宽和CPU使用率。这就是成为一名优秀的网络公民,并与其他人的玩具相处融洽。如果你打得不好,他们可能不会让你和他们一起玩。

我写过数百个蜘蛛和站点分析器。我建议你应该总是有一个支持数据库,并使用它来跟踪你将要阅读的网站,当你最后一次阅读它们时,如果你最后一次尝试获得一个页面时,它们是上或下,以及你试过多少次到达他们,但他们都失败了。 (最后是这样,你不会在墙上试图访问死/停的网站上敲你的代码的头。)

我有一个75线程的应用程序,可以读取页面。每个线程将他们的发现写入数据库,并且,如果需要处理页面,则该HTML被写入另一个表中的记录。然后一个应用程序读取该表并进行处理。单个应用程序很容易在75个线程之前保持领先,因为它们正在处理缓慢的互联网。

使用后端数据库的一大优势是您的代码可以关闭,并且如果您正确编写,它将在同一地点,下一个要处理的站点中选取。您也可以将它扩展为在多个主机上轻松运行。


对于不能够找到主机:

有些事情,我在你的代码中看到:

其中之一可以解释为什么使用open的作品,但你的代码没有。 (我假设你在你的单线程代码结合使用OpenURI尽管你不表现出来,因为open本身并不知道如何处理一个URL做。)


在一般来说,我建议使用Typhoeus and Hydra来并行处理大量网站。 Typhoeus也会为您处理重定向,并允许您使用head请求。您还可以设置同时处理多少个请求(并发)并自动处理重复的请求(备忘录),因此冗余URL不会被捣毁。