世界上最伟大的投资就是投资自己的教育
使用多线程和多进程来写爬虫
随风发布于3806 次阅读
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
完结。
更新:
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(URI.open("https://ruby-china.org/topics?page=#{page}"))
doc.css("div.topic").each do |node|
puts "#{node.css('> div.infos > div.title > a').first['title']} https://ruby-china.org#{node.css("> div.infos > div.title > a").first['href']}"
end
puts ""
rescue : e
puts "problem on page #{page}"
puts e.inspect
end
end
end
threads.each {|t| t.join}
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top
https 的网站 open 不能直接打开
<:ssl::sslerror: ssl_connect returned="1" errno="0" state="error:" certificate verify failed>