Seleniumを使ってVBAからchromeブラウザ操作(VBA編)

スポンサーリンク
excelvba VBA
スポンサーリンク

ここでは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を使うための宣言です。

【VBA】sleepを使えるようにする
VBAにはsleepコマンドがありません。 なのでwindows APIを利用してVBA内でもsleepを使えるようにする必要があります。 モジュールの最上部(関数の上)に下記を追記してAPIの宣言を...続きを読む

上記のようにするとエレメントが出現するまで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を実行する方法が圧倒的に速いのでこちらも参照してください。

SendKeysで文章入力が重たい場合

要素を削除する

取得したくない箇所がある場合などに、タグごと消したい時があります。

その場合、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を使えば様々な自動化が可能です。

他にも色々な機能がありますのでお試しください。

 

 

 

コメント

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