0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UWSCRAdvent Calendar 2023

Day 24

UWSCRの新機能:ブラウザ操作

Last updated at Posted at 2023-12-23

UWSCではCOMインターフェースを介してのInternet Explorer操作が主流でしたが、UWSCRでは標準機能としてGoogle ChromeおよびMicrosoft Edgeの自動操作に対応しています。

UwscWebDriverなんてのもありましたが、これはすでに開発を終了しています。

UWSCRのブラウザ操作は

  1. ブラウザを起動または再接続しBrowserオブジェクトを得る
  2. 操作したいタブのTabWindowオブジェクトを得る
  3. タブ上のdocumentオブジェクトからDOMへアクセスする

という流れでブラウザの操作を行います。擬似的なDOMのオブジェクトを得られるため、使い勝手はUWSCのIE操作に近くなっています。

UWSCRのブラウザ操作にはChrome Devtools Protocolが使われています。MSEdgeもChromiumベースとなったことでこれをサポートしています。

ブラウザの起動およびBrowserオブジェクトの取得

以下の組み込み関数を実行するとブラウザの起動、または以前起動したブラウザへの再接続を試み成功した場合にBrowserオブジェクトを返します。

BrowserControl()

ブラウザ種別を示す定数とブラウザのデバッギングポート番号を指定することでブラウザを起動または再接続します。再接続はすでに同一ポートが開かれている同一ブラウザが存在する場合に行われます。

// msedgeのBrowserオブジェクトを得る
msedge = BrowserControl(BC_MSEDGE) // デフォルトでは9222ポートを使用

// google chromeのBrowserオブジェクトを得る
// 同じポートは使えないので別の値を指定
chrome = BrowserControl(BC_CHROME, 9223)

ブラウザのデバッギングポートが開放されている場合、そのポートを介してブラウザのあらゆる情報にアクセスできてしまいます。デバッギングポートが開かれたブラウザの取り扱いには注意してください。

BrowserBuilder()

BrowserBuilder関数はBrowserBuilderオブジェクトを返し、そのメソッドを介して起動時の設定等を行ってからブラウザを起動します。

builder = BrowserBuilder(BC_MSEDGE)
// ポートを変更
builder.port(9224)
// 起動時オプションを追加
// 拡張機能を無効にする
builder.argument('--disable-extensions')

// startメソッドで起動または再接続
// Browserオブジェクトを返す
msedge = builder.start()

設定用のメソッドはBrowserBuilderオブジェクト自身を返すため以下のようにメソッドチェーンによる記述もできます。

msedge = BrowserBuilder(BC_MSEDGE) _
    .port(9224) _
    .argument('--disable-extensions') _
    .start()

BrowserBuilderオブジェクトのメソッド

メソッド 引数 捕捉 再接続時
port 数値 ブラウザのデバッギングポートを変更 このポート番号のブラウザを対象とする
headless 真偽値 TRUEでヘッドレスブラウザを開く 無視されます
private 真偽値 TRUEでブラウザをプライベートモードで開く 無視されます
profile 文字列 プロファイルを保存するパスを指定 無視されます
argument 文字列 起動時オプションを追加する、複数追加する場合は複数回呼ぶ 無視されます
start なし ブラウザを起動しBrowserオブジェクトを返します

Browserオブジェクト

Browserオブジェクトは以下のプロパティ及びメソッドを持ちます。

名前 種別 詳細
count プロパティ 操作可能なタブの数を返します
tabs プロパティ 操作可能なタブのTabWindowオブジェクトを配列で返します
close メソッド ブラウザを閉じます
new メソッド 指定したURLを新しいタブで開き、TabWindowオブジェクトを返します
id メソッド ブラウザのウィンドウIDを返します

タブの取得

countでタブの数を、tabsでタブそのもののオブジェクトの配列を得られます。

if browser.count > 0 then
    tab = browser.tabs[0]
endif

また、ブラウザオブジェクトに直接インデックスするとtabsと同様に動作します。

if browser.count > 0 then
    tab = browser[0]
endif

newメソッドで新たにタブを開くこともできます。

dim tab
tabs = browser.tabs
if length(tabs) > 0 then
    tab = tabs[0]
else
    // 操作可能なタブがない場合は新しく開く
    tab = browser.new("about:blank")
endif

タブ一覧取得は重い

countおよびtabsプロパティを呼ぶとその都度ブラウザからタブ一覧を取得しているのですが、この処理はレスポンスがとても悪く数秒かかる場合があります。これはChrome Devtools Protocolによるもので現時点では改善の余地がありません。

ウィンドウIDの取得

ブラウザのウィンドウIDを使ってウィンドウ操作関数を実行できます。

ctrlwin(browser.id(), ACTIVATE)

TabWindowオブジェクト

TabWindowオブジェクトを介してタブを操作します。

初回のプロパティやメソッド呼び出しが遅い場合がある

初めてTabWindowのプロパティまたはメソッドを呼び出す際にブラウザのタブに対してWebSocketのセッションを張ります。その接続が確立されるまでに時間がかかる場合があります。

プロパティ

プロパティ 詳細
document RemoteObject ウェブページのwindow.documentに相当するオブジェクトを返します

メソッド

メソッド 引数 戻り値 詳細
navigate 文字列 真偽値 指定したURLを開く
reload 真偽値 真偽値 ページをリロードします、引数TRUEでキャッシュを無視します
wait 数値 真偽値 ページの読み込み完了まで最大で指定秒数まで待機します、デフォルトは10秒です
activate なし なし タブをアクティブにします
close なし なし タブを閉じます
dialog 真偽値, 文字列 なし alert, confirm, prompt等のダイアログを処理します
leftClick 数値, 数値 なし 指定座標に左マウスクリックイベントを送ります
rightClick 数値, 数値 なし 指定座標に右マウスクリックイベントを送ります
middleClick 数値, 数値 なし 指定座標に中央マウスクリックイベントを送ります
eval 文字列 JavaScriptの式を評価しその結果を返します

navigate, reload, wait

navigateおよびreloadメソッドはwaitメソッドと同様の待機処理を行います(最大で10秒待機)。そのためこれらのメソッド呼び出し時にはwaitメソッドはほぼ不要です。
waitメソッドが必要になるのはリンクをクリックし別のページが開かれた場合などです。

eval

JavaScriptの式を評価します。これにより

  • newキーワードで新たなオブジェクトを作る
  • コールバック用のJavaScript関数を作る

といったことが可能になります。

RemoteObject

RemoteObjectはDOMのオブジェクトに相当するオブジェクトです。RemoteObjectからはそのオブジェクトの実体が持つメソッドやプロパティにアクセスできます。TabWindowオブジェクトdocumentプロパティはdocumentオブジェクトを返すため、例えばquerySelectorを呼び出すことができます。

tab = browser[0]
document = tab.document
element = document.querySelector("#hoge")

RemoteObjectのプロパティやメソッドが返す値は、プリミティブな値であればUWSCRの値に変換され、それ以外のオブジェクトはすべてRemoteObjectになります。

RemoteObjectがどのようなオブジェクトであるかはRemoteObjectType関数で調べることができます。

print RemoteObjectType(browser[0].document)

サンプルコード

Seleniumテストページを操作するサンプルコードを掲載します。


// ブラウザを開く
chrome = BrowserControl(BC_CHROME)
// ブラウザをアクティブにする
ctrlwin(chrome.id(), ACTIVATE)

// 新しいタブでSeleniumのテストページを開く
tab = chrome.new('http://example.selenium.jp/reserveApp_Renewal/')
// ドキュメントを取得しておく
document = tab.document

// 宿泊日を入力
// 3日後の日付を得る
date = format(gettime(3, , G_OFFSET_DAYS), '%Y/%m/%d')
// 日付を入力
document.querySelector('#datePick').value = date
document.querySelector('#reserve_year').value = G_TIME_YY4
document.querySelector('#reserve_month').value = G_TIME_MM2
document.querySelector('#reserve_day').value = G_TIME_DD2

// 宿泊日数を選択
reserve_term = 2
document.querySelector("#reserve_term option[value='<#reserve_term>']").selected = TRUE

// 人数を選択
headcount = 5
document.querySelector("#headcount option[value='<#headcount>']").selected = TRUE

// プラン選択
// お得な観光プランをチェック
document.querySelector('#plan_b').checked = TRUE

// 名前入力
document.querySelector('#guestname').value = "おなまえ"

// 利用規約に同意して次へ をクリック
document.querySelector('#agree_and_goto_next').click()

// 読み込み完了を待つ
tab.wait()
// ページを移動したのでdocumentを取得しなおす
document = tab.document

// 合計金額を得る
price = document.querySelector('#price').textContent

// 確定ボタンを押す
document.querySelector('#commit').click()

msgbox("宿泊費用は<#price>円でした")

// タブを閉じる
tab.close()
0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?