1. 0505Keitan

    No comment

    0505Keitan
Changes in body
Source | HTML | Preview
@@ -1,108 +1,110 @@
この記事は[N高等学校 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/n-highschool)の最終日です。
こんにちは。N高等学校2年の0505Keitanと申します。
クリスマスなので今回はディズニーの待ち時間をLINEで見れるようにしたことでも書こうかと思います。←!?
# 作ったもの
以下の画像のように待ち時間を垂れ流します。
今のうちに言っておきますが、**完全に個人用途**です。公開する気など全くありません。というかしたくない。
<img width="1374" alt="LINE_capture_597049992.470206 2.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179129/2e912096-8fc2-137c-5019-54accdb65b03.jpeg">
データ取得先なんですけど、ディズニーは待ち時間APIを出していない(当たり前)なので、[tokyodisneyresort.info](https://tokyodisneyresort.info)の情報を使わせていただくことにしました。このサイトに10分に一回(7分間隔)アクセスし、スクレイピングして更新、表示させます。
念のためサーバーに過負荷を掛けさせないため、要求ごとに取得させるのではなく、取得したデータを一度スプレッドシートに保存し、メッセージごとに呼び出しています。
[詳しく見る](https://scrapbox.io/0505Keitan/TokyoDisneyResort_Unofficial_LINE_Account)
# 使用技術
- Google Apps Script
- Google Spreadsheet
- Parser
- Moment
実行フローとしては
① [tokyodisneyresort.info](https://tokyodisneyresort.info)にアクセス
② 取得データを整形して、Googleスプレッドシートに保存
③ LINEからWebhookでリクエストが飛んでくる
④ スプレッドシートに情報を取りに行く
⑤ データをGASに渡す
⑥ GASからLINEに送信する
という順番です。
![qiita.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179129/eb22c48b-f5ec-06ab-f7ac-e7b5308a93cd.jpeg)
# コード
結構長くて処理複雑なので主要部分だけ書きます。
#### ランドとシーのスタンバイ時間を配列で出す。
```js:コード.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へ送信
```js:コード.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させた。(もっといい方法があるはず)
```js:コード.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}`をつけた
```js:コード.gs
UrlFetchApp.fetch('https://tokyodisneyresort.info/realtime.php?park=land&order=name', {'validateHttpsCertificates' : false});
```
# まとめ
やっぱりGASはいいですよね(あとディズニー)!!!
ぜひ公式API出して欲しいです。
実装もすぐに終わるのでGASはぜひ使いましょう!!!本当に便利です。
+
+ガバガバ実装なの許してください~~なんでもしますから~~