AppleScriptでHTML解析

いよいよスプラトゥーン2の発売が迫り子供のお強請りが正に言葉通り凄まじくなって来たので、と言うのが今回の要件です。

実際にはこの初版運用から4回の販売があり、初めの3回は iPhone のメール通知の発見に遅れたためプッシュ通知が確実なメッセージアプリの利用に変更しました。4回目は通知が来たものの5分間隔では時既に遅しと言うことで、巡回の間隔を短くしました。

解析というほど大袈裟ではなく単に変更を確認するのは “SOLD OUT” ボタンタグの有無にし、混雑時のエラーページを回避する条件分岐を加えたそんなこんなで現在この様なコードで常駐しています。

property INTVAL_CHECK : 90
property INTVAL_NOTIFY : 300
property INTVAL : INTVAL_CHECK
property BASE_URL : "https://store.nintendo.co.jp/customize.html"
on idle
 try
  set rawHTML to do shell script "curl -si " & BASE_URL
  if paragraph 1 of rawHTML is "HTTP/1.1 200 OK" and rawHTML contains "カートに進む" then
   set INTVAL to INTVAL_NOTIFY
   my sendMessage("+8180********", "マイニンテンドーストアで Nintendo Switch の販売が開始されました。" & " " & BASE_URL)
   else
    set INTVAL to INTVAL_CHECK
  end if
 end try
 return INTVAL_CHECK
end idle
on sendMessage(targetBuddyPhone, targetMessage)
 tell application "Messages"
  set targetService to 1st service whose service type = iMessage
  set targetBuddy to buddy targetBuddyPhone of targetService
  send targetMessage to targetBuddy
 end tell
end sendMessage

当初 curl コマンドをオプション指定無しに利用していたところ、プログレスメータをアラートダイアログに表示するということがあり s オプションを、更に鯖落ちしていた場合に備え i オプションを付与しレスポンスヘッダが 200 の場合にのみ処理を実行する様にしました。また、メッセージアプリの宛先がメールアドレスにした場合のエラーを解決できなかったので仕方なく電話番号にしました。

自分からメッセージが送られるという特殊性を活かし、iOS のアドレス帳編集からメッセージ着信音を特別分かりやすいものにすると認知向上に尚良いかと思います。(因みにバルーンファイトのゲームオーバー音を設定しました)

最後に開発環境上で動作させることを考慮し Info.plist に <key>LSBackgroundOnly</key><true/> を追加することでドックにもアプリ切替時にもアイコンを表示させない様にしました。後は増産を待つばかり。

追記:
「0以外の状況でコマンドが終了しました。」というエラー内容(英語では “The command exited with a non-zero status”)は、シェルスクリプトの実行が失敗した際に 0 以外の数字を返した場合に発生することとその回避方法をアップルの公式文書で知りました。

http://hkitago.tumblr.com/post/162968916786

man curl を参照すると 1 から 99 までと XX を返す様で、シェルスクリプトのリダイレクトを利用すると空の値を返した際に次の行にある分岐条件が増えることが格好良く思わなかったので今回は Try ハンドラを利用しました。余談で公式文書にツッコミを入れると、リダイレクトを利用する場合は文末にアンパサンドが必要でないか、と…

追記1:
販売が開始されたら通知の間隔を大きくする目的で、2つの巡回用の数値変数を与えて条件分岐で変更できる様にしました。最初の通知を見逃すと痛手なのですが、気づいて買い物手続き中に通知だらけになるのも避けたいという難しいところ、リマインダアプリの「実行済み」ボタンの様な機能を通知持たせることができれば最善だと感じる苦肉の策。

追記2:
「文字列 “SOLD OUT” を含まない」と言う条件だとコード内でコメントアウトされていたり CSS で非表示になっていた場合に失敗することが分かったので修正。

参考:

投稿者: hkitago

個人事業主でウェブと iOS, Android アプリの開発者で一児の父親。JavaScript, ActionScript, AppleScript, PHP, SQL, ObjC, Java の読書実行試験運用管理を生業とし、Bind, Postfix, Apache を FreeBSD, MacBSD, Mac OS X で使い、エディタは Vi, mi, Kod, Smultron と渡り、現在は Coda, Xcode, Eclipse, Android Studio といった IDE と TextWrangler を重用しています。8時間の区切りで仕事と家庭、睡眠を維持しつつ、作業の自動化や効率化の導入を応援しています。P.S. 制作履歴はLinkedInの公開プロフィールをご覧ください。