複数のdriverを一気に立ち上げる
複数のdriverを宣言するのには普通に考えると以下のようになります。
driver1 = Selenium::WebDriver.for :chrome driver2 = Selenium::WebDriver.for :chrome driver3 = Selenium::WebDriver.for :chrome driver4 = Selenium::WebDriver.for :chrome driver5 = Selenium::WebDriver.for :chrome driver6 = Selenium::WebDriver.for :chrome driver7 = Selenium::WebDriver.for :chrome driver8 = Selenium::WebDriver.for :chrome driver9 = Selenium::WebDriver.for :chrome driver10 = Selenium::WebDriver.for :chrome
スマートじゃないですよね。。。
for文とかでできないかなと思うのですが。。こんな感じで。
for i in 1..10 do
"driver#{i}" = Selenium::WebDriver.for :chrome
end
=> syntax error, unexpected '=', expecting keyword_end
"driver#{i}" = Selenium::WebDriver.for :chrome
syntax errorですね。。。
配列でいける
配列でやってみましょう。
driver = [] (1..10).each do |n| driver[n] = Selenium::WebDriver.for :chrome end
10個のドライバーが立ち上がりましたね。
同じように以下でもいけます。
driver = [] 10.times do |n| driver[n] = Selenium::WebDriver.for :chrome end
これでdriver配列に10個のselenium webdriverオブジェクトが入りました。
それぞれのdriverの呼び出しはdriver配列の中を呼び出すので
driver[0].get("http://google.com")
driver[1].get("http://google.com")
driver[2].get("http://google.com")
で大丈夫です。
seleniumの並列処理
例えば、以下のようなコードを実装した時に
driver[0].find_element(:id, "element").click driver[1].find_element(:id, "element").click driver[2].find_element(:id, "element").click
driver[0]のクリックで画面がロードが終わってからdriver[1]の処理が始まります。
これを全てのドライバーで一気にクリックを行いたいと思いました。
seleniumの並列処理と言えば、selenium gridやjenkinsというイメージがありますが、
同一の処理を複数のドライバーで行うのであれば単体のコードのみで実装できます。
threadクラスを使う
同一の処理を複数のドライバーで行いたい時に Parallel でやってみたのですが、
seleniumとの相性が悪いのかうまく動きませんでした。
そこで特別なgemなどを使わずに標準で入っているthreadクラスで試してみました。
threads = []
driver.each do |d|
threads << Thread.new do
d.find_element(:id, 'element').click
end
end
threads.each { |t| t.join }
おおお、すべて並列で動作していますね。
threadクラスに関してはドキメントがあるので見てみてください。
class Thread (Ruby 2.4.0)
まとめ
では、複数のdriverを立ち上げてそれを並列処理するためのコードをまとめてみましょう。
require 'selenium-webdriver'
driver = []
(1..10).each do |n|
driver[n] = Selenium::WebDriver.for :chrome
end
threads = []
driver.each do |d|
threads << Thread.new do
d.get("http://google.com")
end
end
threads.each { |t| t.join }
スマートに複数driverでの並列実行ができましたね。


コメント