Excel VBAでFirefoxを操れる素晴らしいツール。それがSeleniumbasic。
以前はSeleniumVBAという名称だったが、昨年秋ごろにSeleniumBasicに変わった。今後SeleniumVBAの方はメンテされないそうなので注意。
インストール
ダウンロードページからインストーラをダウンロードして実行する。2016年2月2日現在はSeleniumBasic-2.0.7.0.exe。インストール先は%LOCALAPPDATA%\SeleniumBasic。
インストーラの最後に、Firefoxアドオンを入れるかどうか聞かれる。これを入れておくと、Firefoxの操作を記録してコードをエクスポートすることができる(Excelのマクロ記録に近い感じ)。だけど、私は今のところ使っていないなあ。
Excelを起動し、ツールの参照設定でアドオンを有効にする。
![]() |
Fig.1 参照設定でSelenium Type Libraryを有効化 |
オブジェクトを宣言する
以下を標準モジュールのどっかに書いておけばOK。1 2 3 | Public driver As New WebDriver Public keys As New keys Public by As by |
Firefoxを起動する
まず真っ先にやることは、Firefoxを起動すること。(起動済みのFirefoxを使い回す方法もある。後ほど。)
1 2 | driver. Get "/" |
要素にアクセスする
WebDriverクラスにはFindElement(s)ByXXXXというメソッドが用意されてる。これは、JavaScriptやInternetExplorerオブジェクトにおけるdocument.getElement(s)ByXXXに相当する。 大体メソッド名で使い方は想像できると思う。![]() |
Fig.2 WebDriverクラスのメンバー |
1 2 | Dim elm as Object set elm = driver.FindElementById( "id1" ) |
要素内のテキストを取得する
以下の様な感じで、id="id1"の要素のinnerTextを取得できる。1 | str = driver.FindElementById( "id1" ).Text |
テキストボックス等に文字を入力する
SendKeysメソッドを使う。1 | driver.FindElementByName( "text1" ).SendKeys "みょみょみょ" |
InternetExplorerオブジェクトを使ってIEを自動操作する際には、DOMオブジェクトのvalueプロパティに値を入れるだけで、元の値を上書きしてくれるのだけど。ここは対照的。
1 2 | driver.FindElementByName( "text1" ).Clear driver.FindElementByName( "text1" ).SendKeys "abc" |
1 2 | driver.FindElementById( "text2" ).SendKeys keys.Control, "a" driver.FindElementById( "text2" ).SendKeys keys.Delete |
要素の存否確認
要素が存在しない時に、FindElementByXXXシリーズで要素にアクセスするとエラーで落ちちゃう。 例えば、name="name1"の要素が存在しない時に1 | driver.FindElementByName( "name1" ) |
で、IsElementPresentというメソッドで、DOM内に特定の要素があるかどうか調べることができる。
第一引数には、by.Idとか、by.Nameとかがある。
…はずだったが、私の環境では動いたり動かなかったりする! なんで?
1 | If driver.IsElementPresent(by.name( "name2" )) Then 'expect True of False |
![]() |
Fig.3 IsElementPresentが動かない... |
仕方がないので
1 | if driver.FindElementsByName( "name3" ).Count > 0 Then |
あ、FindElementsByXXXシリーズ(sが入ってる)は、要素がなくてもエラーになりません。
x番目の要素を取り出す
HTML内のx番目のtableのy行目のz列目のテキストを取り出すなら、1 | xyzText = driver.FindElemntsByTag( "table" )(x).FindElementsByTag( "tr" )(y).FindElementsByTag( "td" )(z).Text |
同様に、ページ内の特定のボタンやラジオボタン、チェックボックスをクリックしたい時は、
1 | driver.FindElementsByTag( "input" )(x).Click |
全input要素にidがついていれば、FindElementByIdで要素を特定すればよいが、世の中そうでない場合も多々あるので…。
全部の要素にアクセスするなら、forでループさせる。
1 2 3 4 5 | Dim tags As Object , tag As Object Set tags = driver.FindElementsByTag( "a" ) For Each tag In tags MsgBox tag.Text Next |
1 2 3 4 5 | Dim tags As Object , i as Integer Set tags = driver.FindElementsByTag( "a" ) For i = 1 To tags.Count MsgBox tags(i).Text Next |
特定のリンク先をクリックする
XPathは個人的には嫌いだが使う。以下のような感じで、好きな要素(特定のattributeを持つ要素とか)を狙い撃ちできる。1 2 | href= "../hogehoge.html" driver.FindElementByXPath( "//a[@href='" & href & "']" ).Click |
多分
1 2 | onClickString = "javascript:hoge()" driver.FindElementByXPath( "//a[@onclick='" & onClickString & "']" ).Click |
プルダウンメニューを選択する
AsSelect.SelectByXXX メソッドを使う。1 2 3 4 | < select name = "select1" > < option value = "value1" >text1</ option > < option value = "value2" >text2</ option > </ select > |
1 | driver.FindElementByName( "select1" ).AsSelect.SelectByText ( "text1" ) |
1 | driver.FindElementByName( "select2" ).AsSelect.SelectByValue ( "value1" ) |
プルダウンメニューの中身を取り出す
以下の様な感じで、プルダウンメニューのi番目のoptionのtextが取り出せる。なぜかOptions(i)ではダメ。
1 | optionText = driver.FindElementByName( "select3" ).Options.Item(i).Text |
属性(attribute)
以下の様な感じでattributeを取り出せる。"getAttribute"と間違えがちなので注意。
1 | href = driver.FindElementByName( "a" ).Attribute( "href" ) |
一度開いたFirefoxのウインドウを使い回す
Seleniumというツールは、処理を走らせるたびにブラウザを開いて、処理が終わったら閉じる、という使い方を想定しているっぽい節がある。が、処理のオートメーションという要件からすると、ログインが必要なWebページで同じような処理を繰り返し行いたい場合だってある。そんなケースで、1回処理を流すたびにブラウザが開いて、ログインして、処理して、ログアウトして、ブラウザ閉じる…という動作をしていたら、まどろっこしくて仕方がない。ここは、一度開いたブラウザを、ログインしたままキープして使い回したいところ。今のところ、下記のような関数で、この要件を実装している。
以下のコードはサンプルなので、私が実際に使っているものとは少し変えてある。
(IDとパスワードがベタ書きになってるとことか。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | Public driver As New WebDriver ' Firefoxで某システムを開く ' - Firefox未起動だったら起動し、某システムのログイン画面を表示して自動ログイン ' - Firefox起動済みで、どこか他所のドメインに移動してたら、某システムのトップページに戻る ' - Firefox起動済みでログイン済みだったら何もしない ' - Firefox起動済みでセッションが切れてたら自動再ログイン ' @return 失敗したらfalse Public Function OpenExampleCom() As Boolean Dim winCount As Integer Dim errNum As Integer OpenExampleCom = False On Error Resume Next winCount = driver.Windows.Count errNum = Err.Number On Error GoTo 0 ' ToDo この辺りの処理は精査必要? If errNum = 57 Or winCount = 0 Then ' Firefoxを起動して、ページを開く driver. Get "/login" ' ログイン If AutoLogin = False then GoTo finally End If Else ' baseUrlが変わってたらセットし直し、トップページに移動。 driver. Get "/topPage" End If ' セッション判定 ' ログアウトorタイムアウト画面ならログイン画面に移動。 ' 対象のページに合わせて適切に書き換えること。 If driver.FindElementByTag( "h1" ).Text = "Logout" Or _ driver.FindElementByTag( "h1" ).Text = "TimeOut" Then driver. Get "/login" End If ' 今いるのがログイン画面ならログインする。 If AutoLogin = False then GoTo Finally End If End If OpenExampleCom = True finally: ' 事後処理。何かあればここに書く。 End Function ' 自動ログイン ' @return 失敗したらfalse Private Function AutoLogin() as Boolean AutoLogin = True ' 今いるのがログイン画面ならログイン処理を行う。 ' 対象のページに合わせて適切に書き換えること。 If driver.FindElementByTag( "h1" ).Text = "Login" Then driver.FindElementById( "userid" ).SendKeys "dsp74118" driver.FindElementById( "passwd" ).SendKeys "Password" driver.FindElementByTag( "input" ).submit ' ログイン成否判定。対象のページに合わせて適切に書き換えること。 If driver.FindElementByTag( "h1" ).Text = "Login Error" Then MsgBox "ログインに失敗しました。" AutoLogin = False End If End If End Function |
すごいです。
返信削除勉強になります。
Casino Review and Bonus Code - JTHub
返信削除Casino Bonus 전주 출장안마 Codes — All the 광주광역 출장안마 Casino players can choose 서산 출장마사지 to 경상북도 출장안마 play at JTRCasino. The game offers a generous welcome bonus of $5,000 and 고양 출장안마 a