18
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

N高等学校Advent Calendar 2019

Day 25

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

Last updated at Posted at 2019-12-24

この記事は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はぜひ使いましょう!!!本当に便利です。

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

18
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?