実用! 画像でブックマーク数を返すSBMからブックマーク数を数値で取得

| 0 Comments | 0 TrackBacks | このエントリーをはてなブックマークに追加 このエントリーのはてなブックマーク件数

こんにちは! この前会社のCentOS4のサーバをyumったらPerl5.8.5のパッケージが更新されてしまい、CPANから入れたEncodeモジュールがパッケージのでデグレードしてしまい、メール送信で使っていたencode('MIME-Header-ISO_2022_JP', $foo )が動かなくなって涙目になりました。

さて、前回実用! Perlで少しでもSBMのブックマーク数を多く見せる - perl-mongers.orgでは、いろいろなソーシャルブックマークサービス(以下SBM)に用意されたWeb APIにアクセスし、ブックマーク数の合計をとるということをやりました。

今回は、SBMから得られる特定URLのブックマーク数が、イメージで得られるタイプの場合、どうやって数値として使えるか、というのをやってみます。本来想定された用途以外の使い方にチャレンジする、という意味では、Hackと言えると思います。

~~~

たとえば、FC2ブックマーク、画像としてブックマーク数を表示できるようになっています。

http://bookmark.fc2.com/image/users/http://perl-mongers.org/

で、

が得られます。

コンピュータが画像から文字を解読するのは大変

SBMから得られる画像に数字が書いてある場合、その画像から数字を認識させるのはかなり困難です。あらかじめ得られる画像データの特徴リストを持っておき、それと照合する、なんてことをすれば簡単になりますが、SBMサービス側の気まぐれで、「画像内の数字をかっこよくしよう」、なんてやられてしまった日には涙目です。

というわけで、画像を解析して数字を得るって言うのはあんまり現実的ではないです。

隠れたところにブックマーク数として採用できるデータが!

さて、画像を解析するのがボツになったので、じゃあどうやって、ブックマーク数の情報を取得するのか、という話なんですけれども、先ほどの

http://bookmark.fc2.com/image/users/http://perl-mongers.org/

にブラウザでアクセスすると、

ブラウザのアドレス欄が、"http://bookmark.fc2.com/icons/00002.png"とかになっていることに注目。つまり、画像表示のために、画像アイコンのURLにリダイレクトされているのです。

このURLの中に、なにやらブックマーク数として採用できそうな文字列が入っているので、これを利用します。

リダイレクト先のURLだけを取得

PerlでHTTPの通信をするときによく使われる、LWP::UserAgentを使います。リクエスト用URLをGETすると、ヘッダに、転送先のURLが入って帰ってくるので、それを正規表現で数字部分だけ取り出し、数値として取り扱います。

下の例では、画像として取得できるサービス一般で使えるようにしてみました。

各ソーシャルブックマークサービス(SBM)のブックマーク数画像表示APIを調べた ::: creazy photograph [creazy.net]

にて、各SBMにて、画像として取得するときのリクエスト用URLと、リダイレクト先のURLが書いてありますので、そのようにやってみます。なお、@niftyクリップと、POOKMARKはこっちで調査して付け加えました。

(2008-07-06 13:06訂正:スクリプトの名前をsmb_img_count.plからsbm_img_count.plに変更。livedoor用画像ファイル取得アドレスがYahoo!用のものになっていたのを訂正。また、動作がわかりやすいように、リダイレクト先のURLを表示するようにし、実行例も変更しました。http://b.hatena.ne.jp/kits/20080706#bookmark-9198443より指摘いただきました。)

Filename: sbm_img_count.pl

use strict;
use warnings;
use LWP::UserAgent;
 
our $sbms = { 
       hatena =>
       {
         proxy   => 'http://b.hatena.ne.jp/entry/image/',
         regexp  => '/(\d+)\.png',
       },
       livedoor =>
       {
         proxy   => 'http://image.clip.livedoor.com/counter/',
         regexp  => '/(\d+)$',
       },
       yahoo =>
       {
         proxy   => 'http://num.bookmarks.yahoo.co.jp/image/large/',
         regexp  => '/(\d+)$',
       },
       buzzurl =>
       {
         proxy   => 'http://api.buzzurl.jp/api/counter/v1/image?url=',
         regexp  => '/(\d+)\.gif',
       },
       fc2 =>
       {
         proxy   => 'http://bookmark.fc2.com/image/users/',
         regexp  => '/(\d+)\.png',
       },
       nifty =>
       {
         proxy   => 'http://api.clip.nifty.com/api/v1/image/counter/',
         regexp  => '/(\d+)\.png',
       },
       pookmark =>
       {
         proxy   => 'http://pookmark.jp/count/',
         regexp  => '/(\d+)$',
       },
};
 
my $url = 'http://perl-mongers.org/';
print 0
    + get_sbm( 'hatena'  , $url )
    + get_sbm( 'livedoor', $url )
    + get_sbm( 'yahoo'   , $url )
    + get_sbm( 'buzzurl' , $url )
    + get_sbm( 'fc2'     , $url )
    + get_sbm( 'nifty'   , $url )
    + get_sbm( 'pookmark', $url );
print "\n";
 
exit;
 
 
sub get_sbm {
  my $service = shift;
  my $url     = shift;
  return get_sbm_imageicon( $service, $url )
}
 
# ブックマーク件数イメージ提供サービスから件数取得
sub get_sbm_imageicon {
  my $servce = shift;
  my $url    = shift;
  our $sbms;
  my $ua = LWP::UserAgent->new();
  $ua->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
  my $method = 'GET';
  #my $method = 'HEAD';
  my $req = HTTP::Request->new( $method,
                                $sbms->{$servce}->{proxy}.$url );
  my $res = $ua->simple_request($req);
  my $location = $res->header('location');
  print "$location\n";
  my $count = 0;
  if ( $location =~ m|$sbms->{$servce}->{regexp}| ) {
    $count = 0 + $1;
  }
  return $count;
}
実行例:
$ sbm_img_count.pl
http://b.hatena.ne.jp/images/users/normal/00134.png
http://image.clip.livedoor.com/img/users/small/00019.png
http://thumbnail.yimg.jp/number/large/7
http://cdn.buzzurl.jp/static/image/num/1.gif
http://bookmark.fc2.com/icons/00002.png
http://clip.nifty.com/images/counter/00000.png
http://pookmark.jp/images/count/3
147
$
便利に使うには、コマンドラインからの入力が@ARGVに入るので、コマンドラインからURLを入れて問い合わせるように改造する、CGI.pmモジュールを使って、URLのクエリーから問い合わせるように改造する、等々できるんじゃないかなと思います。


[続きを読む]以降では、画像でしかブックマーク数の情報を提供していないSBMで、SBM運営会社の代わりに、XML-RPCインターフェースのAPIを用意するというあさっての方向に突っ走ってみます。

~~~

FC2ブックマークでは、ブックマーク数が画像でしかとれないような感じですので、代わりにXML-RPCによるAPIを用意してみます。これまでの画像取得URLのリダイレクト先を見るので充分じゃないか、という気もしますが、まあこれはこれで応用できるような気もします故。

Filename: xmlrpc.cgi

#!/usr/bin/perl
use strict;
use warnings;
use XMLRPC::Transport::HTTP;
 
XMLRPC::Transport::HTTP::CGI
  -> dispatch_to('link')
  -> handle;
exit;
 
package link;
use strict;
use warnings;
use CGI;
use LWP::UserAgent;
use utf8;
binmode STDOUT => ':utf8';
 
 
sub getCount {
  shift if UNIVERSAL::isa($_[0] => __PACKAGE__);
  my $self;
  @$self = @_;

  our $sbms = { 
         fc2 =>
         {
           proxy   => 'http://bookmark.fc2.com/image/users/',
           regexp  => '/(\d+)\.png',
         },
  };
  my $res = {};
  foreach my $item ( @$self ) {
    $res->{$item} = get_sbm_imageicon('fc2', $item);
  }
  return $res;
};
 
 
# ブックマーク件数イメージ提供サービスから件数取得
sub get_sbm_imageicon {
  my $servce = shift;
  my $url    = shift;
  our $sbms;
  my $ua = LWP::UserAgent->new();
  $ua->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)');
  my $req = HTTP::Request->new( 'GET',
                                $sbms->{$servce}->{proxy}.$url );
  my $res = $ua->simple_request($req);
  my $location = $res->header('location');
  my $count = 0;
  if ( $location =~ m|$sbms->{$servce}->{regexp}| ) {
    $count = 0 + $1;
  }
  return $count;
}


1;
これを呼び出すクライアントは、こうです。

Filename: client.pl

#!/usr/bin/perl
use strict;
use warnings;
use XMLRPC::Lite;
 
our $EndPoint = 'http://example.com/path/to/xmlrpc.cgi';
 
my @urls = (
    'http://perl-mongers.org/',
    'http://instfont.info/',
    'http://pdf.printjapan.com/',
);
 
my $map = XMLRPC::Lite
     -> proxy($EndPoint)
     -> call ('link.getCount', @urls)
     -> result;
 
printf("%d\t%s\n", $map->{$_}, $_) for @urls;
実行例:

$ perl client.pl
2 http://perl-mongers.org/
0 http://instfont.info/
6 http://pdf.printjapan.com/
$

~~~

今回のエントリは、

M.C.P.C.: XMLRPC::LiteでHello, World! [blog.dtpwiki.jp]
M.C.P.C.: EDGE Now!のリンク件数を返す野良API(XML-RPC)プログラム [blog.dtpwiki.jp]

の再構成品です......


(2008-07-06 13:17追記)

http://b.hatena.ne.jp/kits/20080706#bookmark-9198443

[perl][http][sbm]smb_img_count.plで、livedoorのproxyがyahooのと同じになってます。/ Locationの取得ならHEADでもよさそうだけど、サービス側がGETしか対応してないところが幾つかあり。

とありましたので、proxyの記述については訂正しました。また、HEADでやった例を以下に示します。

$ perl sbm_img_count_head.pl 
http://b.hatena.ne.jp/images/users/normal/00134.png
http://image.clip.livedoor.com/img/users/small/00019.png
http://thumbnail.yimg.jp/number/large/7
http://cdn.buzzurl.jp/static/image/top/s.gif
http://bookmark.fc2.com/icons/00002.png
http://clip.nifty.com/images/counter/00000.png
http://pookmark.jp/images/count/3
146
$
どうやら、BuzzurlがHEADによるリクエストに対応してくれないようです。

No TrackBacks

TrackBack URL: http://perl-mongers.org/MT/mt-tb.cgi/67

Leave a comment

About this Entry

This page contains a single entry by CL published on July 5, 2008 12:59 PM.

デフォルト値のperlらしい指定法 was the previous entry in this blog.

strict プラグマについて is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

Creative Commons License
This blog is licensed under a Creative Commons License.
Powered by Movable Type 4.21-en