eps_r

不思議の謎を解かねばならぬ

ボーダーブレイク 店舗情報ウォッチbotとGoogle Apps Scriptについて

ボーダーブレイク 店舗情報ウォッチというTwitter botを動かしていたところ、「仕組みを知りたい」という言及をいただいてたことに気付きましたので少し書きます。

ちゃんとした学習をしている人間のやり方ではないので、もっとスマートな方法は幾らでもあることでしょう。

プラットフォーム

GoogleスプレッドシートGoogle Driveに付属しているWebベースの表計算ソフトですが、Google Apps Scriptはそのスプレッドシートに紐付け、あるいは単体でJavaScriptを動かすサーバサイドのスクリプティング環境です。Excelで言うところのVBAマクロのように使うことができます(定期実行やWebページ出力などの、あまりExcelマクロ的でない用法もあります)。

構成

  • スプレッドシートの内容
    • 当日の店舗情報シート
    • 前日の店舗情報シート
    • 変更履歴シート
  • Apps Scriptの定期実行ジョブ
    • (毎日21:00頃)店舗情報を取得するジョブ
    • (毎日22:00頃)変更履歴を出力し、変更の概要をtweetするジョブ
    • (5分毎)変更内容の詳細をtweetするジョブ

ボーダーブレイク店舗マップと連動しているため上記の他に「住所-経度緯度の対応表(ジオコード結果)」シートとそれを読み書きするジョブが幾つかありますが今回は割愛します。

動作

店舗情報取得ジョブ(毎日1回実行)

  1. 公式の店舗情報をメモリ上に取得
    • Google Apps Scriptには UrlFetchApp というとても便利なクラスがあり、fetch()メソッドはWebページの内容を一発で文字列変数に格納します。
    • BB公式サイトではJavaScriptに書かれたデータと出力ロジックからページを生成しているので、HTMLのパースでなくevalと少々のコードでデータを取出せます。
  2. 「当日の店舗情報」を「前日の店舗情報」に上書きコピー
  3. メモリ上の最新データで「当日の店舗情報」を更新
番号 店名 住所 YYYY/MM/DD hh:mm:ss(取得日時)
1 店舗A 住所A
2 店舗B 住所B
3 店舗C 住所C

具体的にはこういう保存をします。データの取得日時は1行目D列に直接書いている。

履歴出力・概要tweetジョブ(毎日1回実行)

  1. 当日・前日の店舗情報を比較する
    • ださい多重forです。店舗名か住所が変わっていたら「変更」、どちらも無くなっていたら「削除」、新しい行が増えていたら「追加」という分類。
  2. 差分を変更履歴シートに新しい行として追記する
  3. 分類ごとの集計をtweetする

具体的にはこういう変更履歴シートとこういうtweetが出ます。

データ種別 店名 住所 取得時間 登録種別 tweet結果
BorderBreak 店舗A 住所A YYYY/MM/DD hh:mm:ss 追加
BorderBreak 店舗B 住所B YYYY/MM/DD hh:mm:ss 追加
BorderBreak 店舗C 住所C YYYY/MM/DD hh:mm:ss 削除

詳細tweetジョブ(5分ごとに実行)

  1. 変更履歴シートにtweet結果の入っていない行があればtweetする
    • 同じ都道府県と変更種別の行は、内容をまとめて一度にtweetします。
  2. 変更履歴にtweet結果(ステータスコード)を追記する

変更履歴にステータスコードが追記され、こういうtweetが出ます。

データ種別 店名 住所 取得時間 変更種別 tweet結果
BorderBreak 店舗A 住所A YYYY/MM/DD hh:mm:ss 追加 200
BorderBreak 店舗B 住所B YYYY/MM/DD hh:mm:ss 追加 200
BorderBreak 店舗C 住所C YYYY/MM/DD hh:mm:ss 削除 200

住所か店名が同じなら「変更」で出るはずですが、当時のスクリプトのバグで「削除→追加」扱いにされています。

サンプルコード

twitterとOAuthする方法はGAS(Google Apps Script)でお手軽にbotを作る方法。 - usakoyamaでまとまっていますので最も簡単なものだけ。

特定のシートの値を2次元配列に格納する

var spreadSheet = SpreadsheetApp.openById(sheetId); // スプレッドシートオブジェクトを取得。sheetIdには、シートを開いた際にURLに載ってるkeyパラメータを指定する
var sheet = spreadSheet.getSheetByName(sheetName);  // シートオブジェクトを取得
var values = sheet.getDataRange().getValues();      // データの入っている範囲を選択し、配列に格納する

2次元配列の内容を特定のシートに値として書込む

var spreadSheet = SpreadsheetApp.openById(sheetId);                      // スプレッドシートオブジェクトを取得。sheetIdには、シートを開いた際にURLに載ってるkeyパラメータを指定する(上と同様)
var sheet = spreadSheet.getSheetByName(sheetName);                       // シートオブジェクトを取得
sheet.clear();                                                           // シート内容のクリア
sheet.getRange(1, 1, values.length, values[0].length).setValues(values); // シート左上(引数1, 2)から配列の範囲(引数3, 4)までを選択し、配列の内容を書込む

おわり

Google Apps Scriptは

  • 無料
  • Excelマクロ感覚でJavaScriptを書き散らせる
  • OAuthが整備されていてTwitterとかのアクセスが容易
  • (時間は大雑把だけど)cron的に定期実行をセットできる
  • (ここでは使ってないけど)HTMLとかフォームとか組み合わせて一応GUIも置ける

という環境なので、JavaScriptに慣れてて特にレンタルサーバとか借りてない人が小物を作ってみるのにいいかもしれません。