■週末ともなれば暇な時間を埋めるように美術館やら何やらまわっているわけですが、そういうスケジュールをどこで入手するかといえば、それぞれのHPに掲載されているスケジュール情報なわけです。先月までいた名古屋なら、行く宛てといったら豊田か南伊勢ぐらいしかないのでスケジュールの組み立てに迷うことはないんですが、東京・横浜といったらいたるところにスポットがあるので大変です。そういう話も先日書きましたが、あちこち見て回るのも大変です。
スケジュールを組み立てる時に思うんですが、あちこちのスケジュールをガントチャートで積み上げてどこどこの展示が〈いつまで〉かぶっているのかを把握できると便利だなーと。各施設のスケジュールを網羅しているところとしてはTokyo Art Beatがあるんですが、ここのスケジュール表示は刹那的というか、「今」は把握できるんですが、例えば再来週の土曜日がどうなっているのかとかいった将来の把握がしにくい。MyTABとしてブックマークを作成すればある程度情報の集積はできるんですが、網羅的な把握はまずできません。
別途スケジュールアプリを使って、自分でまとめないとだめかなあと思っていたら、TABにはAPIがあって、スケジュール情報をXMLで取得することができる。じゃあ、それを使ったれ。
例によってPHPを使いましたが、言語は何でもいいでしょう。
XMLを読み込んで、欲しいサイト以外はフィルタして、データ変換する。TABは各施設ごとにページを持っていて、そのURLがXMLには付加データとして載っているから、それをフィルタのキーに使う。データは各地域ごとに分離したURLとなっているので、これらを順次読み込んで、一括出力することで統合する。
要するに、ただそれだけの処理です。
出力フォーマットには最初iCalendar(RFC2445)を使いました。Microsoft Outlookが読み込めるというので。UIDやMETHODの設定に悩みましたが、とりあえず処理させることはできました。ただ、Outlookはイベントをひとつずつしかインポートできないらしく、複数のイベントが同梱されているデータを処理できない。今回の目的はTABから取得したデータを一括処理することなので、個別のファイルに分離させないと処理できないのでは役不足です。他にiCalendarを処理できるスケジュールソフトというのが解らなかったので、ものは試しとGoogle Calendarでインポートさせたら一括読み込みができました。
ただ、Googleアプリを使うならAPIを叩けばいいじゃんという話も当然あって、APIの方を調べてみました。が、iCalendarのインポートに関するAPI情報は見当たらず。どうやら個別にイベントデータを登録させなければならないようなんですが、データの重複排除はできないのが課題でした。
TABからのデータコンバージョンは定期的に実施したいのですが、たとえば1週間ごとに更新するとしてもTABとしては別に1週間前から掲載されているデータかどうかは考慮していないわけです。TABとしては連続して情報を公開しているだけであって、そのデータを定期的にサンプリングしてスケジュールソフトにインポートする、といった使い方まで考慮しているはずがない。
ただ、何も考えずに定期的に更新した結果、過去に登録したイベントと同一のイベントが何度も登録されては使いづらいので、それは排除したい。
1つのやり方としては、登録前にGoogle Calendarに登録状況を確認して、なければ登録する、というやり方。ただ、これは処理が複雑になるし、無駄にトラフィックが多いような気もします。
もう1つのやり方は、ローカルに過去の登録情報を保存して、すでに登録してあれば除外する、というまあ、普通といえば普通のやり方。DBをどうするかという問題はありますが、この方法だと、ローカルでチェックして、登録済みであれば処理をしないので一切のトラフィックが発生しないという利点もあります。それだけ軽くなるわけです。
結局のところ、後者の方式をとりました。TABのXMLには各イベントにユニークなIDが付与されているので、これを検索キーとして利用します。単純にフラットファイルに落として、文字列検索という方法もありますが、今回は検索キーをタグ名称とするXML形式に落としました。ルートノードの配下に各検索キーを名称とする子ノードがずらっと並ぶ形式です。当然タグ名称はイベントごとに異なるものとなるので、1つとして同じタグ名称は存在しません。Namespaceを考えるとヒドイ話ですが、まあ、そこは目を瞑ることに。
この方法をとると、Xpathでキー検索が可能になります。真っ当な使い方では無いと思うのですが、まあ、検索ルーチンもDB設計も不要なので、その方式としました。
Google Calendar APIの呼び出しには、Zend FrameworkのGdataサブセット(Zend_Gdata)にあるデモプログラムを流用しました。1回ログオンして、あとはTAB XMLから抽出したデータをちぎっては投げるわけです。これで、うまく行きました。