Seleniumでブラウザー自動化できるかな？

#目的
Web管理画面がついている機材には認証画面がある。なんとか自動化したい。
プロジェクターとかWebカメラとかいろいろ。

#Seleniumというものがあるらし
[Seleniumブラウザー自動化プロジェクト](https://www.selenium.dev/documentation/ja/)を読み進める。

##Rubyを入れる
[Ruby Installer for windows](https://rubyinstaller.org/)から最新版を入れる。

[【初心者】Rubyインストールから簡単なプログラム実行まで](https://proengineer.internous.co.jp/content/columnfeature/12360)を参考にした。

##ライブラリを入れる
cmd.exeで実行する。

```
gem install selenium-webdriver
```

##WebDriverを入れる

###ダウンロード
[ドライバー要件](https://www.selenium.dev/documentation/ja/webdriver/driver_requirements/)のクイックリファレンスからChromeのダウンロードからできるとおもったら、バージョンのフォルダ一覧が表示される。
数字が大きいのが最新なので、フォルダを開いて「chromedriver_win32.zip」をダウンロードする。

###インストール

zipを展開して「chromedriver.exe」をC:\WebDriver\binに保存する。

pathを通す

```  
setx /m path "%path%;C:\WebDriver\bin\"
```

OSを再起動して試す

```
>chromedriver
Starting ChromeDriver 88.0.4324.27 (6347fe8bf1e48bd0c54d07dc55ca011cf40861c9-refs/branch-heads/4324@{#450}) on port 9515
Only local connections are allowed.
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
```

###試す！

お試しファイルを作成する。

```selenium.rb
require "selenium-webdriver"

driver = Selenium::WebDriver.for :chrome
```

お試しファイルを実行する。

```
>ruby 20201217001.rb
Traceback (most recent call last):
        2: from 20201217001.rb:1:in `<main>'
        1: from C:/Ruby27-x64/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
C:/Ruby27-x64/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- selenium-webdriver (LoadError)
（中略）
x64/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require'
C:/Ruby27-x64/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- ffi (LoadError)
（中略）
3.0.0/lib/childprocess/windows.rb:3:in `<top (required)>'
C:/Ruby27-x64/lib/ruby/gems/2.7.0/gems/childprocess-3.0.0/lib/childprocess/windows.rb:6:in `rescue in <top (required)>': FFI is a required pre-requisite for Windows or posix_spawn support in the ChildProcess gem. Ensure the `ffi` gem is installed. If you believe this is an error, please file a bug at http://github.com/enkessler/childprocess/issues (ChildProcess::MissingFFIError)

```
エラーになった。

最初の「`require': cannot load such file -- selenium-webdriver (LoadError)」に目を奪われがち。中盤にあらわれた「ffi」がポイントっぽい。つうか、Q&Aサイトでもエラーを貼り付けていないから解決できていないんじゃないか？

###追加インストール
世のQAサイトの正解はこれなんじゃないかと過信している。

```
gem install ffi
```

###試す２！
こんどは平気なはず。

```
>ruby 20201217001.rb
DevTools listening on ws://127.0.0.1:49937/devtools/browser/2ac6997d-7b76-4230-b56a-b05765457035
Traceback (most recent call last):
（中略）
Backtrace:: session not created: This version of ChromeDriver only supports Chrome version 88 (Selenium::WebDriver::Error::SessionNotCreatedError)
Current browser version is 87.0.4280.88 with binary path C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe
```

あれ？ブラウザとWebDriverのバージョンがあっていないらしい。最新が良いってわけではないらしい。
ドライバー要件から同じバージョンをダウンロードして、C:\WebDriver\binに入れ替える。

```
>ruby 20201217001.rb

DevTools listening on ws://127.0.0.1:50041/devtools/browser/a4f2bc4b-2ead-48bc-9af6-db8329221104
```
成功したらしい。（ほんとうか？）

#実験
試すとはちがう。
##ブラウザを開く

```
require "selenium-webdriver"
driver = Selenium::WebDriver.for :chrome
# URLを開く
#driver.get 'https://selenium.dev'
```
あっというま、瞬間、なぜ？ってブラウザが閉じる。ドライバーによって閉じたり、閉じる命令が必要っぽい。

##勝手に閉じる対策

```
#sleep(5)
```
末尾につけるとちょと保つ。
でもwaitでやめてしまった。

##Basic認証

[Selenium WebdriverでBasic認証なサイトにアクセスする方法](https://qiita.com/sakaeda11/items/ff70a22e8e5fa209673f)

>driver.get 'http://admin:admin@the-internet.herokuapp.com/basic_auth'

ここで勝手に声が出た「うぉおお！」

##表示されるのを待つ

認証したあとにページが表示される。表示しないうちにコードが要素を探してしまうのを何とかしたい。

[SeleniumWebdriverでWaitを入れてみる](https://qiita.com/t_y_cafe/items/5e1645e9221d3b1d0a4e)

```
# waitに60秒のタイマーを持たせる変数宣言
wait = Selenium::WebDriver::Wait.new(:timeout => 60)

#　表示されるまでまつ
wait.until{driver.find_element(:id, 'pst_select').displayed?}
```

##フレームだった
どうしても要素が見つからないとなる。Frameの入れ子だったorz

フレームの操作がうまくいかない。フレームを直接開くことにした。

##セレクトタグを選択
値を指定してクリックする。

```
# 要素を指定
element = driver.find_element(:id, 'pst_select')
# セレクトタグ指定
select = Selenium::WebDriver::Support::Select.new(element)

# 値指定
select.select_by(:value, '1')
# 要素をクリック
driver.find_element(:id, 'pst_move').click
```

#最終結果
複数の機器を操作したいので、ループにした。

```cam_reset.rb
require "selenium-webdriver"

roomNum = {	"001" => "10.1.1.1",
			"002" => "10.1.1.2"}

roomNum.each{|room, ipAddress|
	driver = Selenium::WebDriver.for :chrome

	# URLを開く
	camUrl = "http://account:password@" + ipAddress + "/live/live_flame_ctrl.html"
	driver.get camUrl

	# waitに60秒のタイマーを持たせる変数宣言
	wait = Selenium::WebDriver::Wait.new(:timeout => 60)

	#　表示されるまでまつ
	wait.until{driver.find_element(:id, 'pst_select').displayed?}

	# 要素を指定
	element = driver.find_element(:id, 'pst_select')
	# セレクトタグ指定
	select = Selenium::WebDriver::Support::Select.new(element)

	# 値指定
	select.select_by(:value, '1')
	# 要素をクリック
	driver.find_element(:id, 'pst_move').click
	
	# 閉じる
	driver.close
}
```
あとはバッチファイルを作るだけ。

```camreset.bat
ruby cam_reset.rb
```