天然パーマです。

WebService-Simple-0.09 の使い方

シンプルに Web API を叩ける WebService::Simple の現在の最新版はヴァージョン 0.09 です。 ヴァージョン 0.03 からスーパーハカーによる修正が入ったこともあり、機能が(Simpleという名前を崩さない程度に)増えたり、多少インターフェースが変わったりしました。 そこで WebService::Simple 0.09 の使い方を POD より詳しめに解説します。 # shipit が便利だったので、調子に乗ってやたら使いまくったらヴァージョンがどんどんあがっちゃった><

最初に、インターフェースの変更点をあげます。大きく変わったのは一点のみです。 例えば、Lingr の API を扱う場合、base_url は http://www.lingr.com/ になりますが、 各メソッドの URL は 例えば http://www.lingr.com/api/session/create という風に、メソッドごとに変化します。つまり base_url に api/session/create みたいなパスを追加したいということです。 そのためには、 get メソッド の パラメータ にそのパスを記載するんですが、0.03 の時と引渡し方が変更になっています。 第1引数に extra_path を指定するようになりました。

 my $lingr = WebService::Simple->new(
    base_url => 'http://www.lingr.com/',
    param    => { api_key => "your_api_key", format => 'xml' }
);

my $response = $lingr->get( 'api/session/create', {} );

my $session = $response->parse_response->{session};

また、上記サンプルに記載されているように、get などで取得した WebService::Simple::Response オブジェクトをパースするには、parse_xml メソッドを今まで呼んででいましたが、parse_response メソッドを使うことを推奨しています(エイリアスを作っているので parse_xml でも動きます)。

あとは普通に使う分には今まで通りで問題ないです。 Flickr API を使ったキーワードによる検索結果を Dump するサンプルコードは以下のようになります。

 use strict;
use warnings;
use WebService::Simple;
use Data::Dumper;

my $flickr = WebService::Simple->new(
    base_url => "http://api.flickr.com/services/rest/",
    param    => { api_key => "your_api_key", }
);

my $response =
  $flickr->get( { method => "flickr.photos.search", text => "cat" } );
print Dumper $response->parse_response;

response のキャッシュも以前と同じ書き方でできます。

 use WebService::Simple;
use Cache::File;

my $cache = Cache::File->new(
    cache_root      => '/tmp/mycache',
    default_expires => '30 min',
);

my $flickr = WebService::Simple->new(
    base_url => "http://api.flickr.com/services/rest/",
    cache    => $cache,
    param    => { api_key => "your_api_key", }
);

次にこの WebService::Simple を継承したサブクラスを作って、もうちょっと楽に API を触れるという方法を紹介します。 例えば、Flickr API の flickr.test.echo 及び flickr.photos.search を呼び出す WebService::Simple::Flickr をこんな感じで作ります。

 package WebService::Simple::Flickr;

use base qw(WebService::Simple);
__PACKAGE__->config(
    base_url   => "http://api.flickr.com/services/rest/",
);

sub test_echo {
    my ($self,$str) = @_;
    return $self->get( { method => "flickr.test.echo", name => $str } );
}

sub photos_search {
    my ($self,$str) = @_;
    return $self->get( { method => "flickr.photos.search", text => $str } );
}

そしたら外部から、よりスッキリとしたコードで API をたたくことができます。

 use utf8;
use WebService::Simple::Flickr;
use Data::Dumper;

my $flickr =
  WebService::Simple::Flickr->new( param => { api_key => "your_api_key", } );

my $ref = $flickr->photos_search("富士山")->parse_response;
print Dumper $ref;

この API ごとにサブクラス化するという方法なんですが、Yappo さんが作った WebService::Simple::Cabinet を使う方法と、「ある API に特化したモジュールもしくはメソッドを作る」という点で似ています。WebService::Simple::Cabinet は YAML 形式などで API の定義をしますが、この場合は Perl モジュールを作っています。API を使うシチュエーションによってどちらか選ぶというのもいいと思います。

最後にパーサー、つまりAPI から返却されたコンテンツをパースするのに使うモジュールが選べるようになったという機能を紹介します。デフォルトでは XML::Simple でパースするようになっていますが、例えば XML::LibXML を使いたい場合は、WebService::Simple::Parser を継承して WebService::Simple::Parser::XML::LibXML モジュールを以下のように作成します( このモジュールはWebService::Simple に同封されています)。

 package WebService::Simple::Parser::XML::LibXML;
use strict;
use warnings;
use base qw(WebService::Simple::Parser);
use XML::LibXML;

__PACKAGE__->mk_accessors($_) for qw(libxml);

sub new
{
    my $class = shift;
    my $args  = shift || {};
    $args->{libxml} ||= XML::LibXML->new;
    $class->SUPER::new($args);
}

sub parse_response
{
    my $self = shift;
    $self->libxml->parse_string( $_[0]->content );
}

1;

それで利用するスクリプトからは、WebService::Simple のコンストラクタの引数 response_parser の値で使いたいパーサのモジュールを指定します。

 my $service = WebService::Simple->new(
    base_url        => "http://api.flickr.com/services/rest/",
    response_parser => 'XML::LibXML',
    params          => { api_key => "your_api_key" }
);

これで面白いのは、とりわけ XML で結果が返ってくる API 以外にも対応するところです。 例えば、JSON もしくは JSONP 形式で返却される API を扱うこともできます。 WebService::Simple::Parser::JSON はもう既に定義済みのものがあるので、以下のようなスクリプトを書くだけで、JSON もしくは JSONP を パースしてくれてデータを利用することができます。

 use strict;
use warnings;
use WebService::Simple;
use Data::Dumper;

my $flickr = WebService::Simple->new(
    base_url        => "http://api.flickr.com/services/rest/",
    response_parser => 'JSON',
    params          => { api_key => "your_api_key", format => "json" }
);

my $response =
  $flickr->get( { method => "flickr.photos.search", text => "cat" } );
print Dumper $response->parse_response;

あとは POST にも対応したので、使いたい場合は post メソッドを get と同じ引数形式で呼び出せばおkだと思います。

dmaki(lestrrat)さん、tokuhirom に(まるごと)書き換えてもらった&Yappo さんが WebService::Simple::Cabinet を作ったおかげで、面白いモジュールになった気がします。感謝です。

CPAN に最新版があがっているので、もしよろしければご利用ください。