AppleScriptでSafari上のフォーム入力を自動化してみた
MacのSafariで、多数のデータ入力を行う機会がありました。一つの画面で、繰り返し同じような入力を何度も行う作業です。自動化向きの作業だと感じましたので、いくらか試行錯誤し、AppleScriptで半自動化することにしました。
「半自動化」です。「完全自動化」ではありません。1件入力するごとに、画面表示内容などを確認しながら作業を進めたかったので、1件自動入力後、ユーザの応答待ちとなり、問題なければ、次の1件を自動入力するようにしました。
なお、AppleScriptは今回はじめて作成しました。なんとか私の環境では動作するレベルになりましたが、お作法的に正しい作りになっているのかなどは全く自信無いです。綺麗に作られているとは、夢にも期待しないで下さい。
AppleScirptによる半自動化 実施手順
操作方法は、こんな感じになります。
1.自動入力データを作成
後述するように自動入力用のデータファイルを作成して下さい。ファイルの場所は、スクリプトファイルと同じフォルダで、ファイル名を「data.txt」として下さい。
※現状ではファイル名固定にしてあります。
3.スクリプトファイルautoinput.scptを実行
私の作成した「autoinput.scpt」を、スクリプトエディタで開き、ウインドウ上部にある「実行」ボタンを押して下さい。Safariが前面表示され、データが自動入力されます。1件分の自動入力が終わると、2件目の自動入力を続行するかダイアログが表示されます。続行ボタンを押すと、2件目入力が始まります。
自動入力がすべて完了すると、完了ダイアログが出てきて終了です。
AppleScriptによる半自動化 スクリプト内容
3つのスクリプトファイルから構成されています。
全体を制御するスクリプト autoinput.scpt
--外部ファイルの呼び出し property fileModule : null property formModule : null tell application "Finder" set basePath to parent of (path to me) as text end tell set fileModule to load script file (basePath & "file.scpt") set formModule to load script file (basePath & "form.scpt") --テスト用ファイルパス --とりあえずファイル名固定にしてあります。 set filePath to basePath & "data.txt" tell application "Safari" activate --入力データ読み込み tell fileModule set commandArr to getCommandArrFromFile(filePath) end tell --Safari上のフォームへデータ入力を行う tell formModule play(commandArr) end tell activate display dialog "完了!" buttons {"OK"} default button 1 end tell
入力データを読み込むスクリプト file.scpt
property TAB_CHAR : ASCII character (9) property CR_CHAR : ASCII character (10) property LF_CHAR : ASCII character (13) --ファイル読み込み --引数のファイルを読み込み、コマンドごとに分割した配列を返却します。 on getCommandArrFromFile(filePath) --ファイルを読み込む try set fileNum to open for access file filePath without write permission set allText to read fileNum on error activate display dialog "Error!" & filePath buttons {"Cancel"} default button 1 end try close access fileNum --読み込んだファイル内容を改行で分割する set orgDelim to AppleScript's text item delimiters set AppleScript's text item delimiters to {CR_CHAR, LF_CHAR} set lineArr to text items of allText set AppleScript's text item delimiters to orgDelim --行をカンマで分割する set commandArr to {} repeat with aLine in lineArr if length of aLine > 0 then set orgDelim to AppleScript's text item delimiters set AppleScript's text item delimiters to {","} set stringArr to text items of aLine set AppleScript's text item delimiters to orgDelim set the end of commandArr to stringArr end if end repeat return commandArr end getCommandArrFromFile
Safariへの自動入力を行うスクリプト form.scpt
property RETURN_CHAR : ASCII character 3 --Return property TAB_CHAR : ASCII character 9 --TAB property CR : ASCII character 13 property UP_ARROW_CHAR : ASCII character 30 --上 property DOWN_ARROW_CHAR : ASCII character 31 --下 property SPACE_KEY : 49 --スペースキー on delayL() delay 1 end delayL on delayM() delay 0.1 --delay 0.5 --DEBUG 動作をゆっくり確認したい場合コメントインする end delayM --Safariのロケーションバーへフォーカス --フォーカスの位置合わせのために使います。 on selectLocation() tell application "System Events" tell application process "Safari" delayM() of me keystroke "l" using command down end tell end tell end selectLocation --フォームのテキストボックスへ入力 on inputText(param) tell application "System Events" tell application process "Safari" delayM() of me keystroke "a" using command down delayM() of me set the clipboard to param keystroke "v" using command down end tell end tell end inputText --フォームのテキストエリアへ入力 on inputTextArea(param) inputText(param) end inputTextArea --フォームのプルダウンを選択 on inputSelect(param) tell application "System Events" tell application process "Safari" --選択状態を初期化するため、プルダウンの先頭項目を選択する delayM() of me keystroke UP_ARROW_CHAR --上 keystroke UP_ARROW_CHAR using command down --Command+上 --引数で指定された項目を選択する delayM() of me repeat param - 1 times keystroke DOWN_ARROW_CHAR --下 end repeat keystroke RETURN_CHAR --Returnキー end tell end tell end inputSelect --フォームのチェックボックスを選択 on inputCheckbox(param) tell application "System Events" tell application process "Safari" --チェックボックスの選択状態を初期化したいが方法がわからない --チェックをつける if param = "true" then delayM() of me key code SPACE_KEY --スペースキー end if end tell end tell end inputCheckbox --フォームのラジオボタンを選択 on inputRadio(param) tell application "System Events" tell application process "Safari" --ラジオボタンの選択状態を初期化したいが方法がわからない delayM() of me repeat param - 1 times keystroke UP_ARROW_CHAR --上 end repeat --引数で指定された項目を選択する delayM() of me repeat param - 1 times keystroke DOWN_ARROW_CHAR --下 end repeat end tell end tell end inputRadio --ダイアログを表示 --ユーザからの応答を待ち、自動入力の続行、停止を選択できます。 on displayDialog(msg) set resultFlag to false tell application "System Events" tell application process "Safari" display dialog msg buttons {"停止", "続行"} default button 2 if button returned of result = "続行" then set resultFlag to true end if end tell end tell return resultFlag end displayDialog --フォームのフォーカスを次項目に移動 on nextItem() tell application "System Events" delayM() of me keystroke TAB_CHAR using option down --Option+TAB end tell end nextItem --データ入力1件を実施 on playOneCommand(stringArr) set resultFlag to true set type to first item of stringArr set value to last item of stringArr if type = "location" then selectLocation() else if type = "delay" then delayL() else if type = "next" then nextItem() else if type = "text" then inputText(value) nextItem() else if type = "textarea" then inputTextArea(value) nextItem() else if type = "select" then inputSelect(value) nextItem() else if type = "checkbox" then inputCheckbox(value) nextItem() else if type = "radio" then inputRadio(value) nextItem() else if type = "dialog" then displayDialog(value) set resultFlag to result else log "不明なコマンドです。「" & stringArr & "」" end if return resultFlag end playOneCommand --入力データ全件の実施制御を行う on play(commandArr) set resultFlag to true repeat with stringArr in commandArr log stringArr tell application "Safari" to activate playOneCommand(stringArr) set resultFlag to result if resultFlag = false then exit repeat end if end repeat return resultFlag end play
その他の自動化案 Selenium
Seleniumを使用して自動化するサンプルを作成してみたのですが、テキストボックスのvalue属性に直接値を設定すると、入力値を上手く扱えなくなってしまいました。対象のWebアプリケーションは、jQueryを多用して作られていて、テキストボックスのvalue属性は、ユーザが値を入力したときには入力値を表示し、ユーザ未入力時は入力項目の説明(ウォーターマーク?というのかな)を表示していました。value属性に2つの用途をもたせたアプリなので、Seleniumから直接value属性を設定すると問題があるのかもしれません。
ダウンロード
今回作成したファイルは、次からダウンロードできます。ファイル名は「safari002-XXX.zip」(XXX部分はバージョン番号)です。