ぜんぜんエロくなかった、とかいう感想が散見されたYusukebeさんのYAPC::Asia2008 LT。
そこでいたってまじめに紹介された WebService::Simple を使って、Amazon A2S(旧ECS)を使ってみたメモです。
WebService::Simpleモジュール
WebService::Simple - Simple Interface To Web Services APIs
WebService::Simple は各種 Web API を利用するのに便利なモジュール。
GET, POST するリクエストの組み立てからレスポンスをハッシュに展開するまで、名前の通り Simpleなインターフェースで実現してくれる。Web APIを利用するためのモジュールはWeb APIの数だけ存在するが、WebService::Simple はそれひとつで様々なAPIに対応できる設計となっており、その存在意義もシンプルでわかりやすい。
というわけで、Web API の代表格といえば Amazon だろうということで、Net::Amazonをスルーして Webservice::Simple でトライ。
Amazon A2S で ItemLookup
まずは、個別商品の情報を取得してみる。
use strict;
use warnings;
use WebService::Simple;
#use Data::Dumper;
my $amazon = WebService::Simple->new(
base_url => "http://webservices.amazon.co.jp/onca/xml",
param => {
AssociateTag => 'wwwbayashinet-22',
SubscriptionId => '04A944EPEX0W030SF302',
Service => 'AWSECommerceService',
locale => 'jp',
ContentType => 'text/xml',
Version => '2007-10-29',
}
);
my $response = $amazon->get(
{
Operation => 'ItemLookup',
ItemId => 'B0012OR6MS',
ResponseGroup => 'ItemAttributes',
}
);
#print Dumper $response->parse_response;
print $response->parse_response->{Items}->{Item}->{DetailPageURL};
結果、壮絶アクメ。
http://www.amazon.co.jp/gp/redirect.html%3FASIN=B0012OR6MS%26tag=wwwbayashinet-22%26lcode=xm2%26cID=2025%26ccmID=165953%26location=/o/ASIN/B0012OR6MS%253FSubscriptionId=04A944EPEX0W030SF302
蒼井そらたん、はぁはぁw
ええと、使い方は、param で基本的なパラメータを設定しておいて、get でさらにパラメータを指定してリクエストする。レスポンスは XML::Simple で Parse されてハッシュが返ってくるって感じ。
実に簡単。
Amazon A2S でキーワード検索
つづいて、DVD をキーワード検索してみます。
use strict;
use warnings;
use WebService::Simple;
#use Data::Dumper;
my $amazon = WebService::Simple->new(
base_url => "http://webservices.amazon.co.jp/onca/xml",
param => {
AssociateTag => 'wwwbayashinet-22',
SubscriptionId => '04A944EPEX0W030SF302',
Service => 'AWSECommerceService',
locale => 'jp',
ContentType => 'text/xml',
Version => '2007-10-29',
}
);
my $response2 = $amazon->get(
{
Operation => 'ItemSearch',
Keywords => '%E5%AE%87%E5%AE%99%E4%BC%81%E7%94%BB',
SearchIndex => 'DVD',
ResponseGroup => 'Medium',
Sort => 'salesrank',
ItemPage => 1,
}
);
#print Dumper $response2->parse_response;
foreach my $item (@{$response2->parse_response->{Items}->{Item}}){
print $item->{ASIN}."\n" if($item->{ASIN});
print $item->{LargeImage}->{URL}."\n" if($item->{LargeImage}->{URL});
}
おお、宇宙企画。はぁはぁww
とまあ無駄にエロいリクエストが簡単に実現。WebService::Simple イイ!
実はこれまで自前ライブラリでREST URLの構築からリクエストして正規表現でパースするという泥臭いことをやっていたんですが、それは Amazon専用だしメンテも大変なので、今後は WebService::Simple 使うかな。
パーサーの切り替え
さて、そんな WebService::Simple なんですが、実は Web API からのレスポンスを Parse するモジュールをいろいろ切り替えられるらしいので、それもやってみた。
デフォで JSON とか XML::LibXML が用意されているが、ここはせっかくなので YAPC::Asia2008、そして同じ “ゆうすけ” つながりで川崎有亮さんの XML::TreePP モジュールを利用できるようにしてみた。
XML::TreePP は 日本語でドキュメントがあるし、PurePerl(.pmをコピーすれば使える)で(XML::Simpleより)早いと聞いたので。
というわけで、WebService::Simple::Parser::XML::TreePP を以下のようにこさえまして、、、
[WebService::Simple::Parser::XML::TreePP]
use strict;
use warnings;
use base qw(WebService::Simple::Parser);
use XML::TreePP;
sub new
{
my $class = shift;
my %args = @_;
my $tpp = delete $args{tpp} || XML::TreePP->new();
my $self = $class->SUPER::new(%args);
$self->{tpp} = $tpp;
return $self;
}
sub parse_response
{
my $self = shift;
my $content =$_[0]->content;
$self->{tpp}->parse($content);
}
1;
先ほどのコードをちょこちょこ改変(response_parser を指定とか)。
use strict;
use warnings;
use WebService::Simple;
#use Data::Dumper;
my $amazon = WebService::Simple->new(
base_url => "http://webservices.amazon.co.jp/onca/xml",
response_parser => 'XML::TreePP',
param => {
AssociateTag => 'wwwbayashinet-22',
SubscriptionId => '04A944EPEX0W030SF302',
Service => 'AWSECommerceService',
locale => 'jp',
ContentType => 'text/xml',
Version => '2007-10-29',
}
);
my $response = $amazon->get(
{
Operation => 'ItemSearch',
Keywords => '%E3%83%9E%E3%82%AD%E3%82%B7%E3%83%B3%E3%82%B0',
SearchIndex => 'DVD',
ResponseGroup => 'Medium',
Sort => 'salesrank',
ItemPage => 1,
}
);
#print Dumper $response->parse_response;
foreach my $item (@{$response->parse_response->{ItemSearchResponse}->{Items}->{Item}}){
print $item->{ASIN}."\n" if($item->{ASIN});
print $item->{LargeImage}->{URL}."\n" if($item->{LargeImage}->{URL});
}
おお、マキシング。はぁはぁwww
というわけで、別パーサでの処理もできたっぽい。
が、オイラ実はクラスの継承とかよくわかってなくて、[WebService::Simple::Parser::XML::TreePP] はこれで正しいのかまったく分かりません。
見よう見まねで作ってますので、変なところ、教えてください!(>。<)!
ふう、これから図書館にオライリー本借りに行く。
参考
