我正在用Ruby编写一个应用程序,它可以从超过10000页的站点中搜索和获取数据。我使用OpenURI和Nokogiri来打开和解析网页以从中获取数据并将它们保存到本地数据文件中::
#An example
page = Nokogiri::HTML(open("http://example.com/books/title001.html"))
#Get title, author, synopsys, etc from that page
对于拥有ADSL连接的人来说,打开一个页面平均需要1秒钟。因为该网站有大约10000页,所以打开所有页面并获取所有书籍的数据需要3个多小时,这个应用程序的时间是不可接受的,因为我的用户不想等待那么多时间。
如何使用OpenURI和Nokogiri快速有效地打开和解析大量网页?
如果我不能和他们一起做,我该怎么办?一些漫画下载者只需要花费5-10分钟来完成大型漫画网站(大约10000个标题),那些做同样工作的应用程序(列出书籍,从页面获取所有数据并保存到文件中)如何才能花费5-10分钟? / p>
答案 0 :(得分:1)
不要先使用OpenURI;如果您使用Hydra and Typhoeus,则有更好的方法。
像具有100个蛇头的神话兽的现代代码版本一样,Typhoeus并行运行HTTP请求,同时干净地封装处理逻辑。
...
并行请求:
hydra = Typhoeus::Hydra.new 10.times.map{ hydra.queue(Typhoeus::Request.new("www.example.com", followlocation: true)) } hydra.run
文档中的更远......
如何在执行队列后获取一组响应:
hydra = Typhoeus::Hydra.new requests = 10.times.map { request = Typhoeus::Request.new("www.example.com", followlocation: true) hydra.queue(request) request } hydra.run
responses = request.map { |request|
request.response.response_body
}
request.response.response_body
是您要用Nokogiri解析器包装的行:
Nokogiri::HTML(request.response.response_body)
此时,您将拥有一系列DOM来完成并处理。
但是等等!还有更多!
因为你想要节省一些处理时间,你需要设置一个线程和队列,推送解析的DOM(或者只是未解析的HTML response_body
),然后让线程处理并写入文件。
这并不难,但是开始将问题超出Stack Overflow的范围,因为它变成了一本小书。阅读Thread和Queue文档,尤其是关于生产者和消费者的部分,您应该能够将它拼凑在一起。这来自ri Queue
文档:
= Queue < Object
(from ruby core)
------------------------------------------------------------------------------
This class provides a way to synchronize communication between threads.
Example:
require 'thread'
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
------------------------------------------------------------------------------
= Class methods:
new
= Instance methods:
<<, clear, deq, empty?, enq, length, num_waiting, pop, push, shift, size
我用它来并行处理大量的URL,并且很容易设置和使用。使用Threads做所有事情是可能的,而不是使用Typhoeus,但我认为捎带现有的,写得很好的工具比尝试自己动作更明智。
...一些漫画下载者只需要花费5-10分钟来完成大型漫画网站的工作(如何做同样的工作(列出书籍,从页面获取所有数据并保存到文件))(约10000个标题)?
他们有:
处理那么多页面并不难,你只需要对你的资源保持现实,并使用明智的用途。
我的建议是什么?
答案 1 :(得分:0)
相对而言,在执行http请求时会有很多等待,这是多线程/进程的一个很好的用例。您可以创建一个工作线程/进程池,从一个队列中检索请求数据,然后将结果推送到您的主线程可以读取的另一个队列中。
见这里:https://blog.engineyard.com/2014/ruby-thread-pool
一些应用程序如何工作(列出书籍,全部获取 来自页面的数据并保存到文件中),例如一些漫画下载程序 大型漫画网站(大约10000个)只需5-10分钟即可完成 标题)?
计算能力。如果您拥有10,000台核心计算机(或10,000台计算机,每台计算机只有一个核心),您可以为每个请求启动一个进程,然后所有请求将同时执行。完成所有请求的总时间将是完成最长请求所花费的时间 - 而不是所有请求的所有时间的总和。