大旦那のお気に入りの裏側

大旦那のお気に入りの技術的な側面に関して解説してみました。

大旦那のお気に入りデータの取得

まずは大旦那のお気に入りを調べるところから始めました。はてな ID からお気に入りを取得する部分は Perl の HTML::TreeBuilder::XPath を使って書いてみました。

sub getFavorites{
    my $id = shift;
    my $res = URI::Fetch->fetch(sprintf 'http://b.hatena.ne.jp/%s/favorite', $id)
     or die URI::Fetch->errstr;

    my $tree = HTML::TreeBuilder::XPath->new;
    $tree->parse($res->content);
    $tree->eof;

    # /user1//user2//user3/
    my $favorites = $tree->findvalue('/html//div[@class="favoritelist"]//li/a[position()=1]/@href');
    $favorites=~m!/([^/]+)/!g;
}

JSON 化

このデータを JavaScript で食えるように JSON 化してやったのが data.js です。

var fav = {
    jkondo : {count : 690, favorite : ["naoya","umedamochio","mkusunok","miyagawa"]},
    // ...
};

旦那衆、若旦那の被お気に入り数のデータと合わせても 61KB。この程度なら、ページをロードするたびに読み込んでも問題ない、と判断して毎回クライアントに渡すことにしました。

その結果、集計結果を切り替えても、アイコンをクリックして詳細を見ても、すべてブラウザ内で処理が可能になりました。サーバーにリクエストをする必要がなく、HTTP リクエストのラウンドトリップタイムがない分だけ、すばやくページ表示することができます。

ただ、この方法は万能ではなくて、すべてクライアントで処理する必要があるため、必要なデータだけをサーバーからとってくる Ajax に比べて、メモリや CPU の消費量が増えてしまうという問題もあります。作成するシステムに応じて、どれだけをサーバーに任せて、どれだけをクライアントに任せるかを判断する必要があります。

条件の追加

今回、すべてのデータをクライアントに転送していることを利用して、1つ面白いことができます。集計条件の追加です。

ソース一式をダウンロードして、alphavorite.js をエディタで開いてみてください。先頭で analyzers というハッシュがあるのですが、ここで集計方法を定義しています。

var analyzers = {
    count : {
        name : "各1pt",
        point : function(){return 1;},
        pixelPerRatio : 16
    },

    fav : {
        name : "被Fav数",
        point : function(hifav, fav, fromid, toid){return hifav},
        pixelPerRatio : 0.16
    },

    fav_ratio : {
        name : "被Fav数 / Fav数",
        point : function(hifav, fav, fromid, toid){return fav != 0 ? hifav / fav : 0},
        pixelPerRatio : 1.6
    }
};

この部分を修正することで、新たに集計方法を追加することができます。

例えば、id が3文字の人でランキングをとるには次のようにします。

    },
    num : {
        name : "3文字IDのみ",
        point : function(hifav, fav, fromid, toid){
            return toid.length == 3 ? 1 : 0;
        },
        pixelPerRatio : 16
    }
};

3文字ID

index.html をブラウザで開くだけで、3文字IDの集計をテストすることができます。データをすべて JavaScript が持っているおかげで、ローカル環境でも簡単にテストできるわけです。これこそ、サーバーレスと表現したおもしろさです。

他にも、例えば、id に数字を含む、とか、はてなの社員だけ、とか、いろいろやって遊べるかもしれません。

いちおうパラメータを解説。

  • name: 画面に表示する日本語名。
  • point: 大旦那が何点投票するかを示す値。
  • hifav: 大旦那の被Fav数。
  • fav: 大旦那のFav数。
  • fromid: 大旦那の id。
  • toid: 投票対象の id。
  • pixelPerRatio: 1ポイントを何ピクセルで表示するか。画面幅に合わせて適当に変更すべし。

おまけ

蛇足を2つほど。

最近のブックマークを取得する部分は、Drk7jp さんの XML を JSON に変換するサービス を利用しています。

もう1つの蛇足。擬似フレームっぽいデザインですが、JavaScript は使っていません。すべて CSS だけでデザインしました。CSS は jigelog さんのものを参考にさせてもらいながら作り上げました。