AlfredのWorkflowでWebサイトのDOMを操作したりする
とあるサイトの検索フォームをAlfredから直接実行したかった。検索用のAPIが用意されていないので、ページのformからsubmitしないといけない。
偶然、AppleScriptからSafariのページでJavaScriptを実行できる事を知ったので、以下のような流れで実現できると思い、調査開始。
- Alfredで検索文字列をAppleScriptに渡す
- AppleScriptで、
- Safariに検索ページを表示
do JavaScript
でDOM操作(formに入力してsubmit)
今回はじめてAppleScriptに挑戦し独特な文法に困惑していたところ、JavaScript (Java Script for Automation; JXA) でも書ける事がわかって、そちらに避難した。プログラミングが初めてならApple Scriptの方が英語の文法そのままなので分かりやすいのかもしれないけど、、AppleScriptはまた次の機会に。
Alfredで検索文字列をApple Scriptに渡す
Templates > Essentials > Keyword to Script を選び、名前やキーワードを適当に設定する。ScriptのLanguageに /usr/bin/osascript (JS)
を選ぶ。
スクリプト
Workflowの前ステップから渡ってきたキーワードを {query}
経由で受け取って処理を実行する。以下は例としてWikipediaのトップページから検索するようになっている。
function run(){ let url = 'https://en.wikipedia.org/wiki/Main_Page' let word = "{query}" let app = Application("Safari") app.includeStandardAdditions = true app.activate() let tab = loadUrlNewTab(app, url) waitPageLoad(app, tab) searchWord(app, tab, word) } function loadUrlNewTab(app, url){ let curWin = app.windows[0] curWin.tabs.push(app.Tab()) curWin.currentTab = curWin.tabs[-1] curWin.currentTab.url = url return curWin.currentTab } function waitPageLoad(app, tab){ ret = false do { ret = app.doJavaScript( "(function(){return document.readyState == 'complete'})()", { in: tab } ) delay(0.2) }while(ret==false) } function searchWord(app, tab, word){ app.doJavaScript( "(function(){\ let form = document.getElementById('searchform');\ let input = document.getElementById('searchInput');\ input.value = '" + word + "';\ form.submit();\ })()", {in: tab} ) }
作るときは、Script Editorで実行(Cmd + R
)して動きを確認しながら書いていった。
loadUrlNewTab
はもう少し簡潔に書けるような気がするけど、とりあえず愚直に。
waitPageLoad
は、これがないとページ読み込み完了より先にDOMを読みに行ってしまうので必要。
searchWord
中の getElementById
は、ページに合わせて適当に修正する。
使い方
キーワード スペース 検索語句
-> Enter
でタブが開いて、検索結果が表示される。
参考
ところでosascriptで使えるAppleScriptもJavaScriptも、あまり流行っていないのか情報が少なくて苦労した。流行りの言葉だと、どうやって書くんだろうと思って調べると、大抵StackOverflowなどでやりたい事が既に質問されていたりするのだけど、それがない。ただし大変ありがたいことに、情報をまとめてすばらしい解説ページを作ってくれている方々がいたおかげで、AppleScript / JXA がどんな感じかなんとなく掴む事ができた。ありがたやありがたや。