Help us understand the problem. What is going on with this article?

ディズニーリゾートの待ち時間をGASを使ってLINEで見れるようにした話

この記事はN高等学校 Advent Calendar 2019の最終日です。

こんにちは。N高等学校2年の0505Keitanと申します。
クリスマスなので今回はディズニーの待ち時間をLINEで見れるようにしたことでも書こうかと思います。

他にも色々作ってるんですけどいい感じに記事にできるやつがなかったのでこれにしました(
ちなみに紹介記事なので作ってみよう系じゃないです。

作ったもの

以下の画像のように待ち時間を垂れ流します。
ちなみに公開はしないです。結構ガバガバ実装なので...。
なお、他にもショーの時間とかも見れるようになってます。詳しくはコチラ
image.png

データ取得先なんですけど、ディズニーは待ち時間APIを出していない(当たり前)なので、tokyodisneyresort.infoの情報を使わせていただくことにしました。このサイトに10分に一回(7分間隔)アクセスし、スクレイピングして更新、表示させます。

念のためサーバーに過負荷を掛けさせないため、要求ごとに取得させるのではなく、取得したデータを一度スプレッドシートに保存し、メッセージごとに呼び出しています。

使用技術

  • Google Apps Script
  • Google Spreadsheet
  • Parser
  • Moment

実行フローとしては
tokyodisneyresort.infoにアクセス
② 取得データを整形して、Googleスプレッドシートに保存
③ LINEからWebhookでリクエストが飛んでくる
④ スプレッドシートに情報を取りに行く
⑤ データをGASに渡す
⑥ GASからLINEに送信する
という順番です。

qiita.001.jpeg

GASのライブラリ

今回は取得したhtmlをパースしてくれるParserと日付の処理を簡単にしてくれるmomentを利用しています。

導入はGASの編集画面からリソースライブラリ→Add a libraryの欄に以下のプロジェクトキーを入力して追加をクリック!

  • Parser
    • M1lugvAXKKtUxn_vdAG9JZleS6DrsjUUV
  • Moment.js
    • MHMchiX6c1bwSqGM1PZiW_PxhMjh3Sh48

コード

結構長くて処理複雑なので主要部分だけ書きます。

ランドとシーのスタンバイ時間を配列で出す。

コード.gs
var response = UrlFetchApp.fetch('https://tokyodisneyresort.info/realtime.php?park=land&order=name', {'validateHttpsCertificates' : false});
var response_c = UrlFetchApp.fetch('https://tokyodisneyresort.info/realtime.php?park=sea&order=name', {'validateHttpsCertificates' : false});
var html = response.getContentText('UTF-8');
var html_c = response_c.getContentText('UTF-8');

var data = Parser.data(html).from('<div class="attr_name">').to('</div>').iterate();
var data_c = Parser.data(html_c).from('<div class="attr_name">').to('</div>').iterate();
var fdata = Parser.data(html).from('<div class="attr_wait">').to('</div>').iterate();
var fdata_c = Parser.data(html_c).from('<div class="attr_wait">').to('</div>').iterate();

for(i=0;i<data.length;i++){
  data[i]=data[i].replace(/ /g,'').replace('&park=land">','').replace('</a>','').replace('<span class="new">NEW</span>','').replace('amp;','').replace(/\n/g,'').replace(/ /g,'');
  fdata[i]=fdata[i].replace(/<span class="fp">【FP:(TICKETING|TICKETING_END|NOT_TICKETING_TODAY)】<\/span>/g,'(FP対象)').replace(/<span class="greeting_timetable">/g, '').replace(/<\/span>/g, '').replace(/ /g,'').replace(/\n/g,'').replace(/<br\/>/g,'\n').replace(/分/g,'').replace(/    /g, '').replace(/^$/g, '情報なし');
  data[i]=''+data[i]+'\n'+fdata[i]+'\n\n';
}
for(i=0;i<data_c.length;i++){
  data_c[i]=data_c[i].replace(/ /g,'').replace('&park=sea">','').replace('</a>','').replace('<span class="new">NEW</span>','').replace('amp;','').replace(/\n/g,'').replace(/ /g,'');
  fdata_c[i]=fdata_c[i].replace(/<span class="fp">【FP:(TICKETING|TICKETING_END|NOT_TICKETING_TODAY)】<\/span>/g,'(FP対象)').replace(/<span class="greeting_timetable">/g, '').replace(/<\/span>/g, '').replace(/ /g,'').replace(/\n/g,'').replace(/<br\/>/g,'\n').replace(/分/g,'').replace(/    /g, '').replace(/^$/g, '情報なし');
  data_c[i]=''+data_c[i]+'\n'+fdata_c[i]+'\n\n';
}

LINEへ送信

コード.gs
function reply(message, token) {
  UrlFetchApp.fetch(line_endpoint, {
      'headers': {
        'Content-Type': 'application/json; charset=UTF-8',
        'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
      },
      'method': 'post',
      'payload': JSON.stringify({
        'replyToken': token,
        'messages': [{
          'type': 'text',
          'text': message,
        }],
      }),
    });
  return;
}

LINEでレスポンスをするにはdoPostに含まれているreplyTokenを指定しなければなりません。

問題点と改善結果

①22:00以降は結果が同じになる

実行しても同じ結果なので22:00以降は各処理前に時間を取得してreturnさせました。(もっといい方法があるはず)

コード.gs
if(Moment.moment().format('HH')>=22||Moment.moment().format('HH')<08){
    sheet_standby.getRange('A1').setValue('東京ディズニーリゾートは現在閉園中です。');
    sheet_standby.getRange('B1').setValue('東京ディズニーリゾートは現在閉園中です。');
    sheet_standby.getRange('A2:B2').setValue('最終取得時間:'+Moment.moment().format('HH:mm'));
    return;
  }

②GASでアクセスするときSSLエラーが出る

(あまりいい方法ではないが)
無理やりアクセスさせるためにUrlFetchApp{'validateHttpsCertificates' : false}をつけました。

コード.gs
UrlFetchApp.fetch('https://tokyodisneyresort.info/realtime.php?park=land&order=name', {'validateHttpsCertificates' : false});

まとめ

やっぱりGASはいいですよね(あとディズニー)!!!
ぜひ公式API出して欲しいです。
実装もすぐに終わるのでGASはぜひ使いましょう!!!本当に便利です。

ガバガバ実装なの許してくださいなんでもしますから

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした