バスのアプリで使用した技術 バックエンド編
概要
大学のスクールバスのアプリを作る上で使用した技術について紹介していきます。
今回はバックエンド側で使用した技術を紹介しています。
7/2 追記: 公式のカレンダーを監視する仕組みについて追記しました。
全体の流れ
まずバスの時刻表のデータをどのように取得しているのか、全体の流れを画像にしてみました。
公式のPDFからデータを抽出し、スプレッドシートへ
全てのデータは公式の時刻表とカレンダーのPDFから取得しています。
ただ、PDFのままではどうしようもないので、PDFからエクセルの形式に変換して、Google スプレッドシート にPDFのデータを移します。
そこからさらに Google Apps Script でスプレッドシートのデータをJSON形式で返すようにしています。
ちなみに、PDFからエクセルの形式に変換する際には このサイト を利用させてもらっています。かなり精度が良いのでおすすめです。
なぜこんな周りくどいフローにしたのか
最初はPDFから直接日付や時刻表のデータを抜け出せないかを試行錯誤していましたが、なかなか上手くできず...
仕方ないのでもう手作業で... せめて管理しやすいようにスプレッドシートに... と泣きながらデータを打ち込んでいたときに上記のサイトを教えてもらいました。
スプレッドシートで入力したデータは Google Apps Script でJSONの形式で返すようにすることができるので、PDFをエクセルに変換、そこからスプレッドシートの関数などを使ってデータを抽出、Google Apps Script でJSONとして返す、というフローにしました。
正直この部分はPDFから直接データを抽出できたりすれば大きく改善できると思っているので、何か良い方法とかがあれば教えて欲しいです。
JSON 形式のデータを Firestore へ書き込み
Google Apps Script で JSON として抽出したデータを Firestore へ一括書き込みをするために Firebase Cloud Functions を使用しています。
特に凝ったことはしていなくて、単純に特定の Firestore のコレクションに書き込みを一気に行っているだけです。
後々メンテナンスしやすいように TypeScript で実装していて、
index.ts が大きくなりすぎないように関数ごとに分割させたりもしました。
分割に関しては以下の記事を参考にさせていただきました。
Firestore のデータ構造
Firestore には運行カレンダーのコレクション、各ダイヤ(時刻表)のコレクションがあるような感じです。
カレンダーの方はドキュメントIDを YYYY-MM-dd の形式にしていて、
クライアント側から where で検索などをしなくても、直接ドキュメントにアクセスできるようにしています。( 検索をしないので若干読み込み数も減らすことができると思っています。 )
// Swift での実装イメージ
Firestore.firestore()
.collection("calendar")
.document("YYYY-MM-dd")
.getDocument { (documentSnapshot, error) in
// ...
}
時刻表のデータは日付ではなく時間だけを扱いたかったので、
到着時刻などは TimeStamp ではなく、時間、分を分けて数値で管理しています。
定期実行を利用してカレンダーを監視
Firebase Cloud Functions には決まった日付、時間で定期的に処理を実行できる仕組みがあるので、それを利用して毎日大学のカレンダーを監視しています。
カレンダーが変更された場合やエラーが発生した時には Github に issue が登録されるようになっています。
この仕組みを実現させるために Cloud Run というサービスを利用しています。詳しくは以下の記事に書かせていただきました。
最後に
バックエンドで使っている技術はこんな感じです。
今後はPDFからデータを抽出する部分を改善できないか試行錯誤していこうと思っています。