【2.演習編】RPAのセレクタ設定の詳細解説(Power Automate for desktop版)

learn rpa selector2

「1.導入編」の記事に続き、RPAのセレクタの詳細内容について解説したいと思います。RPAの安定したフローを構築するには、セレクタを十分に理解しておく必要があります。先ずは、下記の3点を押さえると良いでしょう。

  • 属性(Id、Class、Text、Name)
  • インデックス番号(eq)
  • 動的(変数埋め込み)
重要今回の解説では、RPAソフトの代表格でもあるPower Automate for desktopを使います。ただし、セレクタ設定の基礎知識を正しく身につければ、他のRPAソフトのセレクタ設定にも流用することができると考えます。特定のソフトに依存せずに、「セレクタ」自体の本質に目を向けるようにしましょう。

【検証1】一般的な場合

1-1. セレクタの形

導入編でも言及しましたが、ブラウザ上のUI要素のセレクタはHTMLのタグ名が連なった形になります。

タグ[属性="値"] > タグ > タグ > ・・・ > タグ[属性="値"]

例えば、こちらの検証用ページの【検証1】の「button2」ボタンのセレクタは下記のようになると思います。Power Automate for desktopのバージョンによっては、取得されるセレクタが異なるかもしれません。セレクタの確認方法は、導入編の「3. セレクタの確認方法」を参照してください。

section[Id="test1"] > div > ul > li > button[Text="button2"]

1-2. セレクタの経路

セレクタを理解するには、電車の経路をイメージすると分かりやすいです。左端が「出発駅」で、右端が「到着駅」です。その間に、各「通過駅」が配置されます。この経路に沿って、ターゲットのUI要素を特定します。

実際のWebページのHTMLコードとセレクタを対比しながら、どのようにターゲットのUI要素が特定されるのか順に確認していきます。ブラウザ上でHTMLコードを表示するには、F12ボタンをクリックし、選択ツールでターゲットのUI要素を指定します。

出発駅

先ずは「出発駅」がどこか確認します。基本的には出発駅はhtmlまたは任意のタグ名[Id=””]のどちらかになります。ターゲットのUI要素の祖先に特定のIDを持つ要素がある場合は、タグ名[Id=””]から始まります。そのような要素がない場合は、ルートであるhtmlから始まります。今回は出発駅は、section[Id=”test1″]です。

通過駅

出発駅から始まり、途中の通過駅を順に辿っていきます。今回の通過駅は「div」、「ul」、「li」の3つです。

到着駅(ターゲットのUI要素)

適切なセレクタであれば、最終的に「到着駅」、つまりターゲットのUI要素に辿り着きます。このUI要素をアクションで操作することになります。セレクタが不適切な場合は、到着駅に辿り着けずに、アクションでエラーが発生するかもしれません。

今回の到着駅は、button [Text=”button2″]です。タグ名はbuttonでText属性を持っています。Text属性の値は「button2」です。つまり、button2の文字列が表示されたbuttonタグを指すことになります。

1-3. 経路の必要性

ターゲットのUI要素がbutton2の文字列のボタンであるなら、セレクタは到着駅のbutton [Text=”button2″]だけでも良い気がします。確かに、対象のWebページ内に、button2の文字列のボタンが1つしかないのであれば、それでも上手くいくかもしれません。しかし、button2の文字列のボタンが複数ある場合は、最終的にどのボタンを指すか曖昧になります。

通常、類似したUI要素が複数あった場合でも、ターゲットのUI要素を正しく識別するために、セレクタは出発駅と通過駅を含む経路の形を取ります。到着駅の1点による特定よりも、経路による特定の方が信頼度は高くなります。

【検証2】ID属性のピンポイント指定

一般的に、セレクタは複数のタグが連なった形を取ります。傾向としては、セレクタが長くなるほどWebページの構造変化に影響を受けやすくなります。では、セレクタは短いほど良いのかと言うと、そうとも限りません。ターゲットのUI要素を特定するための情報量が減るため、極端に短いのも好ましくないです。

ただし、例外的にターゲットのUI要素にidがあれば、セレクタは極端に短くすることができます。idはWebページ上の要素を一意に特定できるため、セレクタが短くても特に問題ないです。

では、実際に確認してみましょう。検証用ページの【検証2】の「orange」ボタンのセレクタは下記のようになると思います。セレクタの確認方法は、導入編の「3. セレクタの確認方法」を参照してください。

button[Id="btn-orange"]

タグ名はbuttonでId属性を持っています。Id属性の値は「btn-orange」です。つまり、btn-orangeのidを持ったbuttonタグを指すことになります。とてもシンプルなセレクタになります。

実際のWebページのHTMLコードも確認してみると、「orange」ボタンの要素には「btn-orange」のidが振られているのが分かります。確かに一致しています。

【検証3】Text属性が使えない場合

【検証1】では、到着駅がbutton[Text=”button2″]でした。このText属性はターゲットのUI要素の特徴(文字列)を表すため直感的に分かりやすく、とても便利な属性です。しかし、いつでもこのText属性が使える訳ではありません。

では、実際にText属性が使えないケースを確認してみましょう。検証用ページの【検証3】の「mobile」ボタンのセレクタは下記のようになると思います。セレクタの確認方法は、導入編の「3. セレクタの確認方法」を参照してください。

section[Id="test3"] > div > ul > li > button:eq(2)

3-1. インデックス番号(eq)による指定

【検証3】のボタンにはアイコンマークの要素を付けたことにより、Text属性は使えなくなっています。その代わりに、セレクタの到着駅のbuttonには「:eq(2)」が付与されています。eqはインデックス番号を表し、0から数えます。つまり、eq(2)は3番目のボタンを指しています。実際に、ターゲットのUI要素の「mobile」ボタンは上から数えて3番目なので一致しています。

補足厳密には、「:eq(2)」は直前のbuttonタグだけに掛かっているのではなく、「section[Id=”test3″] > div > ul > li > button」の全体に掛かっています。「section[Id=”test3″] > div > ul > li > button」のセレクタを検索し、見つかったすべての要素に対して、何番目かを指定することになります。

3-2. インデックス番号の注意点

Text属性が使えない場合、eqのインデックス番号の指定が使われることがあります。しかし、インデックス番号を使用する際は、少し注意が必要です。

インデックス番号の指定は、Webページの構造変化に影響を受けやすいです。セレクタの経路の途中に要素が追加または削除されると、インデックス番号が変化するので、間違った要素を指してしまうリスクがあります。

では、インデックス番号以外の方法はないのでしょうか。Id属性ほど確かではないですが、Class属性を使うことで、インデックス番号に依存せずに済みます。

3-3. Class属性による指定

では、実際にインデックス番号から、Class属性に変更してみましょう。なお、いつでもClass属性が使える訳ではありません。Webページ上のターゲットのUI要素に、明確な特徴となるclassが付与されていることが前提条件です。

先ずは、セレクタ情報の編集画面で、タグのリストの最後にある「Button ‘mobile’」を選択します。タグの属性で、Ordinal(eq、つまりインデックス番号)のチェックボックスをOFFにして、代わりにClassのチェックボックスをONにします。画面下の「セレクタをプレビューする」を確認すると、下記のようなセレクタに変化しています。

section[Id="test3"] > div > ul > li > button[Class="btn btn-mobile"]

buttonの後ろにあった「:eq(2)」が消えて、代わりに[Class=”btn btn-mobile”]が付きました。Class属性の値は、「btn」と「btn-mobile」の2つです。複数の値を付ける場合は、半角スペースで区切ります。特に重要となるのは、「mobile」ボタンの特徴を明確に表している「btn-mobile」の方です。「btn」の方は、あってもなくても特に影響はないでしょう(button[Class=”btn-mobile”]でもOK)。

実際のWebページのHTMLコードも確認してみると、「mobile」ボタンの要素には「btn」と「btn-mobile」のclassが振られているのが分かります。確かに一致しています。

3-4. Class属性の注意点

今回のように、ターゲットのUI要素に特徴のあるclassが付与されている場合は、インデックス番号の代わりにClass属性による指定が可能です。

メリットとしては、Webページの構造変化の影響を受けにくくなることです。ただし、classはidとは違い、Webページ上のUI要素を一意に特定することはできません。つまり、同じ値のclassを複数のUI要素に付けることができます。従って、ターゲットのUI要素の特徴を明確に表すclassがある場合に限り、Class属性を使用しましょう。

【検証4】Text属性が変化する場合

セレクタにText属性は使えるが、条件によって値が変化してしまうケースを確認してみましょう。検証用ページの【検証4】の日時の文字列のセレクタは下記のようになると思います。セレクタの確認方法は、導入編の「3. セレクタの確認方法」を参照してください。

section[Id="test4"] > p[Text="2024/9/12 9:23:55"]

Text属性の値に日時の文字列が含まれていることが分かります。検証用ページにアクセスする度に日時が変化するようにしているので、Text属性の値も毎回変化します。この状況ではセレクタが正しく認識されなくなってしまいます。このように、セレクタに固有情報が入ってしまうと、それ以外のケースでは合致しなくなります。つまり、融通の利かないセレクタになってしまうのです。

では、このようなケースはどのように対応するべきでしょうか。1つの方法としては、セレクタから固有情報を排除することです。しかし、セレクタの情報量を削ることは、UI要素を特定する精度が下がることを意味します。従って、別の属性を付与するなどして補ってあげる必要があります。この考え方はとても重要なので、しっかりと頭に入れておきましょう。

4-1. 固有情報の排除

日時が変化しても問題ないように、実際にセレクタを編集してみましょう。セレクタ情報の編集画面で、タグのリストの最後にある「Paragraph ‘2024/9/12 9:23:55’」を選択します。タグの属性で、Text属性のチェックボックスをOFFにします。画面下の「セレクタをプレビューする」を確認すると、下記のようなセレクタに変化しています。

section[Id="test4"] > p

到着駅のpタグのText属性が消えているのが分かります。この状況で一度、セレクタのテストを試してみましょう。上部メニューの「テスト」ボタンを押して、対象のWebブラウザのタブを指定してください。すると、Webページ上で、「下記の日時を取得してください。」のテキスト部分がハイライトされたと思います。

元々のターゲットは「日時」のテキストだったので、UI要素の認識に失敗しています。これは前述した通り、セレクタの情報量を削ったことで特定の精度が下がり、別のUI要素を誤認識してしまったのです。

4-2. 特定精度の補完

では、どのようにして特定精度を補完するのでしょうか。今回のケースでは、ターゲットのpタグのclassにtimeが振られているので、これを活用することにします。

セレクタ情報の編集画面で、タグのリストの最後にある「Paragraph ‘2024/9/12 9:23:55’」を再度選択します。タグの属性で、Class属性のチェックボックスをONにします。画面下の「セレクタをプレビューする」を確認すると、下記のようなセレクタに変化しています。

section[Id="test4"] > p[Class="time"]

この状況で、もう一度、セレクタのテストをしてみましょう。今度は、正しく「日時」のテキスト部分がハイライトされたと思います。なお、前述した通り、Class属性による指定は完璧ではないので注意が必要です。ターゲットのUI要素の特徴を明確に表すclassを使用するようにしましょう。

補足なお、Class属性の代わりに、下記のようにeq(インデックス番号)による指定もできます。しかし、前述の通り、インデックス番号による指定は、Webページの構造変化に脆弱なので十分に注意しましょう。

section[Id=”test4″] > p:eq(1)

【検証5】動的に指定する場合

実行時に動的にターゲットのUI要素を指定したいケースがあります。例えば、ユーザーから入力された値に応じて、クリックするボタンを切り替える場合などです。これを実現する1つの方法としては、セレクタに変数を埋め込み、ターゲットのUI要素を動的に変更します。

では、実際に試してみましょう。検証用ページの【検証5】のラジオボタン「ヤギ」のセレクタは下記のようになると思います。セレクタの確認方法は、導入編の「3. セレクタの確認方法」を参照してください。

section[Id="test5"] > div > label > input[Name="test"]:eq(2)

到着駅はinputタグです。これにName属性とeq(インデックス番号)が付与されています。Name属性はHTMLのinputタグのname属性のことです。値は「test」で、このラジオボタンのグループ名として付けられたものでしょう。ラジオボタンの特徴を表すものなので、Name属性はこのまま使用することにします。

問題はeq(インデックス番号)です。eq(2)は3番目なので、左から3番目のラジオボタンを指しています。確かに、「ヤギ」は左から3番目にあります。

変数の埋め込み

では、指定する項目を動的に変更するにはどうすれば良いでしょうか。1つの方法としては、eqのインデックス番号を変化させることです。eq(%num%)などのように、インデックス番号に変数を埋め込みます。ただし、インデックス番号による指定は、ラジオボタンの配置の変化に対して脆弱です。

インデックス番号よりも、動物の名前による指定の方が分かりやすいと思います。では、動物の名前による指定に変更します。セレクタ情報の編集画面で、タグのリストの最後にある「Input radio ‘test’」を選択します。タグの属性で、Ordinal(eqのこと)のチェックボックスをOFFにします。そして、Value属性のチェックボックスをONにします。画面下の「セレクタをプレビューする」を確認すると、下記のようなセレクタに変化しています。

section[Id="test5"] > div > label > input[Name="test"][Value="ヤギ"]

このままでは、毎回、「ヤギ」を選択してしまうので、Value属性の値を変数に置き換えます。タグの属性で、Value属性の値をダブルクリックして、%animal%を入力します(既に作成済みの変数を配置してもOK)。セレクタは下記のように変化します。

section[Id="test5"] > div > label > input[Name="test"][Value="%animal%"]

この状況で一度、セレクタのテストを試してみましょう。上部メニューの「テスト」ボタンを押して、対象のWebブラウザのタブを指定してください。次に、「変数を持つセレクタ」の画面が表示されます。テストする際に、毎回、変数の値を入力する必要があります。試しに、「ゴリラ」と入力してみます。すると、Webページ上で、「ゴリラ」のラジオボタンがハイライトされたと思います。何度かテストして、変数の値を変え、動的にラジオボタンが指定できるか確認してみてください。

実際に運用する際は、ユーザーからの入力値や、設定ファイルから読み込んだ値を変数に保存しておきます。そして、この変数をセレクタに反映させます。

「3.ケーススタディ編」の記事に続く。