注意!記事中に「Chronium」という表記が出てきますが、正しくは「Chromium」です!
自身の戒めのためにこのまま残しますが、閲覧する方はお間違いないよう、よろしくお願い致します!
前置き
W3C の WebDriver の仕様を確認すると
なんだかNew Session
コマンドでオプションを指定して起動できそうなのです。
しかしながら、Edge を--disable-web-security
と--user-data-dir=C:\Chrome dev session
のオプションを適応して起動したかったのですが、如何せんどのようにリクエストボディを指定すれば良いのか、皆目見当が付きませんでした
そこで、Python & selenium
がWebDriver
に投げてるリクエストを取得しようと始めたのが
これだったんですね。
実は、上記のネタは、全てこのための布石だったのです。
ここから得られた、リクエストは下記の通り
{
"capabilities": {
"alwaysMatch": {
"browserName": "MicrosoftEdge",
"ms:edgeChromium": true,
"ms:edgeOptions": {
"args": [ "disable-web-security", "user-data-dir=C:\\Chrome dev session" ],
"extensions": [ ]
},
"platformName": "windows"
},
"firstMatch": [ {
} ]
},
"desiredCapabilities": {
"browserName": "MicrosoftEdge",
"ms:edgeChromium": true,
"ms:edgeOptions": {
"args": [ "disable-web-security", "user-data-dir=C:\\Chrome dev session" ],
"extensions": [ ]
},
"platform": "WINDOWS",
"version": ""
}
}
この
"args": [ "disable-web-security", "user-data-dir=C:\\Chrome dev session" ]
が当該部分でしょう。
という訳で、VBA から直接 WebDriver を利用して、オプションを適応した Edge 操作をしてみましょう!
VBAで実装
まず、WebDriver へのリクエストボディは、JSON で記述しますし、レスポンスもJSONで返ってきますが
文字列のままこれを扱うのは気が狂うので、VBA で使えるパーサーがあると良いです
私は上記のSet json_ParseObject = New Dictionary
を、片っ端からSet json_ParseObject = CreateObject("Scripting.Dictionary")
に変えましたが・・・
それから、以下の記事は、非常に役立ちました!おすすめ!
WebDriver を VBA で自動更新、って場合は、この記事が便利!
で、肝心なオプション付与した Edge の起動ですが
Public Const DriverFileName As String = "msedgedriver.exe"
Private Const Front_URL As String = "http://localhost:"
Private Const Back_URL As String = "/session"
Private Base_URL As String
'--disable-web-security と --user-data-dir=C:\Chrome dev session オプションを付与してEdgeを起動するサンプルルーチン
Public Sub Test_Sample()
Dim SessionID As String
Dim URL As String
Dim strXPath As String
Dim ElementID As String
'WebDriverのポート番号を指定し、BaseURLを生成
Base_URL = Front_URL & "9515" & Back_URL
'対象のURLを指定
URL = "https://www.yahoo.co.jp/" 'Yahoo のサイトを起ち上げます
'WebDriver実行
'WebDriver は VBA マクロを実行している Excel ファイルと同じフォルダにある前提です
CreateObject("WScript.Shell").Run ThisWorkbook.Path & "\" & DriverFileName, 0, False
'Edgr起動
SessionID = RunBrowser_and_Get_SessionID(Array("disable-web-security", "user-data-dir=C:\Chrome dev session"))
'URLに遷移
Transition_URL_Nav URL, SessionID
'EdgeWindowの最大化
Edge_Window_Maximized SessionID
'Yahoo天気のリンクのエレメントID取得
strXPath = "//*[@id=""ToolList""]/ul/li[12]/div/a"
ElementID = Get_ElementID_From_XPath(SessionID, strXPath, , False)
'Yahoo天気のリンクのクリック
Crick_ElementID SessionID, ElementID
End Sub
'ブラウザを起動し、セッションIDを得る
Private Function RunBrowser_and_Get_SessionID(Optional ByRef varOptionAry As Variant = Empty) As String
Dim Params As Object
Dim SessionID As String
Dim objAlwDic As Object
Dim objBrowserOptions As Object
Dim objOptions As Object
Dim strOptionAry() As String
Dim varNullArray() As Variant
Dim varArray(0 To 0) As Variant
Dim i As Long
RunBrowser_and_Get_SessionID = ""
Set Params = CreateObject("Scripting.Dictionary")
Set varArray(0) = CreateObject("Scripting.Dictionary")
If Check_Array(varOptionAry) Then
ReDim strOptionAry(LBound(varOptionAry) To UBound(varOptionAry))
For i = LBound(varOptionAry) To UBound(varOptionAry)
strOptionAry(i) = CStr(varOptionAry(i))
Next i
Set objAlwDic = CreateObject("Scripting.Dictionary")
Set objBrowserOptions = CreateObject("Scripting.Dictionary")
Set objOptions = CreateObject("Scripting.Dictionary")
objOptions.Add "args", strOptionAry
objOptions.Add "extensions", varNullArray
objBrowserOptions.Add "browserName", "MicrosoftEdge"
objBrowserOptions.Add "ms:edgeChromium", True
objBrowserOptions.Add "ms:edgeOptions", objOptions
objBrowserOptions.Add "platformName", "windows"
objAlwDic.Add "alwaysMatch", objBrowserOptions
objAlwDic.Add "firstMatch", varArray
Params.Add "capabilities", objAlwDic
Set objBrowserOptions = CreateObject("Scripting.Dictionary")
objBrowserOptions.Add "browserName", "MicrosoftEdge"
objBrowserOptions.Add "ms:edgeChromium", True
objBrowserOptions.Add "ms:edgeOptions", objOptions
objBrowserOptions.Add "platformName", "WINDOWS"
objBrowserOptions.Add "version", ""
Params.Add "desiredCapabilities", objBrowserOptions
SessionID = SendRequest("POST", Base_URL, Params)("value")("sessionId")
Else
Params.Add "desiredCapabilities", CreateObject("Scripting.Dictionary")
Params.Add "requiredCapabilities", CreateObject("Scripting.Dictionary")
SessionID = SendRequest("POST", Base_URL, Params)("sessionId")
End If
'ブラウザ起動
Set Params = Nothing
RunBrowser_and_Get_SessionID = SessionID
End Function
'指定URLに遷移
Private Sub Transition_URL_Nav(ByRef URL As String, ByRef SessionID As String)
Dim Params As Object
Set Params = CreateObject("Scripting.Dictionary")
Params.Add "url", URL
SendRequest "POST", Base_URL & "/" & SessionID & "/url", Params
Set Params = Nothing
End Sub
'EdgeWindowの最大化
Private Sub Edge_Window_Maximized(ByRef SessionID As String)
Dim Params As Object
Set Params = CreateObject("Scripting.Dictionary")
SendRequest "POST", Base_URL & "/" & SessionID & "/window/maximize", Params
End Sub
'XPathからElementIDを取得
Private Function Get_ElementID_From_XPath(ByRef SessionID As String, ByRef strXPath As String, Optional ByRef ElementID As String = "", Optional ByRef flgEdge As Boolean = True) As String
Dim Params As Object
Dim strElementID As String
Dim strElem As String
strElem = "ELEMENT"
If Not flgEdge Then strElem = "element-6066-11e4-a52e-4f735466cecf"
Get_ElementID_From_XPath = ""
Set Params = CreateObject("Scripting.Dictionary")
Params.Add "using", "xpath"
Params.Add "value", strXPath
If Len(ElementID) = 0 Then
strElementID = SendRequest("POST", Base_URL & "/" & SessionID & "/element", Params)("value")(strElem)
Else
strElementID = SendRequest("POST", Base_URL & "/" & SessionID & "/element/" & ElementID & "/element", Params)("value")(strElem)
End If
Set Params = Nothing
Get_ElementID_From_XPath = strElementID
End Function
'指定ElementIDをクリック
Private Sub Crick_ElementID(ByRef SessionID As String, ByRef ElementID As String)
Dim Params As Object
Set Params = CreateObject("Scripting.Dictionary")
SendRequest "POST", Base_URL & "/" & SessionID & "/element/" & ElementID & "/click", Params
End Sub
'これは【Excel VBAでSeleniumBasicを使わずにスクレイピングする】から利用させて頂いてます
'リクエストの送信
Private Function SendRequest(method As String, URL As String, Optional data As Object = Nothing) As Object
' クライアントの起動
Dim client As Object
Set client = CreateObject("MSXML2.ServerXMLHTTP")
' メソッドに応じてリクエスト送信
client.Open method, URL
If method = "POST" Or method = "PUT" Then
client.setRequestHeader "Content-Type", "application/json"
client.send JsonConverter.ConvertToJson(data)
Else
client.send
End If
' 送信完了待ち
Do While client.readyState < 4
DoEvents
Loop
' レスポンスをDictionaryに変換してリターン
Dim Json As Object
Set Json = JsonConverter.ParseJson(client.responseText)
Set SendRequest = Json
End Function
'配列化が空か?
Public Function Check_Array(ByRef aryVal As Variant) As Boolean
On Error GoTo Err_Check_Array
Check_Array = False
If IsEmpty(aryVal) Then
Exit Function
ElseIf Not IsArray(aryVal) Then
Exit Function
ElseIf UBound(aryVal) < LBound(aryVal) Then
Exit Function
End If
Check_Array = True
Err_Check_Array:
End Function
全然オプションを指定した意味が無いサンプルですが・・・
RunBrowser_and_Get_SessionID
は引数の起動オプションを指定しないと、Edgeモードで立ち上がります。
オプションを配列で指定すると、Chroniumモードで立ち上がります。
この辺の話は
を参考にしてください。そう、上記記事もこの記事の布石だったのです。
Get_ElementID_From_XPath
のflgEdge
引数は、省略や True の場合、Edgeモードに、False の場合は Chroniumモードに対応します。
次は、actions = ActionChains(driver)
あたりをseleniumを使わずにってネタで行きましょうかね・・・