SeleniumVBAの使い方 実践コード集【VBA】

SeleniumVBAの使い方 実践コード集【VBA】

SeleniumVBAを入れてみたものの、「で、実際にやりたい操作はどう書くの?」というところで止まっていませんか?

導入と基本の流れは前の記事「Excelでもブラウザ操作!SeleniumVBAの使い方」で書いたので、この記事は実際に書くコードに集中した実践編です、導入はそちらで済んでいる前提で進めます

クリックや入力、待機、要素の存在チェック、プルダウン、複数要素のループ、スクショ、JavaScript実行…と、ブラウザ自動化で「結局これ毎回書くよね」というコードをまとめました、私が普段よく使う書き方をベースにしているので、コピペして手を入れながら使ってもらえればと思います

最初に一番だいじな「要素の探し方」から見ていきます、ここを By.CssSelector に寄せておくと、あとがぐっとラクになります

目次

要素の探し方は By.CssSelector に寄せる

SeleniumVBAで要素を探すときは FindElement(By.X, “値”) という形で書きます、この By には id・class・name・タグ名・CSSセレクタ・XPath…と何種類か指定できるんですが、初心者のうちは全部覚えようとしなくて大丈夫です

個人的なおすすめは、基本は By.CssSelector ひとつに寄せるやり方です、CSSセレクタはWeb制作でも使う書き方で、id・class・属性・子孫…とだいたいの探し方をこれ1本でカバーできます、覚えることが減るぶん、つまずきにくくなります

「探したいもの」と「CSSセレクタの書き方」を対応表にするとこんな感じです

スクロールできます
探したいものCSSセレクタ
id で探す#id名#search
class で探す.class名.btn
name 属性で探す[name=’値’][name=’q’]
タグ名で探すタグ名div
属性で探すタグ[属性=’値’]input[type=’text’]
子孫をたどる(スペース).親 .子.list .item
直下の子に限定(>).親 > .子.list > .item

そして、これらをスペース(子孫)「>」(直下の子)でつなげられるのがCSSセレクタの強みです、階層をたどって狙った要素をピンポイントに指定できるので、似た要素がたくさんあるページほどここが効いてきます

属性での絞り込み([id^=]など)や :not:nth-child といったCSSセレクタ自体の書き方は、別記事「CSSセレクタの書き方 自動化で要素を狙う指定方法」に詳しくまとめたので、狙った要素がうまく取れないときはこちらもどうぞ

たとえば id が “search” の検索ボックスを探すなら、こう書けます、By.NameBy.ID を使い分けなくても、CSSセレクタの書き方を変えるだけで済むのがラクなところです

' id が search の要素を探す
Dim el As WebElement
Set el = driver.FindElement(By.CssSelector, "#search")

' name 属性が q の要素を探す(Googleの検索ボックスなど)
Set el = driver.FindElement(By.CssSelector, "[name='q']")

ちなみに FindElementByCssSelector(“#search”) のように、Byを書かずに呼べるショートカットのメソッドも用意されています、どちらでも結果は同じなので、書きやすい方で大丈夫です

CSSで足りないとき … テキスト検索はループ、親だけXPath

正直に書いておくと、CSSセレクタは「要素の中の文字で探す」のと「子から親へさかのぼる」のが苦手です、SeleniumVBAには By.LinkTextBy.XPath もあるので手っ取り早くはそれを使えばいいんですが、By.CssSelectorに寄せ切りたいなら、テキスト検索は独自functionで再現できます

考え方はシンプルで、CSSで候補を集めて、VBAでループしながらtext一致を探すだけです、まずはリンクを表示文字で探す関数、全aタグを集めてループするので、これで By.LinkText の代わりになります

' リンクを表示文字で探す(全aタグをループしてtext一致・LinkTextの代わり)
Public Function FindLinkByText(driver As WebDriver, ByVal keyword As String) As WebElement
    Dim els As WebElements, el As WebElement
    Set els = driver.FindElements(By.CssSelector, "a")
    For Each el In els
        If InStr(el.GetText, keyword) > 0 Then
            Set FindLinkByText = el
            Exit Function
        End If
    Next el
    Set FindLinkByText = Nothing   ' 見つからなければ Nothing
End Function

同じ考え方を、リンク以外の要素にも広げたのがこちらです、探す範囲のCSSセレクタとキーワードを渡すと、その中からtext一致の要素を返します、「送信」という文字のボタンのような、By.XPath でやりがちなテキスト検索を、CSSとループだけで書けます

' 指定CSSの要素をループして表示文字で探す(XPathを使わずtext一致)
Public Function FindByText(driver As WebDriver, ByVal cssSel As String, _
                           ByVal keyword As String) As WebElement
    Dim els As WebElements, el As WebElement
    Set els = driver.FindElements(By.CssSelector, cssSel)
    For Each el In els
        If InStr(el.GetText, keyword) > 0 Then
            Set FindByText = el
            Exit Function
        End If
    Next el
    Set FindByText = Nothing
End Function

' 使い方(button の中からテキスト「送信」を探す)
' FindByText(driver, "button", "送信").Click

これで、リンク文字もテキスト一致も By.CssSelector +ループで書けるので、覚える By を増やさずに済みます

そして、CSSでもループでも唯一どうにもならないのが、子から親へさかのぼる逆引きです、CSSは子孫しか選べないので、ここだけは By.XPath“..”(親を表す書き方)を使います

' 見つけた要素から親をたどる(CSSでは無理・XPathの ".." を使う)
Dim child As WebElement, parent As WebElement
Set child = driver.FindElement(By.CssSelector, "#price")

' その要素を起点に ".." で親要素を取る
Set parent = child.FindElement(By.XPath, "..")

整理すると、子・孫への絞り込みはCSSセレクタ、テキストで探すのはCSSセレクタ+ループの独自function、子から親への逆引きだけがXPathの “..”、という棲み分けです、ほぼCSSに寄せておいて、親をたどるときだけXPathを出す、くらいの感覚でちょうどいいと思います

よく使う操作コード集

ここからは、見つけた要素に対して「何をするか」のコードをまとめていきます、どれも前の記事の基本コード(StartChrome → OpenBrowser → NavigateTo でページを開いたあと)の流れの中で使う想定です

クリックする・文字を入力する

クリックは Click、文字入力は SendKeys です、入力欄に元から入っている文字を消したいときは、SendKeysclearBeforeTyping を True にするか、先に Clear を呼びます

' ボタンをクリック
driver.FindElement(By.CssSelector, ".btn-search").Click

' 入力欄に文字を打ち込む
driver.FindElement(By.CssSelector, "[name='q']").SendKeys "SeleniumVBA"

' 元の文字を消してから入力(clearBeforeTyping)
driver.FindElement(By.CssSelector, "#keyword").SendKeys "新しい値", clearBeforeTyping:=True

' 入力欄を空にするだけ
driver.FindElement(By.CssSelector, "#keyword").Clear

' フォームを送信する
driver.FindElement(By.CssSelector, "#keyword").Submit

テキスト・属性・CSSを取り出す

表示テキストを取るのは GetText、リンク先(href)などの属性は GetAttribute、文字色などの見た目は GetCSSProperty で取れます、メソッド名を間違えやすいところなので、ここはまとめて覚えておくと安心です

Dim el As WebElement
Set el = driver.FindElement(By.CssSelector, "#title")

' 表示テキストを取る
Debug.Print el.GetText

' 属性を取る(リンク先の href など)
Debug.Print el.GetAttribute("href")

' 見た目のCSS値を取る(文字色など)
Debug.Print el.GetCSSProperty("color")

' 中のHTMLやタグ名を取りたいとき
Debug.Print el.GetInnerHTML
Debug.Print el.GetTagName

' 表示・有効・選択の状態を真偽値で取れる
Debug.Print el.IsDisplayed
Debug.Print el.IsEnabled
Debug.Print el.IsSelected

名前を取り違えやすいので注意です、テキストは .Text ではなく GetText(メソッド)、CSS値は GetCSSProperty で取ります、PythonのSeleniumと名前が少し違うので、ここは間違えやすいポイントです

待機する(ImplicitMaxWait が基本)

ブラウザ自動化でハマりやすいのが「要素がまだ表示されていないのに探しにいって失敗する」パターンです、対策の基本が ImplicitMaxWait です

これを設定しておくと、以降の FindElement が、要素が出てくるまで自動でリトライしながら待ってくれます、ページ表示がもたつくサイトでも、これだけでだいぶ安定します

' 以降の FindElement は、最大10秒まで要素を待つ(ミリ秒指定)
driver.ImplicitMaxWait = 10000

' 単純にその場で止めたいだけなら Wait(ミリ秒)
driver.Wait 1000   ' 1秒待つ

ImplicitMaxWait は「要素が出るまで待つ賢い待機」、Wait は「とにかく指定ミリ秒止まる」だけのシンプルな待機です、基本は ImplicitMaxWait を最初に1回セットしておき、どうしても固定で待ちたい場面だけ Wait を足す、という使い分けがおすすめです

要素があるか確認する(IsPresent)

覚えておきたいのが、FindElement は要素が見つからないとエラーになる、という点です、なので「あるかどうか分からない要素」を相手にするときは、いきなり FindElement しないほうが安全です

そこで使うのが IsPresent です、これは要素があるかどうかを True / False で返してくれるので、エラーで止まらずに分岐できます、第3引数で「この要素は最大何ミリ秒待つか」も指定できます

' 要素があるかを True / False で確認する
If driver.IsPresent(By.CssSelector, ".alert") Then
    Debug.Print "アラートが出ています"
End If

' 待ち時間を指定しつつ、見つかった要素を受け取る
Dim el As WebElement
If driver.IsPresent(By.CssSelector, "#result", 5000, , el) Then
    Debug.Print el.GetText   ' 見つかったときだけ使う
End If

最後の引数に ByRef で変数を渡すと、見つかった要素をそのまま受け取れます、「あるか確認 → あれば使う」を1回で書けるので、地味に便利です

プルダウン(select)を選ぶ

プルダウン(select要素)は、専用のメソッドで選べます、表示文字で選ぶ SelectByVisibleText、値で選ぶ SelectByValue、順番で選ぶ SelectByIndex の3つを覚えておけば十分です

Dim sel As WebElement
Set sel = driver.FindElement(By.CssSelector, "#prefecture")

' 表示されている文字で選ぶ
sel.SelectByVisibleText "東京都"

' value 属性の値で選ぶ
sel.SelectByValue "13"

' 上から数えた順番で選ぶ(0始まり)
sel.SelectByIndex 0

複数の要素をまとめて取る・ループする

1つではなく、条件に合う要素を全部取りたいときは FindElements(複数形)を使います、これは要素のコレクションを返すので、For Each でぐるっと回せます、一覧ページから値をまとめて拾うときの定番です

Dim els As WebElements
Dim el As WebElement

' class="item" の要素を全部取る
Set els = driver.FindElements(By.CssSelector, ".item")

For Each el In els
    Debug.Print el.GetText
Next el

表をまるごとExcelに取り込む

VBAでブラウザを動かす一番のうまみが、取ってきた値をそのままExcelに書き出せることです、ページの表(table要素)なら、TableToArray で2次元配列にできるので、シートへの貼り付けがかなりラクになります

' ページの表を2次元配列にして、シートに一気に貼る
Dim tbl As WebElement
Set tbl = driver.FindElement(By.CssSelector, "table#data")

Dim arr As Variant
arr = tbl.TableToArray

Range("A1").Resize(UBound(arr, 1) + 1, UBound(arr, 2) + 1).Value = arr

' 1セルずつ書きたいときは For Each で
Dim els As WebElements, el As WebElement, r As Long
Set els = driver.FindElements(By.CssSelector, ".price")
r = 1
For Each el In els
    Cells(r, 1).Value = el.GetText
    r = r + 1
Next el

逆に、Excelの一覧を読みながらページを順に開く、という回し方もできます、A列に並べたURLやIDを For で回して、そのつど NavigateTo でページを開けば、Excel主導のブラウザ自動化が組めます

スクリーンショットを撮る

画面の証跡を残したいときは SaveScreenshot です、ページ全体・特定の要素だけ・縦に長いページの全体…と撮り分けられます

' 表示中の画面を保存
driver.SaveScreenshot "C:\temp\shot.png"

' 縦に長いページ全体を保存(fullScreenShot)
driver.SaveScreenshot "C:\temp\full.png", , fullScreenShot:=True

' 特定の要素だけ保存
Dim el As WebElement
Set el = driver.FindElement(By.CssSelector, "#chart")
el.SaveScreenshot "C:\temp\chart.png"

iframe・タブを切り替える

ページの中に別ページが埋め込まれている iframe の中身は、そのままだと操作できません、SwitchToFrame で中に入って、終わったら SwitchToDefaultContent で元に戻ります

' iframe の中に入る
Dim frame As WebElement
Set frame = driver.FindElement(By.CssSelector, "iframe#content")
driver.SwitchToFrame frame

' iframe 内の要素を操作したあと、元のページに戻る
driver.SwitchToDefaultContent

タブやウィンドウの切り替えは Windows 経由で行います、タイトルやURLで目的のタブに移ったり、新しいタブを開いたりできます

' タイトルやURLで目的のタブへ切り替える
driver.Windows.SwitchToByTitle "注文一覧"
driver.Windows.SwitchToByUrl "https://example.com/orders"

' 次のタブへ・新しいタブを開く
driver.Windows.SwitchToNext
driver.Windows.SwitchToNew windowType:=svbaTab

JavaScriptを実行する・スクロールする

標準のメソッドだけだと届かない操作は、ExecuteScript でJavaScriptを直接走らせて片付けられます、戻り値も受け取れるので、ちょっとした計算やページ内の値取得にも使えます

JS側では、VBAから渡した引数を arguments[0] の形で受け取れます、よく使うのは「目的の要素まで画面をスクロールする」用途です

' JSを実行して戻り値を受け取る(5 * 10 = 50)
Dim ret As Variant
ret = driver.ExecuteScript("return arguments[0]*arguments[1];", 5, 10)
Debug.Print ret

' 指定した要素までスクロールする
Dim el As WebElement
Set el = driver.FindElement(By.CssSelector, "#footer")
driver.ExecuteScript "arguments[0].scrollIntoView(true);", el

' 画面を下に1000pxスクロールする
driver.ExecuteScript "window.scrollBy(0,1000);"

エンターキーなどの特殊キーを送る

検索ボックスに文字を打って、そのままエンターで検索したい…というのもよくあります、特殊キーは WebKeyboard を用意して、SendKeys の文字とつなげて送ります

Dim k As New WebKeyboard
Dim box As WebElement
Set box = driver.FindElement(By.CssSelector, "[name='q']")

' 検索語を打ってエンターキーで送信
box.SendKeys "SeleniumVBA" & k.ReturnKey

' Ctrl + A で入力欄を全選択する
box.SendKeys k.Chord(k.CtrlKey, "a")

ヘッドレス・起動オプションを付ける

画面を出さずに裏で動かす(ヘッドレス)や、起動時のオプションを足したいときは、StartChrome のあとに CreateCapabilities で設定オブジェクトを作って、OpenBrowser に渡します

Dim driver As New WebDriver
driver.StartChrome

Dim caps As WebCapabilities
Set caps = driver.CreateCapabilities

' 画面を出さずに動かす(ヘッドレス)
caps.RunInvisible

' 起動オプションを足す
caps.AddArguments "--start-maximized"

' ダウンロード先と確認ダイアログの設定
caps.SetDownloadPrefs downloadFolderPath:="C:\dl\", promptForDownload:=False

' 設定を渡してブラウザを開く
driver.OpenBrowser caps

ヘッドレスにすると画面が出ないぶん動作が軽くなるので、定期実行や大量処理のときに向いています、ただ動作確認のうちは、画面を出したまま挙動を見ながら作るほうが安心です

便利なヘルパー関数を用意しておく

同じような書き方を毎回くり返すなら、自分用の小さな関数(ヘルパー)にまとめておくと、コードがぐっと読みやすくなります、ここでは私がよく使うものを紹介します、どれも検証済みのメソッドだけで組んでいるので、そのままコピペして使えます

TryFind … 無ければ Nothing を返す(エラーを出さない)

さっき書いたとおり FindElement は要素が無いとエラーになります、TryFindIsPresent を使って、見つかれば要素を、無ければ Nothing を返します、「あるかどうか分からない要素」を扱うときの土台になります

' 存在チェック付き取得(無ければNothing・エラーを出さない)
Public Function TryFind(driver As WebDriver, ByVal sel As String, _
                        Optional ByVal waitMS As Long = 3000) As WebElement
    Dim el As WebElement
    If driver.IsPresent(By.CssSelector, sel, waitMS, , el) Then
        Set TryFind = el
    Else
        Set TryFind = Nothing
    End If
End Function

WaitFor … 出るまで待って、ダメなら明示エラー

WaitFor は逆に、「この要素は確実に出るはず」という場面用です、時間内に出れば返し、出なければ「何のセレクタで失敗したか」が分かるエラーを出します、原因が分からないまま止まるより、メッセージが残るぶんデバッグがラクになります

' 要素が出るまで待って取得(ダメなら明示エラー)
Public Function WaitFor(driver As WebDriver, ByVal sel As String, _
                        Optional ByVal timeoutMS As Long = 10000) As WebElement
    Dim el As WebElement
    If driver.IsPresent(By.CssSelector, sel, timeoutMS, , el) Then
        Set WaitFor = el
    Else
        Err.Raise vbObjectError + 513, , "要素が見つかりません: " & sel
    End If
End Function

Css … By.CssSelector を短く書くラッパー

毎回 driver.FindElement(By.CssSelector, “…”) と書くのは長いので、Css(driver, “…”) だけで済むようにしたラッパーです、CSSセレクタに寄せる方針と相性がよく、本文のコードがかなりスッキリします

' By.CssSelector 短縮ラッパー
Public Function Css(driver As WebDriver, ByVal sel As String) As WebElement
    Set Css = driver.FindElement(By.CssSelector, sel)
End Function

' 使うとこう書ける
' Css(driver, ".btn-search").Click

SafeClick … 存在・表示・有効を確かめてからクリック

クリックは、要素はあっても「まだ表示されていない・押せない状態」だと失敗することがあります、SafeClickIsPresent で存在を確かめ、さらに IsDisplayedIsEnabled が True のときだけ Click します、押せないときに止まらず素通りするので、流れが安定します

' 安全クリック(存在+表示+有効を確認してClick)
Public Sub SafeClick(driver As WebDriver, ByVal sel As String, _
                     Optional ByVal waitMS As Long = 5000)
    Dim el As WebElement
    If driver.IsPresent(By.CssSelector, sel, waitMS, , el) Then
        If el.IsDisplayed And el.IsEnabled Then el.Click
    End If
End Sub

スクロール系 … 最下部まで・要素を画面中央へ

スクロールまわりも、ExecuteScriptでJavaScriptを走らせる独自functionにしておくと便利です、よく出番があるのが、遅延読み込みや無限スクロールのページで最下部まで自動で送って中身を出し切る処理と、目的の要素を画面の真ん中まで持ってくる処理です

' 最下部までオートスクロール(無限スクロール・遅延読み込み対策)
' 高さが伸びなくなったら読み切ったとみなして止まる
Public Sub ScrollToBottom(driver As WebDriver, _
                          Optional ByVal maxLoops As Long = 30, _
                          Optional ByVal waitMS As Long = 800)
    Dim lastH As Double, newH As Double, i As Long
    lastH = driver.ExecuteScript("return document.body.scrollHeight;")
    For i = 1 To maxLoops
        driver.ExecuteScript "window.scrollTo(0, document.body.scrollHeight);"
        driver.Wait waitMS
        newH = driver.ExecuteScript("return document.body.scrollHeight;")
        If newH = lastH Then Exit For
        lastH = newH
    Next i
End Sub

' 対象の要素を画面の中央へスクロール
Public Sub ScrollToCenter(driver As WebDriver, el As WebElement)
    driver.ExecuteScript "arguments[0].scrollIntoView({block:'center', inline:'center'});", el
End Sub

ScrollToBottomは、ページの高さが伸びなくなったら「もう読み切った」と判断して止まる作りなので、件数の読めない無限スクロールでも空回りしません、ScrollToCenterは要素を上端ではなく中央に置くので、固定ヘッダーに隠れて押せない…みたいなクリック事故も減らせます

ハマりどころとTips

最後に、書きはじめのうちにつまずきやすいところを、軽くまとめておきます

  • 閉じ忘れに注意 … 処理の終わりに CloseBrowserShutdown を呼ばないと、裏でWebDriverが残ることがあります、処理の最後に毎回呼ぶ形にしておくのがおすすめです
  • まず ImplicitMaxWait をセット … 「要素がまだ無い」系のエラーは、最初に ImplicitMaxWait を入れておくだけでかなり減ります
  • 存在チェックは IsPresent で … 無いかもしれない要素を FindElement で取りにいくとエラーになります、迷ったら IsPresent で分岐するのが安全です
  • メソッド名の取り違えに注意 … 探すのは By.CssSelector(By.Cssではない)、テキストは GetText、CSS値は GetCSSProperty です、名前が紛らわしいので、ここはコピペで間違いを防ぐのがラクです

このあたりを押さえておけば、たいていの「動かない…」はかなり減らせると思います、あとは作りたい処理に合わせて、ここまでのコードを組み合わせていく感じです

まとめ

SeleniumVBAの実践コードを、ひととおり並べてみました、最後にポイントを整理しておきます

  • 要素の探し方は By.CssSelector に寄せると覚えることが減る、リンク文字やテキスト検索はCSS+ループの独自functionで再現でき、XPathが要るのは親への逆引き(“..”)だけ
  • 操作は Click / SendKeys / GetText / GetAttribute が基本、待機は ImplicitMaxWait をまずセット
  • 無いかもしれない要素は IsPresent で確認、プルダウンや複数要素・スクショ・JS実行も専用メソッドで書ける
  • よく使う処理は TryFind / WaitFor / Css / SafeClick のようにヘルパー関数化しておくと読みやすい

まだ導入が済んでいない方は、まず「Excelでもブラウザ操作!SeleniumVBAの使い方」で土台を作ってから、この記事のコードを動かしてみてください

ドライバーの更新まわりで困ったときは「VBAでChromeDriverを自動更新する方法」、これまでの定番だったSeleniumBasicから入りたい方は「SeleniumBasicの導入方法」も合わせて読んでもらえると、VBAでのブラウザ自動化がだいぶ見通しよくなると思います

📚 VBAの独学に効く本PR
Excel VBA塾【動画×本で学ぶ!】

Excel VBA塾【動画×本で学ぶ!】

たてばやし淳

パーフェクトExcel VBA

パーフェクトExcel VBA

高橋宣成

Excel マクロ&VBA[実践ビジネス入門講座]完全版 第3版

Excel マクロ&VBA[実践ビジネス入門講座]完全版 第3版

国本温子

私のおすすめからランダムで3冊を表示しています


最後に・・・

クラウドワークスココナラでお仕事受け付けています!

PythonとExcelを中心に仕事に役立つ業務ツールや自動化、スクレイピングツールの作成を受注していて、クラウドワークスでは気が付けば100件以上のお仕事を受注してきました!

会社員をやりながらの副業なので時間の捻出は相応ですが、クライアントの方々と近い立場でこちらからも提案しながら活動していますのでお悩みあれば是非ご相談ください

ココナラのプロフィールページへ

"ココナラ"に新規登録する際は1,000Pもらえる紹介コード使ってください

78E62K

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAとPythonを中心にユーザー側でできるITを自己学習しているので備忘録半分、学習履歴を残して同じ道を辿る人の参考になればとブログを始めました

副業でスクレイピングツール作成を中心にできることを色々やっていますのでご相談いただけるとありがたいです!


クラウドワークスのページへ


ココナラのページへ

コメント

コメント一覧 (2件)

  • はじめまして。sele_chanと申します。
    私は主にXParthを使っているのですがシャドウルート内検索では使えないので、その代替としてCssSelectorを使っているのですが、あまり理解していませんでしたので参考にしたいと思います。

    • シャドウルートはXPathはNGでしたね
      好みもある気がしますが、XPathよりわかりやすい気がするのでCssSelectorおススメです!

コメントする

目次