首页ruby
hfpp2012

使用多线程和多进程来写爬虫

hfpp2012发布于

1. 爬虫

为了提高处理和运算速度,或者充分利用cpu的计算和处理能力,需要使用多线程编程。

我们要把ruby-china.org上每篇贴子的标题和回复的数量,用爬虫爬下来。

我们用ruby代码来实现。

require 'open-uri'
require 'nokogiri'

(1..50).each do |page|
  begin
    puts "page - #{page}"
    doc = Nokogiri::HTML(open("https://ruby-china.org/topics?page=#{page}"))
    doc.css("div.topic").each do |node|
      puts "#{node.css('> div.infos > div.title > a').text} #{node.css("> div.count > a").text}"
    end
    puts ""
  rescue => e
    puts "problem on page #{page}"
    puts e.inspect
  end
end

运行时间:

real    0m30.906s
user    0m2.212s
sys     0m0.279s

2. 用多线程实现

上面的代码效果太低效,我们改用多性程来编写。

我们访问的是50页,那就开50个线程,每页一个线程。

require 'open-uri'
require 'nokogiri'
require 'thread'

threads = (1..50).map do |page|
  Thread.new(page) do |page|
    begin
      puts "page - #{page}"
      doc = Nokogiri::HTML(open("https://ruby-china.org/topics?page=#{page}"))
      doc.css("div.topic").each do |node|
        puts "#{node.css('> div.infos > div.title > a').text} #{node.css("> div.count > a").text}"
      end
      puts ""
    rescue => e
      puts "problem on page #{page}"
      puts e.inspect
    end
  end
end
threads.each {|t| t.join}

时间输出:

real    0m4.610s
user    0m1.480s
sys     0m0.279s

3. 使用线程安全的数据结构保证同步

用ruby中唯一的线程安全的数据结构Queue来保证线程同步。

require 'open-uri'
require 'nokogiri'
require 'thread'

work_q = Queue.new

(1..50).each{|page| work_q << page}

workers = (0...10).map do
  Thread.new do
    begin
      while page = work_q.pop(true)      
        begin
          puts "page - #{page}"
          doc = Nokogiri::HTML(open("https://ruby-china.org/topics?page=#{page}"))
          doc.css("div.topic").each do |node|
            puts "#{node.css('> div.infos > div.title > a').text} #{node.css("> div.count > a").text}"
          end
        rescue => e
          puts "problem on page #{page}"
          puts e.inspect
        end
      end # while
      puts ""
    rescue ThreadError
    end
  end
end
workers.map(&:join)
real    0m5.983s
user    0m1.753s
sys     0m0.357s

使用的时间(6s)比不用线程的情况(30s)缩短了几倍。

4. 使用多进程来实现

parallel这个库可以轻易地开多个进程。

require 'parallel'
require 'open-uri'
require 'nokogiri'

Parallel.map(1..50, in_processes: 10) do |page|
  begin
    puts "page - #{page}"
    doc = Nokogiri::HTML(open("https://ruby-china.org/topics?page=#{page}"))
    doc.css("div.topic").each do |node|
      puts "#{node.css('> div.infos > div.title > a').text} #{node.css("> div.count > a").text}"
    end
    puts ""
  rescue => e
    puts "problem on page #{page}"
    puts e.inspect
  end
end

时间输出:

real    0m4.767s
user    0m1.856s
sys     0m0.360s

完结。

本站帖子均为原创内容,如需转载请注明出处,谢谢。

1 条回复
喜欢
友情提示
   官方 QQ 1 群 697272886(500/2000)
   官方 QQ 2 群 856141852

© Rails365 | 隐私条款 | 服务条款 | 粤ICP备15004902号 | 在线学员:17

Top