6月
08
2011
2

はてブエントリーページを旧仕様っぽくする Greasemonkey

はてブエントリーページを旧仕様っぽくする Greasemonkey である、はてブエントリーページ旧仕様化 を公開しました。

リリース直後から、様々な非難を受けていた現仕様のはてブエントリーページですが、あれほどの反応にもかかわらず、リリースから 2 ヶ月経っても、旧仕様を選べるようにするなどの対応は取られていないようです。

個人的な感想で言うと、旧仕様の時もスターの数を頼りに流し読みする事もあったし、完全否定という立場ではないのですが、はてブの伸びを表すグラフとか良く見てたので、それが見れないのと、やはり多くの指摘にあるように、時系列でブコメを追いたい時にいちいち違うページを開くのが面倒という思いがありました。

そして 2 ヶ月。1 クリックごとのフラストレーションが、徐々に溜まり続けました。

2 ヶ月経ってもはてなからは特に動きが無いので、これはもう「こっち (運営) でやる気はないから、どうにかしたいならそっち (ユーザ) で何とかしな!」というはてなからの挑戦だと受け取り、上記のスクリプトを書きました。

単に、「すべてのブックマークを見る」にリダイレクトするのではなく、現状のエントリーページの中に、全てのブックマークをスムーズに統合して、出来る限り (記憶にある限り) 旧仕様に近づけているのが特徴です。
「人気のブックマークコメント」情報はあっても良いかと思ったので、項目自体は残しつつ、不要な時は閉じられるように配慮しています。

当初、もう少し簡単に出来るかなと思っていた部分が、案外難しく、はてブ側のスクリプトの中にまで手を入れて実現している機能とかがあります。
はてなで作って使っている JavaScript のライブラリに妙に詳しくなったりしつつ、試行錯誤を繰り返し、ようやく公開出来るレベルにまでなりました。

現仕様のエントリーページに苦々しい思いを持っている方は、是非おためし下さい。

はてなの方へ

上で色々と生意気な事を書きましたが、公式に対応して旧仕様を選べるようにしてもらえるのがベストに決まっています。
公式に対応されればこちらでもアナウンスして、公式機能の利用を促すようにするので、サーバに負荷をかける部分もあって恐縮ですが、公式対応までの間はお目こぼし頂けるととても嬉しいです。

参考にしたページなど

2011-04-05 – はてなブックマーク日記 – 機能変更、お知らせなど
はてなブックマークのエントリーページ改良が何を狙っているのか – 没個性テーマパーク
はてブのエントリーページ“改良”に疑問の声 – さまざまなめりっと
はてなブックマークのUIが大幅リニューアル(個人的に改悪)な件 – y-kawazの日記
新しいはてブが不評と聞いたので、全てのブックマークを見るグリモンスクリプトを作ったよ!(使えるかもしれないものが出来たので追記あり) – 不動産屋のラノベ読み

Written by Otchy in: Development | タグ: , ,
6月
01
2011
2

[α版]はてブエントリーページを旧仕様っぽくする Greasemonkey

はてブのエントリーページを旧仕様っぽくする Greasemonkey 書きました。
まだ超α版なので、user.js ファイルでは置きません。
Chrome でしか確認してないです。まあ Firefox でも動くんじゃないかな?たぶん。

// ==UserScript==
// @name         Hatebu Entry Page Downgrader
// @namespace    http://www.otchy.net/
// @version      0.0.1
// @include      http://b.hatena.ne.jp/entry*
// ==/UserScript==

(function (callback) {
    var script = document.createElement("script");
    script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js");
    script.addEventListener('load', function() {
        var script = document.createElement("script");
        script.textContent = "(" + callback.toString() + ")();";
        document.body.appendChild(script);
    }, false);
    document.body.appendChild(script);
})(function() {
    var isMore = (location.href.indexOf('mode=more') >= 0);
    if (!isMore) {
        var iframe = $('<iframe />');
        iframe.hide();
        $(document.body).append(iframe);
        var href = $('#more-link a').attr('href');
        iframe.attr('src', href);
    } else {
        var pBody = $(parent.document.body);
        var iBody = $(document.body);
        var bk = iBody.find('#new-bookmarks');
        pBody.find('#new-bookmarks').html(bk.html());
        pBody.find('ul.bookmark-list li').css({'padding': '5px 0px 5px 30px'}).find('img.profile-image').css({'width': '16px', 'height': '16px', 'margin-left': '-20px'});
        var scored = pBody.find('#scored-bookmarks');
        var sToggle = $('<span />').toggle(function() {
            scored.find('.bookmark-list').hide();
            $(this).text('[開く]');
        }, function() {
            scored.find('.bookmark-list').show();
            $(this).text('[閉じる]');
        });
        scored.find('h4.entry-page-main-subtitle .inner').append(sToggle);
        sToggle.css({'cursor': 'pointer'}).click();
    }
});

出来る事

  • エントリーページの「新着」ブックマークを「全ての」ブックマークに差し替え
  • ユーザのアイコンを 16 x 16 に変更
  • 人気のブックマークの表示/非表示切り替え

出来ない事

  • コメントのみ表示チェックが効かない
  • スターが付けられない
  • グラフが見れない

現状は、全てのブックマークを表示するページから HTML を親ページに流し込んでる実装です。
この実装だと、上記の問題解決はかなり難しそうです。
なので、全てのブックマークページをそのまま iframe で埋め込む方法に実装を変更する予定なのですが、とりあえず情報参照だけなら綺麗に動いたのでアルファ版として公開してみました。

フィードバック、改造報告などがあれば是非コメントに!

Written by Otchy in: Development | タグ: ,
1月
29
2010
2

Chrome 正式版 Greasemonkey でクロスドメイン POST をする方法

最近公開された、Google Chrome の Ver 4 では、正式に Greasemonkey がサポートされ、以前のように特別なオプションを指定することなく、ワンクリックでユーザスクリプトがインストール出来るようになりました。
それ自体は非常に嬉しい事だったんですが、バージョンアップに伴い、はてブ with Twitter が動かなくなってしまっていました。(現在は修正済み)

以前、JavaScript だけでクロスドメインで POST メソッドを送る方法で紹介したやり方が、Chrome のバージョンアップによって無効になってしまったためです。
無効になったとはいえ、通常の JavaScript として使用する分には問題なく、Greasemonkey だけに問題が発生していました。
動的に生成した iframe の contentWidow オブジェクトが取得出来なくなっており、セキュリティの制限が強化されたものと思われます。

最終的にはその制限を回避する方法を見つけたので、以下に解説します。

通常 JavaScript の記述

まず、Greasemonkey ではなく普通の JavaScript としてJavaScript だけでクロスドメインで POST メソッドを送る方法等を参考に、本来やりたい処理を記述します。
この時は普通に script タグでスクリプトを読み込んで、正常動作を確認しておきます。

そして、正常に動作するスクリプトが作成出来たら、それを任意のサーバにアップします。

Greasemonkey の記述

以下のようなスクリプトを書きます。

(function() {
    var d = document;
    var s = d.createElement('script');
    s.src = 'http://www ...'; // スクリプトファイルをアップした場所
    d.body.appendChild(s);
})();

これだけで、本来の window オブジェクトから実行したかった処理が実行され、Greasemonkey の制限に掛かることなく、iframe を使用したクロスドメイン POST が実現します。

でもちょっと待って

Greasemonkey が実行されるたびに、自分のサーバから js ファイルがダウンロードされるなんて嫌ですよね?私は嫌です。レスポンスを考えたって好ましくないですし。

そこで、data スキームを使って外部スクリプト自体を Greasemonkey スクリプトの中に埋め込んでしまう事にします。(data スキームについてはこの辺を参照して下さい。)

data スキームへの変換には、[JavaScript] dataスキームURI生成(画像データのBase64変換)を使用させていただきました。
このサイトで、先ほどアップした js ファイルの URL を指定し、data スキームに変換した文字列を取得します。

その上で、Greasemonkey を以下のように書き換えます。

(function() {
    var data = 'data:application/x-javascript;base64,'+
        'KGZ1bmN0aW9uKCkgewoJdmFyIGQgPSBkb2N1bWVudDsKCWZ1bmN0aW9uIGdldEVsZW1lbnQoeHBh'+
        // 中略
        'fSkoKTs=';
        var d = document;
    var s = d.createElement('script');
    s.src = data;
    d.body.appendChild(s);
})();

これで、単体の Greasemonkey スクリプトでありながら、外部スクリプトを読み込んだのと同等の状況を作り出す事が出来ます。

これでスッキリしましたね!

Written by Otchy in: Development | タグ: , , ,
8月
04
2009
2

Google Chart API を使って自サイトの合計はてブ数をグラフ化する

日頃、自サイトにはてブが付いて増えていく様子を、TopHatenar でグラフを見てほくそ笑んでいたりしたのですが、TopHatenar は更新が遅れることが多く、残念な気持ちになることも度々ありました。

そこで以前、せめて記録だけは残そうと、自分のサイトの合計はてブ数を淡々と csv に記録し続けるというエントリを書いて、それ以来ずっと記録しています。
それでまあ、そろそろデータも貯まってきたので予告通り(?)、グラフ化してみる事にしました。
ブログパーツのようにして、このサイトの右メニューにも貼り付けてあります。

大きく出すとこんな感じです。

当初、PHP で何らかのライブラリを使用して楽をしようと思ったのですが、自分の希望を全て満たすものが見あたらなかったので、自力で Google Chart API を使用しています。

グラフの元になるデータは、自分のサイトの合計はてブ数を淡々と csv に記録し続けるで取得したものです。
下記のようなファイルになっています。

2009-07-16,204
2009-07-17,205
    :
    :
2009-08-03,245
2009-08-04,250

これを元に、Google Chart API のパラメータを生成して、グラフを表示しています。
以下にソースを載せておきます。

<?php

/* グラフ設定 */
$api = 'http://chart.apis.google.com/chart?'; // Google Chart API の URL
$width = 400; // 画像の横
$height = 300; // 画像の縦
$type = 'lc'; // グラフの種類 (折れ線グラフ)
$yUnit = 10; // Y軸の単位 (データの内容によって調整)
$csv = '/your_file_dir/hatebulog.csv'; // 読み取る CSV ファイル

/* データ取得 */
$fp = fopen($csv, 'r');
$data = array();
$isFirst = true;
while (($values = fgetcsv($fp)) !== FALSE) {
	if ($isFirst) {
		$firstDate = substr($values[0], 5);
		$isFirst = false;
	}
	$lastDate = substr($values[0], 5);
	array_push($data, (int) $values[1]);
}
fclose($fp);

/* yUnit に基づいてデータを正規化(0.0~100.0 の範囲に調整する) */
$min = (int) min($data); // グラフ上の最小値
while (($min % $yUnit) != 0) {
	$min--;
}
$max = (int) (max($data) + 1.0); // グラフ上の最大値
while (($max % $yUnit) != 0) {
	$max++;
}
$range = (float)($max - $min); // グラフ描画範囲
$normalizeData = array(); // 正規化データ
foreach ($data as $d) {
	$d = (float) $d;
	$d = ($d - $min)/$range * 100.0;
	array_push($normalizeData, number_format($d, 1));
}

/* min, max, yUnit に基づいて、Y軸を生成 */
$yAxis = array();
for ($y = $min; $y <= $max; $y+=$yUnit) {
	array_push($yAxis, $y);
}
$yDiv = number_format((100.0 / (count($yAxis)-1)-0.1), 1); // Y 軸の分割

/* タグ を生成 */
$url = $api . 'chs=' . $width . 'x' . $height .
	'&amp;cht=' . $type .
	'&amp;chd=t:' . implode(',', $normalizeData) .
	'&amp;chxt=x,y&amp;chxl=0:|' . $firstDate . '|' . $lastDate . '|1:|' . implode('|', $yAxis) .
	'&amp;chg=0,' . $yDiv
;
$tag = '<img src="' . $url . '" width="' . $width . '" height="' . $height . '" alt="" />'
?>
<html>
<head>
<style>
* {
	margin: 0;
	padding: 0;
	border: 0;
}
</style>
</head>
<body>
<?php echo $tag ?>
</body>
</html>

ソース中にざっくりとコメントを書いておきましたが、ポイントになるのは、Google Chaart API の線グラフでは、Y 軸の値が、0.0~100.0 と固定されていて、グラフを描画する値をその範囲の値に正規化しないといけない点です。
値を正規化したら、Y 軸のラベルには、その正規化された世界で本来の値がどこになるのか、という情報を渡してやる必要がありますね。
そんな処理が上に書かれています。

X 軸についてはシンプルに、最初と最後の日付を載せているだけです。

また、今回は元データが整数値なのですが、汎用性を考えて、仮に小数の値が元データになっても問題なく動作するように書いたつもりなので、小数のデータであってもきっと上手く動作するでしょう。
整数値前提となっている部分がありました…。

追記

元データの行数が増えてくると、グラフとして描画するのが苦しくなってくることが予想されます。
その場合、csv を保存した後に、tail -n 60 hatebulog.csv > hatebulog_tail.csv のようにしておいて、最新の何件かを取り出すようにするといいでしょう。

Written by Otchy in: Development | タグ: ,
7月
16
2009
2

自分のサイトの合計はてブ数を淡々と csv に記録し続ける

Twitter ボットの作り方 Perl 編 連載中ですが、ちょっとお休みして、さっき思い立って書いたスクリプトを紹介します。

最近、TopHatenar の更新が止まってしまっていて悲しいので、自分のサイトのトータルはてブ数を記録して、自分でグラフを書くことにしました。
といっても、自分が見る専用で問題ないので、csv を出力しておくだけです。適宜 Excel とかで加工してグラフ化します。

まず必要になる CPAN モジュールをインストールします。root 権限必須です。

$ su -
# cpan
cpan> force install XMLRPC::Lite
cpan> install DateTime

XMLRPC::Lite は自分の環境だとテストで引っかかって上手く入らなかったので、force install してます。
force install する前に、通常の install で入れられないかを試すべきです。
いずれのインストールも結構時間がかかるので、原則放置でたまに Enter を押してやる感じです。

実際のスクリプトは下記のような感じです。
標準出力に吐くようにしたので、ファイルに記録したい場合は任意にリダイレクトしてやります。

#!/usr/bin/perl

use strict;
use warnings;
use XMLRPC::Lite;
use DateTime;

my $url = 'http://www.otchy.net';

my $count = XMLRPC::Lite
    ->proxy('http://b.hatena.ne.jp/xmlrpc')
    ->call('bookmark.getTotalCount', $url)
    ->result;

my $now = DateTime->now(time_zone => 'Asia/Tokyo');
print $now->strftime('%Y-%m-%d') . ',' . $count . "\n";

$url の値はカウント対象の URL ですが、もちろん変更して下さい。
スクリプトに実行権限を与えて実行すると、こんな感じの出力が出てきます。

2009-07-16,204

毎日の記録を残すのであれば、例えば下記のように cron に登録すればいいです。

00 00 * * * /home/your_id/hatebulog/hatebulog.pl >> /home/your_id/hatebulog/hatebulog.csv

今のところ日次で記録する前提で日付しか出力していませんが、はてブ数が多くもっと頻繁に記録するのであれば、出力を下記のように変える事で実行時間も記録されます。

print $now->strftime('%Y-%m-%d %H:%M:%S') . ',' . $count . "\n";

最初に自分専用とはいったものの、いったん csv に落としてしまえば、PHP + Google Chart API でグラフ化して Web から見れるようにするとかもありですね。

追記(2009-08-04)

グラフ化してみました!

Written by Otchy in: Development | タグ: ,

Powered by WordPress | Aeros Theme | TheBuckmaker.com