2019/09/21 追記
2019年度版の更新があったので追記しておきます。
とあるイベントのスケジュールページをプライベートで作成してみた。
そのイベントは、年に一回8月~9月頃に、三日間開催される大きな大きなイベントです。
スケジュールページは2016年の時に作成したのですが、
なぜ作ったのか?や、どう作ったのか?と聞かれる事がちょくちょくあったので、
自身も振り返りながら、つらつら書いてみたいと思います。
なぜ作ろうと思ったか
その大きなイベントというのは、日本国内最大のゲーム開発者向けのカンファレンス
CEDEC(Computer Entertainment Developers Conference)です。
自身は関西のとあるゲーム会社に勤務しているのですが、
本当に大きなイベントですから、毎年多くのスタッフが参加します。
ですが、関西から関東へ三日間出張しようものなら結構な経費が発生しますよね。
会社から行きたいからと言って気軽に誰でも、無制限で参加出来るわけではありません。
そんな中、毎年参加者を募りどのセッションに興味があるのかや、
参加出来ないメンバーからの是非ともこれは聴いて来て欲しい等の調整を行います。
どうやって調整していくかと言うと、
Excelに書き起こされたタイムテーブルを使います。
そのタイムテーブルは、
「公式サイトに公開されたセッション情報を
誰かが定期的にチェックしながらExcelにまとめる」
という事を毎年、社内でいろんな人が行っていました。
スケジュールは定期的に公開されますし変更もある為、
スケジュールが公開され初めてから、イベント開催が近づくまでの間に
何度もサイトをチェックしてExcelの表を更新していました。
いやいや...
- 毎年人力で作るのってどうよ・・・。
- なんでセクション(部署)毎で作ってるのよ・・・。せめて一人だろう
- え?作ってる人、すごく技術力高い人なんですけど?その人の無駄遣いじゃない?
話をしても、「まぁ年に一回だし」との反応。
いや・・・。まぁ年に一回とは言うけども・・・
数年放置してましたが2016年春頃。
あれ?まてよ。これ絶対うちの会社だけじゃないぞ?
他の企業さんでも絶対同じことやってる気がする?
数年先も見据え、今後のメンテナンスコストを限りなく最小に。
かつ最小のコストで作ったら、みんなその時間でもっとゲーム作れるんじゃない?
良いゲーム作る為にクリエイティブな時間を各社増やせるのでは?
やばい!それ自分が出来たらすごく楽しい。うれしい。(今年はあれだしネタになる。)
じゃ~作ろう!!という感じで制作しました。
仕組み
基本的にjQueryスキーなので、HTML + jQuery,jQueryUI 以外考えていませんでしたね。
2016年度 Version 1.0
一番最初に作った時の、設計思想はこんな感じでした。
- 今年も来年もメンテナンスコストを極限まで最小化
- スクレイピング等のデータキャッシュ無し
- カテゴリ名とかの画像も作成しないしデータキャッシュしない
- Fileプロトコルに置いても動作
- HTMLからコピペしてExcelにペタリとできる
クロスドメインアクセスについて
「スクレイピング等のデータキャッシュ無し」という所に関して技術的な事を言えば、
jQueryのクロスドメイン用プラグイン jquery.xdomainajax.jsを使用しました。
このプラグインを使うと、jQuery.ajaxコマンド実行時にURLを判断し、別ドメインのURLにアクセスする場合にYQL(Yahoo! Query Language)を使用する仕組みになっていました。
※後述しますが、2017年にYQLのAPI仕様変更に伴い、現在そのままでは使用できなくなっています。
スケジュールページの作成方法
公式サイトのスケジュールページは日程毎にHTMLが割り当てられていました。
CEDEC 2016
1日目:http://cedec.cesa.or.jp/2016/session/schedule_0824.html
2日目:http://cedec.cesa.or.jp/2016/session/schedule_0825.html
3日目:http://cedec.cesa.or.jp/2016/session/schedule_0826.html
CEDEC 2013
1日目:http://cedec.cesa.or.jp/2013/schedule/day1.html
2日目:http://cedec.cesa.or.jp/2013/schedule/day2.html
3日目:http://cedec.cesa.or.jp/2013/schedule/day2.html
スケジュールページにアクセスした際に、公式サイトから対応する年、日付のページを読み込み得られたDOMを解析し、時間やタイトルやリンク、その他いろいろな情報を取得します。
加工前の公式サイトの元データとChrome Developer Toolsの結果
加工後
抜き出したら、セッションの時間が重複しないように列毎のデータ配列を作成します。
部屋番号が存在するデータであれば、部屋番号の列を作成するが、
部屋番号が無ければ「不明_0」「不明_1」という列のデータを作成していました。
列毎のデータ配列が出来てしまえばあとは簡単。HTMLテーブルを作成するだけです!
(簡単とは言いましたが、不要なセルを削除したりいろいろ面倒な事やってます)
公開済み資料CEDiLへのリンクについて
CEDiLとは、CEDEC Digital Library の略称で、
CEDEC開催後、公開が許可された資料が順次アップロードされていきます。
スケジュールページから直接CEDiLの資料が開ければ便利だと感じたため、リンクさせる事にしました。
タグ検索が可能なので、そのページを利用します。
CEDEC 2018:タグ番号717
https://cedil.cesa.or.jp/cedil_sessions/search_tag/717
このページにアクセスし、h2タグに記述されたタイトル名とURLを取得。
1ページ分のデータ取得が終了したら、開いているスケジュールページ内に同一タイトルが無いか調査し、同一タイトルがあった場合に「CEDil page」というリンクを追加。
$(CONTENTS_TABLE_SELECTOR + "," + CONTENTS_FAVORITE_TABLE_SELECTOR)
.find('td.session').each(function(){
var $this = $(this);
if( $this.text().indexOf("CEDiL page") != -1 ) return; // 多重登録防止
var title = $this.find('.ss_title,.session-title').text()
.replace(/\n/g, "")
.replace(/ /g, "")
.replace(/ /g, "");
for( var i = 0 ; i < list.length ; ++i ){
if( title.indexOf( list[i].title ) == -1 ) continue;
$this.append( '
')
break;
}
});
その後、ページ下部にあるページ番号を順次解析し、
2ページ目、3ページ目と同様の処理を繰り返します。
CEDEC 2018:タグ番号717 2ページ目
https://cedil.cesa.or.jp/cedil_sessions/search_tag/717/page:2
お気に入り機能について
並列で行われるセッションが多くページもみづらくなるため、
お気に入り機能を実装しました。
ログインさせて、データベースもってどのブラウザから開いても!
みたいな事は一瞬頭をよぎりましたが、データベース作るほどの物か?
データベースを作る事で、Fileプロトコルでアクセスとか、
GitHubページでの表示が出来なくなったりしたら失うものが多いなと判断し
年毎のCookieデータとして保存する事にしました。
セッションの詳細ページ毎にユニークそうなIDを発見したので、
http://cedec.cesa.or.jp/2016/session/KN/12048.html
http://cedec.cesa.or.jp/2017/session/KN/s5966bc0d596d9/
お気に入りに設定した際にそのIDをCookieで覚えるようにしました。
個人的にはGoogleやFacebookのログインで何かするのも学びとしてはありかなと考えましたが、お気に入り情報が消えたとして、それがユーザーにとって重大な問題かと言うと・・・。そうでもないと考えました。
「学びたい事」と「実装コスト」と「実装したことによる制約」を天秤にかけた結果です。
メンテナンスコストについて
来年のメンテナンスコストを下げるという事に関しても、開催年、開始日、日程別のスケジュールページのURLフォーマットを持つオブジェクトを追加すれば動作するように実装していました。
var SCHEDULE_SETTING = [
{ year:"2016", first_date:"0824", format:'session/schedule_{date}.html' },
{ year:"2015", first_date:"0826", format:'session/schedule_{date}.html', cedil_tag_no:709 },
{ year:"2014", first_date:"0902", format:'session/schedule_{date}.html', cedil_tag_no:9 },
{ year:"2013", first_date:"0821", format:'schedule/day{day_no}.html', cedil_tag_no:8 },
{ year:"2012", first_date:"0820", format:'schedule/day{day_no}.html', cedil_tag_no:4 },
{ year:"2011", first_date:"0906", format:'schedule/day{day_no}.html', cedil_tag_no:6 },
{ year:"2010", first_date:"0831", format:'schedule/day{day_no}.html', cedil_tag_no:5 },
];
過去数年のページを確認した所、サイトテーマに大きな変化はなく、
各日程毎のページURLが違うくらいだったので、2017年は一瞬で対応できそうな予感。
2017年度 Version 1.3
なんと?!2017年に大きな問題が!!
YQLが APIの仕様変更を行い、htmlでの取得が不可能に・・・。
しかし公式で説明はないが、 html string が存在するという記事を発見。
プラグインをいじって html string版に差し替えて対応しました。
APIの問題はありつつも、スケジュールページの対応に関しては一瞬でした。
「SCHEDULE_SETTING」に一行追加するだけで対応が完了しました。
メンテナンスコスト最小化成功!!
他にもいくつか問題はありました・・・。
- セッションのキャンセルが発生し同時刻のデータが重複
- セッション毎のユニークIDの記述場所が変更されていた
- 昨年にくらべアクセス数が増えてYQLのリクエスト数がパンクした
まさかSNSで友達限定で共有していたものが、あれよあれよと広がり
YQLの使用制限に引っ掛かりましたw
Per application limit (identified by your Access Key): 100,000 calls per day Per IP limits: /v1/public/*: 2,000 calls per hour; /v1/yql/*: 20,000 calls per hour
引っ掛かってアクセス出来なくなったのが、開催数日前?とかだったので、
仕方なくこのタイミングでHTMLをキャッシュする事にしました。
そしてFileプロトコルでそのまま動作させる事が出来なくなり、Fileプロトコルはあきらめました・・・。
まぁ仕方ない。
そしてこのタイミングで、スクレイピングとかいろいろやらないといけないかな~と感じ始めました。しかし年に一回の開催、半年以上忘れるわけですね。
2018年度 Version 2.0
やられた!ついにやられた!
- サイトテーマ大幅変更。DOM周りが完全に別物に
- クロスドメイン対策
くっそ~!!と言いながら対応していました。(内心はものすごく楽しい)
時間なども単純なテキストになっていたりしたため、
区切り文字検索して前後左右から抜いたり、
日程は、正規表現で抜いたりといろいろ大変でした。
/\d{4}年\d{1,2}月\d{1,2}日/
いや~~DOM解析って楽しいですよねホント(おい
2019年度 Version 2.1
なんと...ついに YQLがサービス終了...
ということで、YQLではなくWebスクレイピングに変更しました。
詳しくはこちらで
最後に
このタイムスケジュールページに関しては、公式を批判・非難するものではありません。
そして一番やりたかった事と言いますか、
「既存のサイトデータを直接参照し加工して別の物に作り替える」
が出来たので楽しかったです。
これもメンテナンスコストに関係する話ですよね。
今回は非公式ページとして作成した為にクロスドメインの制約がありましたが、
それが無ければ「サイトの一部を変更していれば、タイムスケジュールページは勝手に更新される。」という事になるので、めっちゃくちゃ楽ですよね。
元々データベースや別ファイルで作ってそっから両方とればいいじゃん!
と言われるかもですが、デザインを考え作っている人がいて、いろいろ変更すると思うので
最初にテーマのDOMルールやフォーマットを与えてしまえば、後は勝手に出来ます。
これもある種の自動化ですか。
そしてそして、今回のこのスケジュールページ関係無く
少し業務の事を考えてみませんか?
「年に一回くらいだから」と言いながら毎年やってるムダな作業ありませんか?
一年に限った話ではなくて、日常にある手間だけど慣れてしまった作業ありませんか?
「合計しても毎日たった15分くらいだから。」とか。
それって何人ですか?毎日って何日続いてますか?
誰かが数時間やって返せるならやったほうがいいですよね。
対応コストの事を考える必要はあるかもしれませんが、いきなり何か作るわけじゃないので、
「今更だけど、面倒な事ない?」って会社の人に聞いてみて下さい。
リンク
お酒を飲みながら書いたクソコードは実は誰にも見られたくはないのですが、
全てGitHubに公開してあります。
https://github.com/kazunori0909/cedec_schedule
利用者が本ソフトウェアを使用し、または第三者に提供することによって生じるいかなる損害に対しても一切責任を負いません。個人の責任で使用して下さい。