LoginSignup
11
14

【VBA】セレニウムなし、WebDriverなし、VBA-JSONなしでクローム操作にチャレンジしてみた①

Last updated at Posted at 2022-05-21

きっかけ

半年~1年前に会社で「Selenium」と「WebDriver」の使用申請をしたところ却下されました。

しばらく、放置していたのですが、IEのサポート終了が迫ってきたこともあり、
なんかいい方法ないかなーとおもってネットで探していたら、以下の記事・・・

・・・をみつけ、記事の中でEdge操作ツール(Selenium,WebDriver不使用)が紹介されていました。


ここで初めて ChromeDevToolsProtocol (以下CDP)の存在を知り、それを使えば

Selenium,WebDriverなしでクロームが操作できる!!

ということを知りました。

記事で紹介されているツールを会社で使用申請しても、却下されるのは目に見えているため、
「CDPについて調べて自分で作ってみよう!」と思ったのが、チャレンジのきっかけです。

<補足>

※記事で紹介されているEdge操作ツール自体は、Edgeとの通信にパイプ処理が使われており、
個人的にはまだパイプについて詳しく学習したことがなく
「パイプ???」
というレベルだったので、レベルが高すぎて理解できず、全然参考に出来ませんでした・・・

そのため、今回はCDP通信する際にスタンダードだと思われるWebSoketを使用しての実装にチャレンジしました。

また、現在完成している機能としては、「クロームとの通信開始」「URLを開く」「タブを閉じる」程度の状況です。

そのためこの記事の内容としては、ChromeとWebSocketでCDP通信を行い、指定のURLを開き、タブを閉じるところまでの方法をご紹介する内容になります。

※最終的にはライブラリっぽいものを作りました。(2020/8)
実装の詳細よりも使えるものに興味がある方はこちらへ

概要

以下の手順でChromeを操作することができました。

  1. Chrome起動時に「--remote-debugging-port=9222」オプションをつけて起動する。
    ⇒ローカル内でChromeがリモートホストとして起動する。

  2. 「localhost:9222/json」(1.で起動したクローム)に対して、GetメソッドでHTTP通信を行う。
    ⇒開いているタブに関する情報がJSON形式のレスポンスとして返ってくる。
    ※そのJSONの中に「WebSocketDebuggerURL」という、CDPでChromeに指示を与えるために
      必要な通信先や「ID」というブラウザ内の操作対象を指定する項目が含まれています。

  3. 「WebSocketDebuggerURL」にまずHTTP通信を行う。

  4. HTTP通信からWebSocket通信にUpGradeする。
    ※CDPでのやりとりにはWebSocket通信が必要なため

  5. CDPで定義されている「Method」をJSONのオブジェクト形式にして、WebSocket通信で投げる。

実装概要

以下のように実装を行っております。

  1. WSHオブジェクトを使用して、クローム起動

  2. XMLHttpオブジェクトを使用して「localhost:9222/json」Http通信(Get)を行う
    VBAの文字列操作関数を使用して、レスポンス(JSON)から必要情報取得

  3. WindowsAPI(WinHttp関連のAPI)を使用して「WebSocketDebuggerURL」にHttp通信を行う。

  4. WindowsAPI(WinHttp関連のAPI)を使用して、HTTP通信をWebSockt通信にUpGradeさせる。

  5. WindowsAPI(WebSocket関連のAPI)を使用して、CDPメソッドの送信、レスポンスの受信を行う。

実装詳細

※注意※

コードは本来、全てクラスで実装しますが、わかりやすさのため、
以下のような記述をしています。
  • 該当箇所のみを標準モジュールに記述したような形式でコード例を記載
  • リテラルは本来は定数宣言しますが、そのままリテラルで記載
  • グローバル変数なんてもちろん本来は使用しませんが、コード例では使用。
    (クラス内でメンバ変数宣言、およびプロパティ設定するものとお考え下さい)

<実装1.WSHオブジェクトを使用して、クローム起動>

vba
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)

Private Sub StartChrome()
    CreateObject("WScript.Shell").Run _
        """chrome.exe"" --remote-debugging-Port=9222", 1, False
    Sleep 2000
End Sub

これはそのまんまですね。クロームをオプション付きで起動しているだけです。
結果:ローカル内でクロームがリモートサーバーとして起動します。


<実装2.XMLHttpオブジェクトを使用して「localhost:9222/json」にHttp通信(Get)を行いJSON取得>

vba
Private Function HTTPGetToChromeDebuggingPort() As String
    Dim client As Object
    Set client = CreateObject("MSXML2.ServerXMLHTTP")
    client.Open "GET", "http://127.0.0.1:9222/json"
    client.SetRequestHeader "Content-Type", "application/json"
    client.Send
    HTTPGetToChromeDebuggingPort = client.responsetext
End Function

これもそのままです。
1.で起動したクロームのデバッグポート+「/json」というURLに、XMLHTTPでGet通信してるだけです。
今回のコード例のように「/json」というパスに対してGetすると、クローム側からはレスポンスとして、開いているタブに関する情報が、以下のようなJSON形式で返ります。

参考:戻り値のJSONのイメージ(青線箇所=項目名、赤線箇所=取得したい情報)
image.png

※ちなみに「/version」というパスにGetすると、ブラウザ自体の情報が取得できたりします。

<実装2.の続き:VBAの文字列操作関数を使用して、JSONから必要情報取得>

vba
Public resourcePath_ As String
Public targetID_ As String

Private Sub SetTragetInfo(JSON As String)
    '1WebDebuggingURLの取得
    Dim startNum As Long, URLLength As Long
    startNum = InStr(JSON, "ws://")
    URLLength = InStr(JSON, "}") - startNum - 2
    Dim WebDebuggingURL As String
    WebDebuggingURL = Replace(Mid(JSON, startNum, URLLength), """", "")
    
    '2後々必要になるので、WebDebuggingURLのパス部分のみ別途取得
    resourcePath_ = Mid(WebDebuggingURL , 20)
    
    '3後々必要になるので、更にresourcePath_から取得
    targetID_ = Replace(resourcePath_, "/devtools/page/", "")
End Sub

今回VBA-JSONは使わない前提なので、JSON関連の文字列処理は後回しにしており、いったん先に進む目的でこんなゴミコードで済ませてます。

一旦コードのゴミさ加減には目をつぶって、このステップでは後々必要になる「リソースパス」と「操作対象を示すID情報」を取得しておきたいんだなという趣旨をご理解ください。

ちなみにWebDebuggerUrlは構成として、
image.png
赤線部=ループバックアドレス
青線部=リソースパス
オレンジ線部=ターゲットID(操作対象を示すID情報)
となっており、欲しいのはリソースパスとターゲットIDだけです。


次の実装からWinAPIを使用し難易度が上がるのですが、そのせいか記事が長くなってきており、続けて記載すると記事全体がとても長くなってしまうので、いったんここで切ります。


続きはこちらです。

11
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
14