Parallelで簡単にRubyで並列処理

  • Pocket
  • このエントリーをはてなブックマークに追加
  • 164 follow us in feedly

まえがき

Rubyで簡単に並列処理ができるパッケージ『Parallel』を使って遊んでみたのでメモ。

今回単純なプログラムだけど処理速度がかなり上がったので感動です。

開発環境

  • Ruby 1.9.3
  • gem 1.8.23
  • Parallel 0.8.4

Parallelのインストール

gemでインストールします

sudo gem install parallel

# 確認
gem list parallel

Parallelの基本的な書き方

こんな感じ

require 'parallel'

# :in_threds => スレッド数
Parallel.each(lists, in_threds: 2) do |list|
  # 処理
end

んーとても簡単

サンプル

今回のサンプルは以前にNokogiriでお寿司のメニューを取得してきたコードに少し変更を加えて、メニューの画像ファイルをダウンロードしてくるプログラム。

以前のNokogiriサンプルコードというのはこれ↓

RubyのNokogiriでギコギコスクレイピングだ

RubyのNokogiriでギコギコスクレイピングだ

なお、相対パス指定によって画像がダウンロードできないものがいくつかあるのは目を瞑る。1割ぐらいが相対パスだった。

非並列処理バージョン

# coding: utf-8

t0 = Time.now

require 'yaml'
require 'nokogiri'
require 'open-uri'
require 'term/ansicolor'
include Term::ANSIColor

def save_file(url)
  filedir = File.expand_path(File.dirname(__FILE__)) + "/images/"
  FileUtils.mkdir_p(filedir) unless FileTest.exist?(filedir)
  begin
    filename = filedir << File.basename(url)
    open(filename, 'w+b') do |file|
      open(url) do |data|
        file.write data.read
      end
    end
  rescue
    print red + "Download Error #{url}" + reset + "\n"
  end
end

# yamlで列挙したURLを順番に読み込む
urls = YAML.load_file(File.expand_path(File.dirname(__FILE__)+"/urls.yml"))
urls.each do |url|
  html = Nokogiri::HTML(open(url))

  # url + タイトル
  print blue+url+reset+"\n"
  print yellow+html.search("h3").text+reset+"\n"

  # メニュー一覧の取得(commod1_l or commod2_lのクラスのオブジェクト取得)
  menus = html.search(".commod1_l, .commod2_l")
  menus.each do |menu|
    # メニュー名、画像URL、カロリー値の表示
    p menu.search("h4").text
    p menu.search("img").first.attribute("src").value
    p menu.search("p > .calory").text.gsub(/>/, "")
    p ""

    save_file menu.search("img").first.attribute("src").value
  end
end


t1 = Time.now
p "#{t1 - t0} sec"

並列処理バージョン

# coding: utf-8

t0 = Time.now

require 'yaml'
require 'nokogiri'
require 'open-uri'
require 'term/ansicolor'
require 'parallel'

include Term::ANSIColor

def save_file(url)
  filedir = File.expand_path(File.dirname(__FILE__)) + "/images/"
  FileUtils.mkdir_p(filedir) unless FileTest.exist?(filedir)
  begin
    filename = filedir << File.basename(url)
    open(filename, 'w+b') do |file|
      open(url) do |data|
        file.write data.read
      end
    end
  rescue
    print red + "Download Error #{url}" + reset + "\n"
  end
end

# yamlで列挙したURLを順番に読み込む
urls = YAML.load_file(File.expand_path(File.dirname(__FILE__)+"/urls.yml"))
urls.each do |url|
  html = Nokogiri::HTML(open(url))

  # url + タイトル
  print blue+url+reset+"\n"
  print yellow+html.search("h3").text+reset+"\n"

  # メニュー一覧の取得(commod1_l or commod2_lのクラスのオブジェクト取得)
  menus = html.search(".commod1_l, .commod2_l")
  Parallel.each(menus, in_threds: 2) do |menu|
    # メニュー名、画像URL、カロリー値の表示
    p menu.search("h4").text
    p menu.search("img").first.attribute("src").value
    p menu.search("p > .calory").text.gsub(/>/, "")
    p ""

    save_file menu.search("img").first.attribute("src").value
  end
end


t1 = Time.now
p "#{t1 - t0} sec"

見ての通り、内容的には1行書き換えて、1行(requireを)追加しただけのものである。

実行結果

  • 非並列処理バージョン: 16.79574 sec”
  • 並列処理バージョン : 7.906693 sec

何回か実行してみておおよその速度を書いてみましたが、約2倍ぐらい早くなりました!

おすすめ書籍

パーフェクトRuby (PERFECT SERIES 6)
Rubyサポーターズ すがわら まさのり 寺田 玄太郎 三村 益隆 近藤 宇智朗 橋立 友宏 関口 亮一
技術評論社
売り上げランキング: 9,964
プログラミング言語 Ruby
プログラミング言語 Ruby
posted with amazlet at 13.12.02
まつもと ゆきひろ David Flanagan
オライリージャパン
売り上げランキング: 114,558

関連記事

images-3

Mac rbenvでRuby2.1.0をインストールするの巻

まえがき そういえば今月にRuby2.1.0がリリースされたみたいだ...

記事を読む

github-travisci-ruby-rspec-1github-travisci-ruby-rspec-1.png

RubyのテストをGiHub・TravisCIを使ってやってみる

まえがき 今回はTravisCIというGitHubで使える無料のCIツ...

記事を読む

imgres-11

SinatraをShotgunで実行させる。ついでにBunderの勉強

まえがき 前回の記事 [browser-shot url="htt...

記事を読む

RailsでSendGrid×ActionMailerを使って簡単メール送信をやってみる

まえがき Herokuのアドオンとして人気のある無料から使えるメール送...

記事を読む

rails runnerでRailアプリのバッチスクリプトを作る。

まえがき Railsで開発している時にちょっとしたバッチスクリプトな...

記事を読む

新着記事

no image

PHPでRubyのirbっぽいインタラクティブなスクリプトが実行できる「boris」

まえがき PHPでもRubyのirbみたいなことがしたくて探してみたと...

記事を読む

2015年の抱負と去年の振り返り〜よちよちWEB業界1年経験して〜

まえがき あけましておめでとうございます。今年もどうぞよろしくお願いし...

記事を読む

Java SE 7 Bronze試験(1Z0-802)を受けてきました

まえがき 以前から少し受けてみたかった試験『Java SE 7 Bro...

記事を読む

HubotでJenkinsのジョブを実行する

まえがき HubotをつかってJenkinsのジョブをじっこうしてみた...

記事を読む

no image

Hubotをforeverでデーモン化する

まえがき 今回はHubotをforeverを使ってデーモン化してみた時...

記事を読む

スポンサーリンク

PAGE TOP ↑