はじめに
別記事(VBAとPowerShellで作るWebView2/CDP駆動のRPAエンジン)にて、VBAを司令塔とし、WebView2(Edge)を完全制御する自作RPAエンジンの基礎アーキテクチャを紹介しました。
今回はその実践編です。Webサイト(ポータルサイトやSaaS型の業務システムなど)を自動化する際、以下のような「モダンWeb特有の罠」に悩まされました。商用RPAの足元にも及ばない簡易なコードですが、VBAからモダンWebを操作する上で重宝したアプローチを紹介します。
レスポンシブデザインの罠
「検索」というボタンをクリックさせたいのに、裏側に隠れている「スマホ用の非表示メニュー」を誤って掴んでしまい、クリックが空振りする。
無限ロードの罠
裏で広告や非同期通信が走り続けているため、いつまで経っても「ページ読み込み完了」にならずタイムアウトする。
ブラックボックス化の罠
エラーで止まっても「なぜクリックできなかったのか(透明だったのか、画面外だったのか、要素が2つあったのか)」が分からない。
この罠を回避し、新人さんでも「画面に見えている文字を指定するだけ」で安全に自動化ができる『Robust DOM Utilities(DOM解析)』の簡易アプローチです。
こんな感じで
開発テストコード用のVBA(フォーム)で、手動での画面操作で必要な画面へ行き、(黄色のxxxでコメントを入力可)画面情報をエクスポート。
Debug] デバッグ・証跡モジュール
Export-WebHtml HTMLスナップショットExport-WebScreenshot 画面のPNGスクショ
Export-WebElementsToCsv 画面内の操作可能要素の属性をCSV化
Export-WebFrameTreeToCsv ネスト構造をツリー形式でCSV化
Export-WindowHierarchyToCsv OS上の全プロセスのハンドルをCSV出力
今度は、フォームの入力欄(画像の黄色いxxx部分)へ、画面に見えている文字(例:『ニュース』や『検索』)をそのまま打ち込み、TESTボタンを押すだけで、必要なCSSをエンジンが自動で探し出してくれます。
最後にログファイルを確認します。
アプローチ
確実なクリックを実現するために、JavaScriptを画面に注入して以下の「2段階フェーズ」で処理を行います。
フェーズ1:曖昧な指示から「一意のCSSセレクタ」を生成する(探索)
例えば、画面上にある「ニュース」という文字のリンクをクリックしたい場合、VBAからは以下のような曖昧なXPathを投げます。
//a[contains(., 'ニュース')]
すると、内部の解析エンジン(JS)は以下のように動きます。
1 画面内から条件に合う要素をすべて取得する。
2 取得した要素に対して、一つずつ「現在、本当に画面に見えているか(可視性)」をチェックする。
3 スマホ用メニューなどの「非表示(隠し要素)」を除外し、最初に見つかった「可視要素」を正解とする。
4 【ここ!】 その正解要素から、「他と被らず、かつ画面のレイアウト変更に強い」最適なCSSセレクタを逆生成する。
5 このセレクタの逆生成時、変化に強い属性から順番に探す独自の優先順位アルゴリズムを実装しています。
優先度 順位(アルゴリズム)
優先度 1位:id 属性 (存在すれば最強。例: #news-btn)優先度 2位:意味を持つ特定属性 (name, type, title, aria-label など。
...例: [aria-label="ニュースへ遷移する"])
優先度 3位:カスタムデータ属性 (VueやReactでよく使われる data-* 属性。
...例: [data-action="news"])
優先度 4位:DOMツリーの階層構造 (上記がない場合の最終手段。
...例: div.main > ul > li:nth-of-type(1) > a)
フェーズ2:安全なクリック(狙撃)
フェーズ1で作られた「一意のセレクタ」を使って、最終的なクリックを実行します。
ここでも単にクリックするのではなく、以下の安全確認を行います。
・要素が本当に存在するか確認。
・要素を画面中央へ確実にスクロール(scrollIntoView)。
・スクロール後、フローティングメニュー等の裏に隠れていないか最終の可視性チェック。
・問題なければネイティブクリックを実行。
最大のメリットは、「エンジンが何を考えて要素を選んだのか」がすべてログとして可視化されることです。
Yahoo●日本のトップページで「ニュース」というテキストを探させた際のログです。
rpaEngine.RunAction("Get-WebCssSelectorHint", CreateParams("XPath", "//a[contains(., 'ニュース')]"))
実行ログ: (Get-WebCssSelectorHint)
[Robust DOM] XPath検索: 合致する要素を 3 件発見しました。-> 候補 1: [可視〇] [aria-label="ニュースへ遷移する"]
-> 候補 2: [非表示] div.mobile-menu > a
-> 候補 3: [非表示] div.footer-links > a
[Robust DOM] 最適セレクタ: [aria-label="ニュースへ遷移する"]
rpaEngine.RunAction "Invoke-WebSafeClick", CreateParams("Selector", cssSelector, "TimeoutSec", 10)
実行ログ: (Invoke-WebSafeClick)
[Robust DOM] 探索開始: セレクタに合致する要素 1 件[Robust DOM] --- [候補 1/1] の検証を開始 ---
[Robust DOM] isVisible: 要素は可視状態です (幅: 168, 高さ: 30)
[Robust DOM] safeClick: スクロール前の可視性チェックを実行します。
[Robust DOM] safeClick: 画面中央へのスクロール(scrollIntoView)を試行します。
[Robust DOM] safeClick: スクロール後の最終可視性チェックを実行します。
[Robust DOM] safeClick: 対象要素へのネイティブクリックを実行します!
このように、「裏側の隠しリンク」を回避し、見えている要素だけを見つけ、可視性チェック(isVisible)で要素が見えているかどうかを判定します。
(JS関数は単に display: none だけでなく、サイズや透明度までチェックし、ダメだった理由をログに残します。)
勘のいい皆さんはフェーズ1 の 曖昧なXPathを投げます。で、やはり☜ と思われた思います。
別記事:【VBA×PowerShell】多段iframeとShadow DOMを透過する探索アルゴリズムと同じく、Shadow DOM内は探索できません。
タイトル通り(はじめの一歩)です。
とはいえ、一般的な業務システムやポータルサイトの多分8割方(希望)はこのアプローチで十分に自動化可能です。
どうしても届かない部分は、地道に Export-Web... などのデバッグツールと AIさん に頼りましょう。
おわりに
WebView2(Edge)を活用した自動化は、IE時代とは違う「非同期・レスポンシブ」への対応が必要でした。
自前のRPAエンジンでのコード作成などする時代では無いと思いますが、職場のPCには普通にあるVBA×powershellを使わないのも!?
これだけAIさんが身近で応援してくれて、無料で簡単な操作コードが作成出来る時代はありがたい。
参考にも成りませんがコードは、私のガラクタ倉庫(GITHUBさんのお世話なっています。)
Lib-WebSafeAction_v101(フェイルセーフ・安全クリック拡張)
RPAのテスト(フォームのテストコード) text
VBA×WebView2の需要も余り無いようですが、
フォームでのテストコードですが、マルチモニター環境だと上手く動いていましたが、ノートPC(シングルモニター環境)での「ユーザーフォーム最前面(ピン留め)が邪魔になる」点の修正が出来たら、また私の倉庫へ放り込んで於きます。
**コード検証・改修はお願いします。**バグ等を教えていただけたら幸いです。
