初めに
「あ,学校前に献血バス来てる!,けど時間ない!」
ということはありませんか?
こんなとき,事前に献血バスが来ていることがわかっていれば,それを組み込んだ予定を立てられて,便利ですよね.
実は献血バスのスケジュールは,1か月前くらいから発表されています.
献血バス運行スケジュール|東京都赤十字血液センター
(東京都以外も調べれば出てきます.)
しかし,これを自動で通知してくれる機能は存在しません.
そこで,1か月に1回程度,自動で献血バスのスケジュールを取得し,Googleカレンダーに反映させる機能を作りました.
仕様
月に一度,献血バスのスケジュールを取得し,指定したキーワード(例えば「大岡山」)に合致する場所で開催される献血のスケジュールを,指定したGoogleカレンダーに,以下のような形式で追加します.
なお,URLは予約用のリンクです.
使い方
- 後述のプログラムをGAS(Google Apps Script)にコピーする.
- スケジュールが掲載されているサイトのurlを
target_url
に与える. - GoogleカレンダーのIDを
calendar_id
に与える.
(カレンダーIDの取得方法は適宜調べてください.) - 献血会場のキーワードを,
keyword_place_array
に与える.
(下図の赤で囲んだ部分に含まれるワードです.)
- 月1回程度(恐らく月末に翌月のスケジュールが発表される?)の時間主導型トリガーを設定する
プログラム
// 献血バスのスケジュールが掲載されているページのURL(東京以外の方は変えてください)
const target_url = 'https://www.bs.jrc.or.jp/ktks/tokyo/place/m1_03_kenbus.html';
// 対象カレンダーのID
const calendar_id = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@group.calendar.google.com';
// 場所のキーワード
const place_keyword_array = ["大岡山"]
// htmlを取得する関数
function get_html(url) {
var response = UrlFetchApp.fetch(url);
var htmlContent = response.getContentText("utf-8");
return htmlContent;
}
// htmlから献血場所を配列として取得する関数
function get_table(html) {
let doc = Parser.data(html).from('<article class="mod-iconIndent01">').to('</article>').build();
doc = doc.replace(/\t/g,"");
doc = doc.replace(/\n/g,"");
let table_by_day = Parser.data(doc).from('<br><p>').to('</div>').iterate();
console.log(table_by_day);
// 日付ごとのループ
let table = new Array();
let index = 0;
for (let i = 0; i < table_by_day.length; i++) {
const date = Parser.data(table_by_day[i]).from('').to('</p>').build();
const today = new Date();
const year = today.getFullYear();
const month = Number(Parser.data(date).from('').to('月').build());
const day = Number(Parser.data(date).from('月').to('日').build());
let table_by_place = Parser.data(table_by_day[i]).from('<tr><td class="tac vam">').to('</td></tr>').iterate();
console.log(table_by_day[i]);
// 場所ごとのループ
for (let k = 0; k < table_by_place.length; k++) {
table_by_place[k] = '<td class="tac vam">' + table_by_place[k] + '</td>';
table[index] = {};
table[index].place = Parser.data(table_by_place[k]).from('<li>').to('</li>').build();
table[index].booking_url = Parser.data(table_by_place[k]).from('<li><a href="').to('">※Web予約はこちら').build();
let temp = Parser.data(table_by_place[k]).from('<td class="tac vam">').to('</td>').iterate();
console.log(temp);
console.log(table[index]);
table[index].municipalities = temp[0];
table[index].time = temp[1].split("<br>");
// 献血の開始時間,終了時間を取得
table[index].date = new Array();
for (let j = 0; j < table[index].time.length; j++) {
table[index].time[j] = table[index].time[j].replace(/:/g,":"); // たまに,全角":"で区切っているところがあるので修正
table[index].time[j] = table[index].time[j].replace("-","~"); // たまに,"-"で区切っているところがあるので修正
//console.log(table[index].time[j]);
const temp = table[index].time[j].split("~");
table[index].date[j] = {};
table[index].date[j].start_time = Utilities.parseDate(year+"/"+month+"/"+day+" "+temp[0], 'JST', 'yyyy/M/d HH:mm');
table[index].date[j].end_time = Utilities.parseDate(year+"/"+month+"/"+day+" "+temp[1], 'JST', 'yyyy/M/d HH:mm');
//console.log(table[index].date[j])
}
index++;
}
}
console.log(table);
return table;
}
// カレンダーに反映する関数
function add_calendar(calendar_id, keyword, table) {
let target_calendar = CalendarApp.getCalendarById(calendar_id);
for (item of table) {
if (item.place.includes(keyword)) {
console.log(item.place);
for (time_zone of item.date) {
target_calendar.createEvent("献血バス "+item.place, time_zone.start_time, time_zone.end_time,{description:item.booking_url});
}
}
}
}
function main() {
// htmlを取得
let html = get_html(target_url);
// htmlから献血場所を配列として取得
let table = get_table(html);
// カレンダーに反映
for (place_keyword of place_keyword_array) {
add_calendar(calendar_id, place_keyword, table);
}
}