たとえば id が “search” の検索ボックスを探すなら、こう書けます、By.Name や By.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']")
' リンクを表示文字で探す(全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の要素をループして表示文字で探す(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では無理・XPathの ".." を使う)
Dim child As WebElement, parent As WebElement
Set child = driver.FindElement(By.CssSelector, "#price")
' その要素を起点に ".." で親要素を取る
Set parent = child.FindElement(By.XPath, "..")
' 要素があるかを 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
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
' ページの表を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主導のブラウザ自動化が組めます
' 表示中の画面を保存
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"
' 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);"
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")
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
' 存在チェック付き取得(無ければ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
' 要素が出るまで待って取得(ダメなら明示エラー)
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
' 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
' 安全クリック(存在+表示+有効を確認して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
' 最下部までオートスクロール(無限スクロール・遅延読み込み対策)
' 高さが伸びなくなったら読み切ったとみなして止まる
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
コメント
コメント一覧 (2件)
はじめまして。sele_chanと申します。
私は主にXParthを使っているのですがシャドウルート内検索では使えないので、その代替としてCssSelectorを使っているのですが、あまり理解していませんでしたので参考にしたいと思います。
シャドウルートはXPathはNGでしたね
好みもある気がしますが、XPathよりわかりやすい気がするのでCssSelectorおススメです!