はてなブックマークにはサイト内のブックマーク数合計を表示してくれるはてブカウンターというのがあります。他のSBMには無い機能ですが、サイトの人気度を示す良い指標だと思っています。
参考:はてブ数1000越え記念に、はてブカウンターの使い方を調べた
同じ事をDeliciousでもできないか?というのが今回のお題なのですが、すでに先人がRubyで実装されておりました。
del.icio.us では、 JSON URL Feeds を使用して「ページのブックマーク数」を取得できます。 「サイトの合計ブックマーク数」を取得するには、 「ページのブックマーク数」と同じ要領で、サイトが保有しているすべての URL を処理します。
これをPHPでやってみようと思います。
実装の準備
下準備として必要な情報をまとめておきます。
1)Deliciousのブックマーク数取得API
DeliciousではJSON Feed APIを使ってブックマーク数が取得できます。
# Summary information about a URL (as seen in the tagometer):
# http://feeds.delicious.com/v2/json/urlinfo/{url md5}via: delicious/help/feeds
旧del.icio.usでは複数の(MD5された)URLをパラメータに渡して一度にデータを取得できました。
http://badges.del.icio.us/feeds/json/url/data?hash={url md5[&hash={url md5}...]}
新しいAPIでも同じ事ができるか試したところ問題なくできるようです。
http://feeds.delicious.com/v2/json/urlinfo/data?hash={url md5[&hash={url md5}...]}
サンプルでは一度に100件ずつ取得しています。
負荷とか大丈夫なのだろうか…。
2)サイト内のURL一覧を用意する
DeliciousではURLをキーにして検索する事ができず、同様にそのようなAPIも存在しません。
なので、調べるURLのリストを自分で用意する必要があります。
このブログはMTを使っているので、DB(MySQL)のmt_entryテーブルからSQLで公開されているエントリーURL一覧を作ってみました。
エントリーURLのフォーマットは下記のようになるので、
http://creazy.net/(年:YYYY)/(月:MM)/ファイル名.html
「公開日」と「ベースネーム(ファイル名)」を取得するSQLは下のような感じ。
select entry_created_on,entry_basename from mt_entry where entry_status = 2 // 公開 order by entry_created_on desc
3)JSONのパースはPEAR::Services_JSONで
DeliciousのAPIはJSONで返ってくるのでライブラリを使ってパースします。
参考:PHPでJSON – Do You PHP?
別のライブラリでもいいですけど。
サンプルコード
<?php
/**
* Deliciousのサイト内ブックマーク数合計を取得するサンプル
*
* @author yager <yager[ at ]creazy.net>
* @see http://delicious.com/help/feeds
* @memo 各URLのブックマーク数を取得するJSON API
* http://feeds.delicious.com/v2/json/urlinfo/{url md5}
* http://feeds.delicious.com/v2/json/urlinfo/data?hash={url md5[&hash={url md5}...]}
*
*
*/
require "JSON.php";
$api_base = 'http://feeds.delicious.com/v2/json/urlinfo/data?hash=';
$api_delimiter = '&hash=';
//------------------------------------------------------------
// 調べるURL一覧の生成(DBから直接取得)
//------------------------------------------------------------
// DB接続
$link = mysql_connect('{DBホスト}', '{DBユーザ}', '{DBパスワード}');
mysql_select_db('{DB名}',$link);
// 公開中のエントリー一覧を取得
$sql
= "select entry_created_on,entry_basename "
. " from mt_entry "
. " where entry_status = 2 "
. " order by entry_created_on desc ";
$res = mysql_query($sql);
$hashes = array();
$i = 0;
$j = 0;
// エントリーURLを構築
while( $row = mysql_fetch_array($res) ) {
// format : http://creazy.net/YYYY/MM/{BASE_NAME}.html
$yyyy = date('Y',strtotime($row['entry_created_on']));
$mm = date('m',strtotime($row['entry_created_on']));
$url = "http://creazy.net/$yyyy/$mm/".$row['entry_basename'].".html";
// 100件ずつ分けて配列に格納
if ( count($hashes[$i]) >= 100 ) $i++;
$hashes[$i][] = md5($url);
}
//------------------------------------------------------------
// ブックマーク数を取得
//------------------------------------------------------------
foreach ( $hashes as $hash ) {
// API接続
$api_url = $api_base . implode($api_delimiter,$hash);
$api_res = file_get_contents($api_url);
// JSONをパース
$json = new Services_JSON();
$list = $json->decode($api_res);
foreach ( $list as $data ) {
if ( $data->total_posts <= 0 ) continue;
echo (++$j) . ' : ' . $data->hash . ' : ' . $data->url . ' : ' . $data->total_posts . '<br />';
// ブックマーク数を加算していく
$site_total_count += $data->total_posts;
}
}
echo "total : $site_total_count<br />";
?>
上記スクリプトを実行してみた結果はこんな表示です。
1 : f3dda99e9ab4eb0c887c4097384b0958 : http://creazy.net/2008/08/apple_store_outlet_notifier.html : 1 2 : 0f30e1027140c627d5c1d742e2a0c14c : http://creazy.net/2008/08/can_isp_access_remote_desktop.html : 1 3 : b1cb03dab8c7987147f2b74ba4f0394f : http://creazy.net/2008/08/add_sbm_counter_mt_plugin.html : 1 4 : 2bcd0e1efdb594bd968e7a2739cffccc : http://creazy.net/2008/08/livedoor_reader_with_sbm_counter_greasemonkey.html : 8 5 : d34ad26f5d1700c6f3b2a960699598de : http://creazy.net/2008/08/delicious20_counter_image_api.html : 18 6 : 51c5857693640b768f51d098fedaf128 : http://creazy.net/2008/07/post_a_mixi_dialy_from_php.html : 13 7 : fa8e472e7c66897529895ae8c40bc472 : http://creazy.net/2008/07/sbm_common_api.html : 21 (省略) 95 : 69928391ce85d7754733d2e8faf87728 : http://creazy.net/2007/02/post_39.html : 1 96 : ca2f5e0033a57ea99a147f7ee6ee9598 : http://creazy.net/2006/12/javascript.html : 9 total : 595
まとめ
結構処理が重いので実用には耐えられないかもしれないです。
特にリアルタイムで出すのは厳しいのでやるとしてもバッチ処理ですかね。
ってか、これ使って何かアイデア出てくるかなぁ・・・。