Ruby 刚学 Ruby 想问一下怎么改代码能提升一下程序运行速度实在是太慢了。

regnskali · 2022年03月24日 · 最后由 lehug 回复于 2022年04月14日 · 1259 次阅读
require 'net/http'
require 'nokogiri'
require 'benchmark'

begin_time = Time.now
uri = URI('http://www2.kugou.kugou.com/yueku/v8/album/index/getData.js')
referrer_policy="http://www2.kugou.kugou.com"
number = 1
(1..200).each { |i|
  params = { :cdn => "cdn", :l => 1, :p => i, :c => 0 }
  uri.query = URI.encode_www_form(params)
  res = Net::HTTP.get_response(uri)
  parsed_data = Nokogiri::HTML.parse(res.body)
  if parsed_data.xpath("/html/body//ul//li//a[@class='pic']/@title[1]")[0]==nil then puts "暂无"; break end
  title_name = parsed_data.xpath("/html/body//ul//li//a[@class='pic']/@title[1]")
  title_name_url = parsed_data.xpath("/html/body//ul//li//a[@class='pic']/@href ")
  (0..title_name_url.length - 1).each { |i|
    puts "ID:#{number}"
    puts title_name[i]
    puts Nokogiri::HTML.parse(Net::HTTP.get(URI(referrer_policy + title_name_url[i]))).xpath("/html/body//div[@class='intro']//tr//td/a[@onclick=\"LogStat(1,'','演唱者点击量');\"]/text()")
    puts Nokogiri::HTML.parse(Net::HTTP.get(URI(referrer_policy + title_name_url[i]))).xpath("/html/body//div[@class='intro']//tr//td[@id='language']/text()")
    puts Nokogiri::HTML.parse(Net::HTTP.get(URI(referrer_policy + title_name_url[i]))).xpath("/html/body//div[@class='intro']//tr//td[@id='company']/text()")
    puts Nokogiri::HTML.parse(Net::HTTP.get(URI(referrer_policy + title_name_url[i]))).xpath("/html/body//div[@class='intro']//tr//td[@id='publish_time']/text()")
    number=number+1
    puts "--------------------------"
 }
}
end_time = Time.now
puts "Time taken is #{end_time - begin_time}."

爬虫慢主要是 http 响应速度问题。

用线程会快,然而太快话会被对方识别、屏蔽和投毒。

搞爬虫的话直接上框架产品吧,异步、重连、更新内容、代理配置,都现成的。自己开发没必要。

请问 Ruby 用什么框架比较好

regnskali 回复

可以试试 Sidekiq 简单易上手,变成异步任务执行,任务之间就不用互相等待。

这开些线程,或进程,能提高几十倍的速度,再换个请求库,加 xml 解决的库,又能提高几十倍

爬虫可以用 https://github.com/sparklemotion/mechanize,使用起来比较方便

试试使用基于 Ruby 3 新特性的 Fiber 调度器 https://github.com/bruno-/fiber_scheduler

require 'fiber_scheduler'
require 'net/http'
require 'nokogiri'
require 'benchmark'

Fiber.set_scheduler(FiberScheduler.new)

begin_time = Time.now
uri = URI('http://www2.kugou.kugou.com/yueku/v8/album/index/getData.js')
referrer_policy="http://www2.kugou.kugou.com"
number = 1

(1..200).each do |i|
    Fiber.schedule do
        params = { :cdn => "cdn", :l => 1, :p => i, :c => 0 }
        uri.query = URI.encode_www_form(params)
        res = Net::HTTP.get_response(uri)
        puts res.body
    end
end

end_time = Time.now
puts "Time taken is #{end_time - begin_time}."

ruby 内置的多线程,虽然不是真正的多线程,但是能提高爬虫数倍

haohaodehao 回复

ruby 内置的线程怎么就不是真正的线程?那是很久以前的 Ruby 吧

和语音无关,针对这个场景,该考虑到多线程的并行执行

需要 登录 后方可回复, 如果你还没有账号请 注册新账号