WebElementから指定したH1、H2、H3のタグは以下のコードで出来ます。
FindElementsByTag("H1") FindElementsByTag("H2") FindElementsByTag("H3")
しかし、H1~H3のタグを出てきた順に取得することはできません。
FindElementByTagでORが使う事ができれば解決するのですが・・・
解決策1:OR条件が使える Xpathを使う
以下のXpathを指定すると FindElementsByXpath でコレクションが取得できるので、For Eachで出てきた順にタグを取得することができます。
//*[ self::h1 and not(.=preceding::h1)
or self::h2 and not(.=preceding::h2)
or self::h3 and not(.=preceding::h3) ]
実際のコーディング例
' Xpathでマッチングさせる方法
Function GetHeadingList(objWeb As Object, iLevel As String) As String
Dim i As Integer ' ループ用のカウンタ変数
Dim sXpath As String ' Xpath条件を格納する文字列
Dim sRtn As String ' 最終的な結果を格納する文字列
Dim elmLoop As WebElement ' ループ内で使用する要素を格納する変数
' 指定されたレベル(見出しの階層)までループ
For i = 1 To iLevel
If i <> 1 Then sXpath = sXpath & "or "
' Xpathで要素を選択する条件を構築
sXpath = sXpath & " self::h" & i & " and not(.=preceding::h" & i & ")"
Next
' Xpath条件に一致する要素を検索
For Each elmLoop In objWeb.FindElementsByXPath("//*[" & sXpath & "]")
' 見出しのタグ名とテキストを取得し、改行を整形して結果に追加
sRtn = sRtn & elmLoop.tagname & vbTab & Replace(Replace(elmLoop.Text, vbCr, ""), vbLf, "") & vbCrLf
Next
' 結果文字列の末尾の改行を削除して関数の結果として返す
GetHeadingList = Left(sRtn, Len(sRtn) - Len(vbCrLf))
End Function
解決策2:FindElementsByTagを使う
FindElementsByTagではなんと * が使えます。
* を指定すると全タグを順に取得できます。
ただし遅いです。
速度を気にせず、とにかく目的を達成できれば良いという時には有用な手段の1つになるかと思います。
以下コーディング例
' 全タグを調べる方法(遅い)
Function GetHeadingList2(objWeb As Object) As String
Dim elmLoop As WebElement ' ループ内で使用する要素を格納する変数
Dim sRtn As String ' 最終的な結果を格納する文字列
' ウェブページ上の全要素をタグごとにループ
For Each elmLoop In objWeb.FindElementsByTag("*")
Select Case UCase(elmLoop.tagname) ' 要素のタグ名を大文字に変換し比較
Case "H1", "H2", "H3", "H4", "H5", "H6" ' 見出し要素(h1, h2, h3, h4, h5, h6)を検出
' 見出しのタグ名とテキストを取得し、改行を整形して結果に追加
sRtn = sRtn & elmLoop.tagname & vbTab & Replace(Replace(elmLoop.Text, vbCr, ""), vbLf, "") & vbCrLf
End Select
Next
' 結果文字列の末尾の改行を削除して関数の結果として返す
GetHeadingList2 = Left(sRtn, Len(sRtn) - Len(vbCrLf))
End Function
使用方法
Sub Main()
' PhantomJSDriverオブジェクトを作成
Dim driver As New PhantomJSDriver
' 一時的な文字列変数を宣言
Dim sTmp As String
' ループを使って200回改行を出力(デバッグ用途)
Dim i As Integer: For i = 1 To 200: Debug.Print: Next
' PhantomJSDriverオブジェクトの操作を始める
With driver
' ウェブページを指定のURL(https://florentbr.github.io/SeleniumBasic/)にアクセス
.Get "https://florentbr.github.io/SeleniumBasic/"
' GetHeadingList関数を使用して、指定のレベル(4)の見出しリストを取得し、sTmp変数に格納
sTmp = GetHeadingList(driver, 4)
' 取得した見出しリストをデバッグ出力
Debug.Print sTmp
' 区切り線(50文字のハイフン)をデバッグ出力
Debug.Print String(50, "-")
' GetHeadingList2関数を使用して、見出しリストを取得し、sTmp変数に格納
sTmp = GetHeadingList2(driver)
' 取得した見出しリストをデバッグ出力
Debug.Print sTmp
End With
End Sub
実行結果
h1 Seleniumbasic h2 A Selenium based browser automation framework for VB.Net, VBA and VBScript h3 Description h3 Download h3 Bug tracker h3 Third party software h3 Tested environments h3 Authors and Contributors -------------------------------------------------- h1 Seleniumbasic h2 A Selenium based browser automation framework for VB.Net, VBA and VBScript h3 Description h3 Download h3 Bug tracker h3 Third party software h3 Tested environments h3 Authors and Contributors
全ソース
Option Explicit
Sub Main()
' PhantomJSDriverを使用するためのドライバーオブジェクトを作成
Dim driver As New PhantomJSDriver
' 一時的な文字列を格納する変数
Dim sTmp As String
' 200回のループを実行し、空行を表示する
Dim i As Integer
For i = 1 To 200
Debug.Print
Next
' PhantomJSDriverオブジェクトを使用して指定のウェブページにアクセスし、見出しリストを取得
With driver
.Get "https://florentbr.github.io/SeleniumBasic/" ' 指定URLにアクセス
sTmp = GetHeadingList(driver, 4) ' レベル4の見出しリストを取得
Debug.Print sTmp ' 見出しリストを表示
Debug.Print String(50, "-") ' 区切り線を表示
sTmp = GetHeadingList2(driver) ' 全ての見出しを取得
Debug.Print sTmp ' 見出しリストを表示
End With
End Sub
' Xpathでマッチングさせる方法で見出しリストを取得
Function GetHeadingList(objWeb As Object, iLevel As String) As String
Dim i As Integer
Dim sXpath As String
Dim sRtn As String
Dim elmLoop As WebElement
' 指定したレベルの見出しに対応するXPathを構築
For i = 1 To iLevel
If i <> 1 Then
sXpath = sXpath & "or "
End If
sXpath = sXpath & "self::h" & i & " and not(.=preceding::h" & i & ")"
Next
' 構築したXPathにマッチする要素を探し、テキストを取得して見出しリストを作成
For Each elmLoop In objWeb.FindElementsByXPath("//*[" & sXpath & "]")
sRtn = sRtn & elmLoop.tagname & vbTab & Replace(Replace(elmLoop.Text, vbCr, ""), vbLf, "") & vbCrLf
Next
GetHeadingList = Left(sRtn, Len(sRtn) - Len(vbCrLf))
End Function
' すべてのタグを調べる方法で見出しリストを取得
Function GetHeadingList2(objWeb As Object) As String
Dim elmLoop As WebElement
Dim sRtn As String
' すべてのタグをループして、H1からH6までの見出しのテキストを取得
For Each elmLoop In objWeb.FindElementsByTag("*")
Select Case UCase(elmLoop.tagname)
Case "H1", "H2", "H3", "H4", "H5", "H6"
sRtn = sRtn & elmLoop.tagname & vbTab & Replace(Replace(elmLoop.Text, vbCr, ""), vbLf, "") & vbCrLf
End Select
Next
GetHeadingList2 = Left(sRtn, Len(sRtn) - Len(vbCrLf))
End Function
コメント
FindElementsByTagではなんと * が使えます。
* を指定すると全タグを順に取得できます。
ただし遅いです。
のところ、とても驚きました。
なんと*が使えるんですね。
大変助かりました。