像や引用したテキスト、動画などを自由にPostしていけるサービス「Tumblr」が非常に便利です。はてなブックマークなどのソーシャルブックマークがページごとの記録であるのに対して、Tumblrではそのページ内の特定の要素をブックマークしていけるという点でよりポイントを絞って記録していくことが出来ます。Tumblrの一般的な用途はいわゆるミニブログ、つまりTwitterのように次々と書き捨てていって他人のそれをリアルタイムで取得して楽しんでいくという用途になると思いますが、僕としてはもう少しアーカイブ的な使い方をしたいと考えています。気になる言い回しや、面白い画像を見かけたときにそれをどんどんTumblrに放り込んでいき、あとで閲覧したりまとめてエントリにしたりしていくイメージです。


しかしTumblrをそうしたアーカイブとして使うには、現状少し問題点があります。それはサービスとして用意されているAPIの機能が限定的で、データを取得する(read)という点で言えば連続する50件取得を取得することしかできないことです[*1]。

API | Tumblr

過去のデータも自分がPostしたページのURL(Post ID)がわかればAPIで取得することが出来ますが、そのURLを知るには過去のデータを取得していることが必要なわけで、結局何もない状態から得られる情報は最新の50件以上ではないわけです。Tumblr Tag Clouds(Tag Cloudを作成するスクリプト)がしているように、遡りながら50件ずつ取得することを繰り返していけば過去のデータを扱うことも可能ですが、実際に運用する上で毎回それを行うのは手間ですし、エントリが増えるにつれて検索や表示に時間が掛かることになります。実際Tumblr Tag Cloudsは表示に非常に時間が掛かりお世辞にも便利だとは言えません。


この状態を解決する方法として結局は自分のデータをTumblrではなく自分で持ち、表示に当たってTumblrにリクエストしなくて済むようにするのが一番良いのではないか、そう考えたところが今回の企画の始まりです。まぁそれを詳しく記述したところで誰得?という感じではあるのですが、整理のためにとりあえず1つずつ説明していこうと思います。

基本的な流れ

  1. サーバ上にSQLite DBを用意する
  2. cronで定期的にAPIを叩く
  3. 取得したデータの中から保存するデータを抽出する
  4. 抽出したデータをDBにInsertする



1. サーバ上にSQLite DBを用意する

これまでDBを使うときには殆ど必ずMySQLを使ってきました。高速で安定しているという点で非常に便利なのですが、今回のような小規模なサービスの場合は少し大げさかなという気も。幸いさくらインターネットではSQLiteが問題なく使用できるのでそれを使ってみることにしました。ちなみにMovableTypeをSQLiteで運用してはいますが、実際に自分で運用するのは初めてだったりもします。


用意したテーブルは次の3つ。
  • posts
  • tags
  • post_tag

postsは文字通りエントリ1つずつの情報を格納するためのテーブル。格納しているデータは、Post ID、type(photoなど)、image_largest(500px)、image_large(400px)、image_medium(250px)、image_small(100px)、thumnail(75px四方)、テキスト、投稿時間です。imageについては登録するデータ(画像URL)それぞれに検索すべき情報があるわけでもないので、imagesとしてserializeしたデータを突っ込もうかなぁ…とも考えたのですがとりあえずはこれで。実際の画像ファイルはディスク容量的に負担になるので取得せず、単に画像URLを記録するだけなのでもし画像サーバが大幅に変更になったら大量のリンク切れが発生することになりますが…それについては祈るのみ。てかまぁ、Post IDさえ変わらなければいつでも修正は可能です。なお、Post IDにはUNIQUEを設定してあります。

tagsはタグを格納するためのテーブル。単純なリストです。

post_tagはエントリとタグの関係を規定するためのテーブル。tags.idとPost IDがセットで格納されています。タグの運用を設計したことがないので、おぼろげな記憶をもとに非常に単純な設計にしてみましたが、多分これだと「あるタグが付いているpost一覧」「あるpostに付けられたタグ一覧」は上手く表示できるとしても、「AというタグとBというタグが付いているpost一覧」といった感じの検索には適していないような気がします。。用途として想定しているのでもう少し工夫すべきなんですが、その辺は今後改良予定と言うことで。ちなみに、tags.idとPost IDのセットにUNIQUEを設定してあります。



2. cronで定期的にAPIを叩く

1回の更新でAPIを叩くのは1回まで、ということにしています。遡ってもきりがないですし。APIからのデータはXMLで取得しPHPで極シンプルに以下のように書いています。

$xml = simplexml_load_file('http://nobodyplace.tumblr.com/api/read?num=50&type=photo');

photoタイプのエントリの最新50件を取得するということです。photoタイプに限っているのは用途としての想定が画像データの蓄積だからです。



3. 取得したデータの中から保存するデータを抽出する

上で取得したXMLを適当にいじって連想配列に格納します。特に大したことはしていません。



4. 抽出したデータをDBにInsertする

「基本的に過去のデータは変更しない」というかなり大雑把な仕様で設計しました。というわけで既に登録されているPostの場合Post IDにUNIQUEが設定されているのでエラーが出ますがその時点で登録を諦め、その後の処理はされずに無視されます。そんなんで良いのかとか思いますが。まぁいいんじゃないですか。



以上で、更新フェーズは終わりです。

ちなみに既にPostされてしまっている過去ログについてもDB化したかったので、月毎アーカイブのページをスクレイピングしてPost IDを取得した上でそれぞれについてAPIを叩くということをやりました。でも今になって考えてみれば、50件ずつ遡りながらAPI叩いていけば良かっただけじゃんね…まぁもう終わったことなので気にしないことにしましょう。



次回は、実際にデータを読み出して表示してみます。
中途半端にAPI的なものを書いてそれを使ってデータにアクセスしてみようと思っているんですが、さてどうなることやら。そんなのPHPで書くものじゃない気もしないでもありませんが、せっかくなのでPHPで終わりたいと思います。

以下は、サンプル「タグ一覧」です。
(データをJSONPで取得してJavaScriptで書き出しています)




注釈

  1. TumblrのAPIがFlickr並みに充実していれば問題はないのですがこの後も劇的に変わることは無さそうですし、またFlickrに自分が撮影した写真以外の画像データを上げることには抵抗があるので…