QR Send

スマホとPCのChrome間で、URLやテキストをQRコード1回のペアリングで送り合える自作Chrome拡張。アカウント不要・無料。

使ってみる →

selenium gridやjenkinsを返さず単体のコードのみで複数のdriverを並列実行

Selenium・自動化

複数の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での並列実行ができましたね。

コメント

タイトルとURLをコピーしました