2009年02月02日

この記事をクリップ! b.hatena.ne.jp/entry Google Chromeのブックマークレットに好みのfaviconを割り当てる方法

Google ChromeのStableチャンネルでもそろそろGreasemonkeyが標準サポートされそうですね。それをきっかけにFirefoxのユーザーが本格的に乗り換えそうな気がします。

私はブラウザのブックマークバーにアイコン(favicon)だけ表示してるのですが、Google Chromeだとブックマークレットにアイコンを表示できない(白紙のアイコンが表示される)ので困ってました。

いろいろ調べたところ、ブックマークレットに好みのアイコンを表示できるようになったので、以下にやり方のメモを書いておきます。

一言で言うと、「特定のフォルダにURLとfaviconのデータがSQLiteデータベースに保存されているので、faviconを用意して、PerlスクリプトでそのDBを修正」します。

特定のフォルダは、XPだと、

C:\Documents and Settings\userid\Local Settings\Application Data\Google\Chrome\User Data\Default
Vistaだと
C:\Users\userid\AppData\Local\Google\Chrome\User Data\Default
になります。useridには、ユーザIDが入ります。

そのフォルダにあるHistoryというファイルで、URLとアイコンの対応付けがされていて、Thumbnailsというファイルで、アイコンに対応したPNGデータがBLOBで格納されています。

DBに格納するアイコンデータはPNG形式なので、別途、16x16サイズのPNGファイルを作っておいて、以下のスクリプトを実行すればOKです。

なお、スクリプトの実行には以下が必要です。

  • Chromeをすべて終了させる(DBがロックされるため)。
  • DBD::SQLiteが無ければインストールしておく。
  • History、Thumbnailsと同じフォルダで実行する。
  • History、Thumbnailsを事前にバックアップする(奨励)。
  • Google Chromeのバージョン(1.0.154.46)で動作確認済。
#!/usr/bin/perl
use strict;
use warnings;
use DBI qw(:sql_types);

# '%'が含まれないこと
my $book_url = "javascript:(function(){hoge;})()";
my $png_path = 'C:\hoge.png';

my $favicon_id = add_favicon($book_url, $png_path);

update_history($book_url, $favicon_id) if defined $favicon_id;

sub add_favicon {
    my ($book_url, $png_path) = @_;

    # PNGファイル(16x16)を読込む
    open my $fin, $png_path or die "can't open file";
    binmode $fin;
    my $buf = join('', <$fin>);
    close $fin;
    
    my $dbh = DBI->connect(
        "dbi:SQLite:dbname=Thumbnails", undef, undef, {
            RaiseError => 1,
            AutoCommit => 0,
        }
    );

    my $last_rowid = undef;

    eval {
        my $sth = $dbh->prepare('select id from favicons where url = ?');
        $sth->bind_param(1, $book_url);
        $sth->execute();
        my @data = $sth->fetchrow_array();
        $sth->finish();
        undef $sth;

        if (scalar(@data) > 0) {
            print "update id($data[0])'s image_data\n";
            my $sth2 = $dbh->prepare('update favicons set image_data = ? where id = ?');
            $sth2->bind_param(1, $buf, SQL_BLOB);
            $sth2->bind_param(2, $data[0]);
            $sth2->execute();
            $dbh->commit();
            $last_rowid = $data[0];
        } else {
            print "insert image_data\n";
            my $sth2 = $dbh->prepare('insert into favicons(id, url, image_data) values (null, ?, ?)');
            $sth2->bind_param(1, $book_url);
            $sth2->bind_param(2, $buf, SQL_BLOB);
            $sth2->execute();
            $dbh->commit();
            $last_rowid = $dbh->func('last_insert_rowid')
        }
    };

    if ($@) {
        warn "db error: $DBI::errstr\n";
        $dbh->rollback();
    }

    $dbh->disconnect() or warn $!;
    
    return $last_rowid;
}

sub update_history {
    my ($book_url, $favicon_id) = @_;
    
    my $dbh = DBI->connect(
        "dbi:SQLite:dbname=History", undef, undef, {
            RaiseError => 1,
            AutoCommit => 0,
        }
    );

    eval {
        my $sth = $dbh->prepare('select id, url, favicon_id from urls where url = ?');
        $sth->bind_param(1, $book_url);
        $sth->execute();
        my @data = $sth->fetchrow_array();
        $sth->finish();
        undef $sth;

        if (scalar(@data) > 0) {
            print "update id($data[0])'s favicon_id to $favicon_id\n";
            my $sth2 = $dbh->prepare('update urls set favicon_id = ? where id = ?');
            $sth2->bind_param(1, $favicon_id);
            $sth2->bind_param(2, $data[0]);
            $sth2->execute();
            $dbh->commit();
        } else {
            print "insert favicon_id $favicon_id\n";
            my $sth2 = $dbh->prepare('insert into urls(id, url, last_visit_time, favicon_id) values (null, ?, 1, ?)');
            $sth2->bind_param(1, $book_url);
            $sth2->bind_param(2, $favicon_id);
            $sth2->execute();
            $dbh->commit();
        }
    };

    if ($@) {
        warn "db error: $DBI::errstr\n";
        $dbh->rollback();
    }

    $dbh->disconnect() or warn $!;
}

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gotospace/51172937
この記事へのコメント
この記事へのコメントではないのですが、適当なところがわかりませんでしたので、ここを使わせていただきます。

携帯からの開示情報を使わせていただき、ありがとうございます。

さて、RSS配信を利用しているのですが、Htmlページに表示されている情報数と比べると、明らかに少ないと思います。そのため、決算発表が集中した時刻では情報が抜け落ちてしまいます。

技術的な理由があるのかも知れませんが、可能であれば、できるだけ多くの最新情報を含めた状態で発信していただけましたらうれしいです。

よろしくお願いします。
Posted by だる at 2009年02月06日 15:29
だるさん

拙Webサービスをご活用くださり、また、貴重なご指摘をありがとうございます。

なるべく早期に、より多くの最新情報を含めてRSS発信できるように内部処理を変更して行きますので少しお時間をください。

今後ともどうぞよろしくお願い致します。
Posted by gotospace at 2009年02月07日 01:50
だるさん

応急処置として、HTMLページに表示する情報とRSSに含める情報が同一となるように改修いたしました。

引き続き、改善したいと思いますので、よろしくお願いします。
Posted by gotospace at 2009年02月08日 00:14
gotospaceさん

さっそくの対応ありがとうございます。

私は自作チャートソフトで、銘柄関連項目をインターネットから取り込んだり、IEで表示しています。以前から、大量保有報告書DBは利用させていただいてます。この機会にと思い、ブログを一気に読みました。

>>2006年02月02日 慣れ→処理高速化→需要増→オーバーフロー。(^^;

すごく共感しました。

>>2008年05月10日 特定の日付に対する休場判定処理ソースコード

使えるかわかりませんが、私の方法を紹介しておきます。
東証カレンダーの仕様変更に対応する必要はありますが、祝日法や東証の業務規定の変更は気にする必要がありません。

立会日の判定を記入したカレンダーを用意しておく方法です。
未来の部分は東証カレンダーより取得。
http://www.tse.or.jp/tseHpFront/HPTCDS0701.do?method=init

過去の部分は、継続的に必ずある日経平均を利用。日経平均過去データは下記サイトより取得。
http://www3.nikkei.co.jp/nkave/data/index.cfm

>>2005年09月19日
○最近、分析にかかる時間をより短くするために、
 今までExcelで作っていたシステムを、Webサービスに移行させています。

体系的なことは何もわかってないのですが、Webサービスに移行すると高速化できるようですね。

ブログを読み進めていると、記事の投稿時より、かなり後から付いたコメントにもすぐに返信されているのをみましたので、
この一連のやりとりがすみましたら、今後はもう少し関連性のある記事にコメントするようにします。

あと、最初に返信して頂いた二番目のコメントですが、実際には見れない状態が、私の環境では長かったです。取り消されたのかと思いましたが、時刻を見るとそうでもなかったようで、少し不思議に思いました。

以上、長々と書いてしまいましたが、あらためて、すばやく対応していただいたことに感謝いたします。
Posted by だる at 2009年02月09日 00:29
だるさん

ブログのかなり古い投稿までお読みいただいてありがとうございます。感謝です。

>>使えるかわかりませんが、私の方法を紹介しておきます。

貴重な情報をありがとうございます。東証カレンダーのデータから反映する方法は確実で良い方法ですね。日経平均を見ると、昔の人は良く週6日も働けたものだなぁと思ってしまいます。

>>最初に返信して頂いた二番目のコメントですが、実際には見れない状態が

実は私も見れませんでした…。同じ内容を投稿しようとするとエラーになるので、データは格納されたということは分かったので、様子を見ました。(livedoor Blogでは時々コメント反映が遅れるようです)

また何かお気づきになられましたら是非ご連絡いただけるとありがたいです。よろしくお願いします。
Posted by gotospace at 2009年02月09日 01:27
 (管理人にのみ通知)
 (管理人にのみ通知)
 
月別コラム
スポンサード リンク
逆アクセスRanking
実験中
あわせて読みたい
livedoor Blog
このBlogをはてなRSSに追加 このBlogを
はてなRSSに追加
このBlogをチェッカーズに追加 このBlogを
チェッカーズに追加
このBlogをリーダーに追加 このBlogを
リーダーに追加
アクセス解析