あとで読む率を算出するブックマークレット

コンセプト:「あとで読む率」

大漁にブックマーカーが釣れているからといってその記事が有意義な記事であるとは限らない。というのもブックマークは必ずしも読まれた後にされるとは限らないからだ。大手サイトが一見役に立ちそうな題名を付けて比較的長い文章を載せた場合、「あとで読む」というタグをつけてブックマークされることがしばしばある。このような「あとで読む」タグは記事の内容に関係なくその数が決まる。
他方、その他のブックマークは善かれ悪かれ記事の内容に反応して為される。したがってブックマーク数は記事の内容に影響される。(もっとも、ブックマーク数が多いからといって価値のある記事だという訳ではない。大手が書いた記事は中身が無くてもブックマークされる。が、その議論は今回は無視。)


と、いうわけで。
タイトルは立派でも中身の無い記事は、「あとで読む」は釣れても読後のブクマは少なくなる、ような気がする。その結果、被ブックマーク数に占める「あとで読む」ブックマークの割合が大きくなる。そこで
「あとで読む率」 = 「あとで読む」ブックマーク数 ÷ 総ブックマーク数
という式に当てはめて求める「あとで読む率」は、看板倒れな記事ほど高くなることが考えられる。
(したがって「あとで読む率」は「看板倒れ度」とか「ヨウトウクニキシティ」とか呼びうるだろう。)


つっても看板倒れ度は一つの観測手段にすぎないというかむしろネタなので、あまり真剣に考えられても困るわけですけど。

あとで読む率Bookmarklet

javascript:void((function(){ function JSONscriptRequest(fullUrl) {     this.fullUrl = fullUrl;      this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();     this.headLoc = document.getElementsByTagName("head").item(0);     this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++; }; JSONscriptRequest.scriptCounter = 1; JSONscriptRequest.prototype.buildScriptTag = function () {     this.scriptObj = document.createElement("script");     this.scriptObj.setAttribute("type", "text/javascript");     this.scriptObj.setAttribute("charset", "utf-8");     this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);     this.scriptObj.setAttribute("id", this.scriptId); }; JSONscriptRequest.prototype.removeScriptTag = function () {     this.headLoc.removeChild(this.scriptObj); }; JSONscriptRequest.prototype.addScriptTag = function () {     this.headLoc.appendChild(this.scriptObj); }; function countRIL(jsonData) { var count = 0; findRIL = function(bm, index, array){ for(var i=0; i<bm.tags.length; i++){ if(bm.tags[i] == "あとで読む") count++; } }; jsonData.bookmarks.forEach(findRIL); return count; }; document.callback = function(jsonData){ var ril = countRIL(jsonData); var bkms = jsonData.bookmarks.length; document.title = document.title + ':あとで読む率='+Math.round((ril/bkms)*10000)/100+'%('+ril+'/'+bkms+')'; bObj.removeScriptTag();  }; var que = escape(document.URL); var req  = 'http://b.hatena.ne.jp/entry/json/?url='+que+'&callback=document.callback';  var bObj = new JSONscriptRequest(req);  bObj.buildScriptTag();  bObj.addScriptTag(); })()); 

例の如くはてなの驚き最大の法則によりブックマークレットを普通に記事に貼れないので、↑のコードをコピペしてブックマークして下さい。任意のページで使うと、ページタイトル(ウィンドウのタイトルになってる奴ね)の後ろにはてブでの「あとで読む率」,「あとで読む」数,総ブクマ数が付け足されます。
動作確認 on Firefox 2.0

参考資料。どんぐらいなら羊頭狗肉

おそらく凄く高い方であろうと思われる『Linuxをいまから学ぶコツ教えます:Linuxをいまから学ぶコツ教えます - @IT』では13%くらいでした。10%越える記事はちょっと凄いんじゃないかと思います。

コード解説。

上のコードは下のコードに相当するものをブックマークレットとして1行にしたものです。

// Constructor -- pass a REST request URL to the constructor
//
function JSONscriptRequest(fullUrl) {
    // REST request path
    this.fullUrl = fullUrl; 
    // Keep IE from caching requests
    this.noCacheIE = '&noCacheIE=' + (new Date()).getTime();
    // Get the DOM location to put the script tag
    this.headLoc = document.getElementsByTagName("head").item(0);
    // Generate a unique script tag id
    this.scriptId = 'JscriptId' + JSONscriptRequest.scriptCounter++;
}
// Static script ID counter
JSONscriptRequest.scriptCounter = 1;

// buildScriptTag method
//
JSONscriptRequest.prototype.buildScriptTag = function () {
    // Create the script tag
    this.scriptObj = document.createElement("script");
    // Add script object attributes
    this.scriptObj.setAttribute("type", "text/javascript");
    this.scriptObj.setAttribute("charset", "utf-8");
    this.scriptObj.setAttribute("src", this.fullUrl + this.noCacheIE);
    this.scriptObj.setAttribute("id", this.scriptId);
}
// removeScriptTag method
// 
JSONscriptRequest.prototype.removeScriptTag = function () {
    // Destroy the script tag
    this.headLoc.removeChild(this.scriptObj);  
}
// addScriptTag method
//
JSONscriptRequest.prototype.addScriptTag = function () {
    // Create the script tag
    this.headLoc.appendChild(this.scriptObj);
}

//以下、俺コード
// RIL = Read it later. 「あとで読む」の英訳のつもり。
function countRIL(jsonData) {
	var count = 0;
	findRIL = function(bm, index, array){
		for(var i=0; i<bm.tags.length; i++){
			if(bm.tags[i] == "あとで読む") //ここを変えれば「これは酷い」率とかもできる。
				count++;
		}
	}
	jsonData.bookmarks.forEach(findRIL); //forEach使うんなら上でも使えよ俺orz
	return count;
}
// はてブのJSONPのcallback。documentにくっつけてやる。
document.callback = function(jsonData){
	var ril = countRIL(jsonData);
	var bkms = jsonData.bookmarks.length;
	document.title = document.title + ':あとで読む率='+Math.round((ril/bkms)*10000)/100+'%('+ril+'/'+bkms+')';
	bObj.removeScriptTag(); 
}
var que = escape(document.URL);
var req  = 'http://b.hatena.ne.jp/entry/json/?url='+que+'&callback=document.callback'; 
var bObj = new JSONscriptRequest(req); 
bObj.buildScriptTag(); 
bObj.addScriptTag();

とりあえずコメント読んで下さい。
JSONPを扱うのにJSON and the Dynamic Script Tag: Easy, XML-less Web Services for JavaScript様のjsr_class.jsをまんま流用させて頂きました(「俺コード」より上の部分)。Greasemonkeyとかだとクロスドメインの制約無しで出来るんだけど、ブックマークレットだとそうもいかないので、普通のWebページでJSON使う時と同じ苦労が必要ということで。あ、流用したのは2005-12-07時点のコードなので、本家は新しくなってるかもしれません。また、Bookmarkletで必要な機能に絞ればもっと直接的で単純なコードに出来るかもしれません。今回はとりあえず動けば良いのよ。
Array.forEachはJavaScript1.5なのでFx以外で動くかどうかよく解りません。物珍しさに手を出してみただけなので、普通にforループとかでやっても良いです。
ブックマークレットにする場合、変数に(無名?)関数を代入する場合には中括弧の後に;をいれて行を閉じなきゃいけないみたいです。
条件分岐を"あとで読む"|"後で読む"にすればより正確に計れるかもしれないけど、そもそも性格に測ってどうというものでもないし、まぁ暇な人は改造しておくれ。条件分岐(とタイトル書き換え部分)を書き換えれば他のタグの率も出せます。
ちょっと応用すれば、『http://www.ohmynews.co.jp/News.aspx?news_id=000000001743』の炎上係数=コメント数÷トラックバックに似たノリで、地の文のあるはてブの率も求められますね。だからどーこー言うつもりは無いですが。

それGre?

全てのページでいちいちヨウトウクニキシティを計測するというのはネチケ的(主に?の鯖と帯域の負担)にも人格的にもアレなので、気になった記事でだけ使うBookmarkletの方が良いと思います。