こんにちは、estieでSWEをしている齊藤です。estieでは、機械学習まわりのお仕事をしています。
また、JAIST(北陸先端科学技術大学院大学)という大学院へ通ってコンピューターサイエンスの勉強もしています。JAIST本校は北陸にありますが、品川にキャンパスがあって、社会人用のコースを提供してくれています。授業ではパケットを覗いたり、アセンブラ書いたり、関数型言語でコンパイラを作ったり、色々な授業があります。
研究ではCUDA書いたり、deepfake音声の検出をしたりしています。締め切りがないと動けない人間なので、授業や研究で時間を区切って勉強できる環境は自分にあってるなと思います。最近動けていないですが…
jaist-tokyo-calendar
入学した時に、自分の講義をカレンダーに登録するWebアプリ(jaist-tokyo-calendar)を作りましたので、それを紹介します。
サイト: jaist-tokyo-lecture.herokuapp.com
コード: https://github.com/johntronik/jaist-tokyo-lecture
JAIST東京は社会人向けのコースなので、講義が曜日固定ではなく、柔軟に組まれています。
講義のスケジュールでよくあるパターンは
- 平日夜にまとめて一週間(ビジネス系の講義に多い)
- 土日のうち半日*2~3ヶ月くらい(CS系の講義に多い)
などですが、教授の予定などもあるので、結構不規則です。
また、講義予定はPDFで公開されます。特に初年度は取る講義(取りたい講義が)が多く、PDFを目で見ながらカレンダーに打ち込むより、コードを書いた方が早そうだな…と思ったのが、そもそもの動機です。
加えて、プライベートのカレンダー以外にも、業務で使っているカレンダーに講義を登録したかったのもあります。カレンダーに入れておくことで、早めに帰るよ!というアピールをしたり業務の調整をするのに役立つのですが、複数カレンダー登録も大変だなと思っていました。
処理の流れ
- pdf → xlsx
- xlsx → csv
- csv → subset-csv
- subset-csv → google-calendar
1. pdf → xlsx
まず、PDFをパースしてなんらかのデータ形式に変換します。表が含まれるPDFはたいていエクセルから作られていますが、セル結合が使用されていると、うまくパースできないことが多いです。そのため、まずはセル結合されたままの、エクセルファイルに戻すことを目標にしました。
これには、僕の知る限り、大きく3つ方法があります。
- ライブラリ等を使ってコードで変換する
- adobe-acrobatなどアプリで変換する
- webサービスで変換する
上に行くほどチューニングができて柔軟度が高く、いろいろなPDFをハンドリングできます。
余談ですが、業務でもPDFをパースすることがあります。業務ではCamelotというライブラリを使い、テーブル情報を取り出しています。大事な情報がPDFにしかないということは往々にしてありますよね。
PDFのパースに興味ある方はぜひお話しさせてください!
今回は結構複雑なパースになりそうなのと、開発の初速を落とさないためにWebサービスを使いました。今回はsodapdfというサービスを使いました。自分調べでは、かなりうまくパースできる印象があります。
たくさんのセル結合が使われていますね!
2. xlsx → csv
openpyxlでエクセルのセル結合を解除して全シートを結合し、表形式にします。その後、pandasで縦持ちの表に変換します。
カレンダーにインポートできるcsvは以下のようなフォーマットにする必要があります。
SubjectとStart Dateが必須カラムです。今回は時間割なので、開始と終了の時間も入れます。
これで、csvに全部の授業を起こすことができました。
3. csv → subset-csv
上で作ったcsvをそのままカレンダーにインポートしてしまうと、全部の授業が登録されてしまいます。そのため、自分がとっている授業のみに絞る機能が必要です。
最初に作った時はjupyter notebookで授業を絞る機能を作ってgoogle colabで公開しました。その後、colabを立ち上げるのが面倒だったので、streamlitでアプリ化しました。
streamlitはすごく簡単で、pandasさえ書ければwebページが作れます。僕みたいなデータ分析上がりの人にはおすすめです。
例えば以下の画像はこのくらいのコードで書けます。
import streamlit as st
import pandas as pd
df = pd.read_csv('jaist-lecture.csv')
st.title('JAIST東京 授業カレンダー登録 2021')
st.markdown('11/30現在のデータです')
st.markdown('## 1. 授業を選択する')
## 講義選択
lectures = st.multiselect('', df['Subject'].unique().tolist(), ['I485F-知覚情報処理特論'])
## 選択したデータを表示
data = df[df['Subject'].isin(lectures)]
st.table(data)
アプリを作った後、無料で手軽なherokuでホストしました。今はstreamlit sharingという機能があって、streamlitで作ってそのまま公開できるらしいです!すごいですね。
4. subset-csv → calendar
上のページで作った自分の講義csvを各々のカレンダーにインポートすれば無事終了です。お疲れ様でした!
反響
ほとんど自分用に作ったものですが、JAIST東京のslackで共有したところ、実際に使っていただき、便利だと言ってもらえました!
これを作った時(前職)ではデータをきれいにする前処理職人だったので、ユーザーから直接フィードバックをもらうのは初めての経験でした。
githubでstarをもらったのも初めてだったので、嬉しかったです!
今後やりたいこと
授業予定のPDFが時々更新されているんですが、特に検知したりしていないので、情報が古いままになっている時があります。更新を検知したり、前回とのdiffを表示したり、それをカレンダーに反映したりできたらいいなーと思っています。一緒に作っていただける方、Githubのissueなどお待ちしてます!
終わりに
何かデータの誤り等見つけましたら、github かJAISTのslackで話しかけてもらえればと思います!また、カジュアル面談もお待ちしてます!
明日はCEO平井の「estie3周年を振り返って!」です!お楽しみに!