ここではSeleniumを使ってVBAからchromeブラウザ操作するVBAプログラムについて解説します。
※自動化した処理は接続先にトラフィックを送ります。過度になった場合は異常アクセスとされることがありますので使用にはご注意ください。
まずはchromeとseleniumがインストールされていない場合はインストールをしましょう。
Seleniumを使ってVBAからchromeブラウザ操作(インストール編)
それではVBAでよく使われる手法を見ていきましょう。
ブラウザ設定と起動や終了
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
基本のブラウザを開いてURLにアクセスしそれを終了するプログラムです。
「driver」がブラウザのオブジェクトになりますので、これに様々な処理をしていきます。
最後のリセットは変数を空(未設定)にしておくものです。
終了時は「.Close」を使用していますが「.quit」も使用できます。
.quitは
このドライバを使用して、関連するすべてのウィンドウを閉じます。停止と同じです。
.closeは
現在のウィンドウを閉じます
おまけにブラウザ画面の設定方法です。
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 '画面表示設定 '画面に表示しない場合はコメントアウトを外す 'driver.AddArgument "headless" 'driver.AddArgument "disable-gpu" '画面サイズ 'driver.AddArgument "window-size=200,400" driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
ソースを取得する
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く source = driver.PageSource '開いているページのソース driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
ソースのスクレイピングなどの時は「source」を加工したりすることによって色々な情報が取得できます。
属性やセレクタを指定して取得する
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く Set objIdNameid = driver.FindElementById("id属性名") Set objIdNameclass = driver.FindElementsByClass("class属性名").Item("出現番号(0~)") Set objIdNamename = driver.FindElementsByName("name属性名").Item("出現番号(1~)") Set objIdNamesele = driver.FindElementByCss("cssセレクター") driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
「.FindElement~」が様々な方法で指定したものを取得するものです。
cssセレクターは「#id > div > div > div.class-1」のよう記述方式で、ブラウザのデバック機能などで確認できます。
エレメントがあるかを確認
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 Dim By As New By driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く id_judge = driver.IsElementPresent(By.Css(IdNamename)) if id_judge = True then Debug.Print "存在します" end if driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
「IsElementPresent」はエレメントが存在するかをBoolean(True,False)で返します。
エレメントに対して処理をする際、存在しない場合はエラーになってしまいますので、エラー処理をする場合に有効です。
ループ処理などにして応答を待つということもできます。
chromedriveは基本的にページの応答は待ってくれますが、javascriptなどで出現するエレメントは待ちません。
そのような場合は自分で待機する処理を入れる必要があります。
#If VBA7 Then Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr) #Else Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long) #End If sub test() id_judge = driver.IsElementPresent(By.Css(IdNamename)) HT_loop_num = 0 Do While id_judge = False If HT_loop_num > 6 Then "エラー処理" End If HT_loop_num = HT_loop_num + 1 Sleep 5000 DoEvents id_judge = driver.IsElementPresent(By.Css(IdNamename)) Loop end sub
冒頭はsleepを使うための宣言です。
上記のようにするとエレメントが出現するまで6回ループし、なければエラー処理をします。
また、セレクターがあっても画面に表示されていない場合があります。
何かを読み込んだ後に出るボタンなどです。
その場合はIsDisplayedを使用します。
#If VBA7 Then Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr) #Else Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long) #End If sub test() IdNamename = "#target > a" id_judge = driver.IsElementPresent(By.Css(IdNamename)) display_judge = driver.FindElementByCss(IdNamename).IsDisplayed'ディスプレイに表示されているか HT_loop_num = 0 Do While id_judge = False and display_judge = False If HT_loop_num > 6 Then "エラー処理" End If HT_loop_num = HT_loop_num + 1 Sleep 5000 DoEvents id_judge = driver.IsElementPresent(By.Css(IdNamename)) display_judge = driver.FindElementByCss(IdNamename).IsDisplayed Loop end sub
セレクターがあって、ディスプレイに表示している場合に処理を行います。
フォームに入力したりキーボード操作を送る
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 Dim Keys As New Selenium.Keys 'sendkeyでブラウザにkeyを送るために使う driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く Set objIdNameid = driver.FindElementById("id属性名") Set objIdNamesubmit = driver.FindElementById("id属性名(submit)") objIdNameid.Clear objIdNameid.SendKeys "テスト" objIdNameid.SendKeys Keys.Enter objIdNamesubmit.submit driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
ID属性でテキストエリアを指定してクリアしてからテキストを挿入しています。
その後改行を入れるためにキーボードの「Enter」を押下しています。
その後submitしています。
.submitは.clickでも大丈夫なことが多いです。
objIdNamesubmit.click
尚、長い文章をフォームなどに挿入する場合はSendKeysは向きません。処理に時間がかかるからです。
javascriptを実行する方法が圧倒的に速いのでこちらも参照してください。
要素を削除する
取得したくない箇所がある場合などに、タグごと消したい時があります。
その場合、VBA関数ではできないのでjavascriptを使用します。
Dim des_dell_css() des_dell_css(1) = "#target > p" 'セレクター1 des_dell_css(2) = "#target > a" 'セレクター2 des_dell_css(3) = "#target > div" 'セレクター3 For dell_num = 1 To UBound(des_dell_css) 'jsのコードを作成 dell_judge = driver.IsElementPresent(myBy.Css(des_dell_css(dell_num))) If dell_judge = True Then js_code = "document.querySelector('" & des_dell_css(dell_num) & "').remove()" driver.ExecuteScript (js_code) End If Next dell_num
上記では削除対象を複数設定するようになっています。
ブラウザの操作を画面表示しない
sub test() Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.AddArgument "headless" '!ここ driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
ヘッドレスモードというもので画面に表示せずバックグラウンドで処理をします。
chromeで処理中は前面にブラウザが来てしまいます。
他の作業の邪魔にならないようにするにはバックグラウンド処理がいいでしょう。
また、ブラウザの表示がしませんので非表示のほうが端末への負荷が減りますので処理も早くなります。
画面サイズを指定して開く
sub test() driver.AddArgument "window-size=1500,1000" '!ここ Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く source = driver.PageSource driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
画面サイズ指定はスクリーンショットを取るときなどに設定すると一律したサイズで取得できます。
スクリーンショットを取得する
sub test() driver.AddArgument "window-size=1500,1000" Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.TakeScreenshot.SaveAs "保存先パスとファイル名" driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
「.TakeScreenshot」でスクショを取って「.SaveAs」で保存します。
保存先にはファイル名も含みます。
この機能はデバックにも使えます。
バックグラウンドで実行している場合、実際に処理をしている画面を確認したいときに便利です。
ツイッターなどで自動でログインさせない方法
ツイッターなどではログインページにアクセスすると、一度ログインしている場合ユーザー情報がブラウザに残っていて勝手にログインすることがあります。
ですが、ログインできたりできていなかったりだと、ログイン状態の確認をする必要がありますがなかなか面倒です。
そんな時に毎回必ずログインするようにできれば確認の作業が必要なくなります。
通常はブラウザのユーザー情報は
C:/Users/ユーザ名/AppData/Local/Google/Chrome/User Data
あたりに格納されていますのでこの格納場所を変えてあげて毎回削除するばログイン画面から始められます。
尚、下記ではエクセルファイルと同階層に「tmp」というフォルダを作成しておきます。
sub test() driver.AddArgument "window-size=1500,1000" Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 PROFILE_PATH = "tmp" driver.AddArgument ("user-data-dir=" & PROFILE_PATH) driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする Dim fso As FileSystemObject Set fso = New FileSystemObject Dim fl As Folder Set fl = fso.GetFolder(PROFILE_PATH) ' フォルダを取得 Dim f As File For Each f In fl.Files f.Delete (True) ' ファイルを削除 Next Set fso = Nothing end sub
最初にデータを格納するフォルダを設定します。
処理が終わったらユーザーデータを削除するという具合です。
逆に普段使っているアカウント以外で自動ログインしたい時などは、chromedrive用にユーザーデータを格納しておけばキャッシュクリアされるまではアクセスが可能です。
ブラウザでF5を押すようなリフレッシュをする
処理の途中で画面をリフレッシュしたいときもあると思います。
sub test() driver.AddArgument "window-size=1500,1000" Dim driver As New Selenium.ChromeDriver 'ブラウザ設定 driver.Start "chrome" 'chromeを起動 driver.Get "https://www.google.com/?hl=ja" 'URLを指定して開く driver.Refresh '!ここ source = driver.PageSource driver.Close 'chromeを閉じる Set driver = Nothing 'driveをリセットする end sub
javascriptで処理をして、リロードしないと情報が更新されない場合などに使えるかと思います。
seleniumとvbaを使えば様々な自動化が可能です。
他にも色々な機能がありますのでお試しください。
コメント