2008年05月27日(火) 12:34

WebService::SimpleでAmazon Web API

ぜんぜんエロくなかった、とかいう感想が散見された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

まずは、個別商品の情報を取得してみる。

#!/usr/bin/perl


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 をキーワード検索してみます。

#!/usr/bin/perl


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]

package 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 を指定とか)。

#!/usr/bin/perl


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] はこれで正しいのかまったく分かりません。
見よう見まねで作ってますので、変なところ、教えてください!(>。<)!


ふう、これから図書館にオライリー本借りに行く。


参考

このエントリーに最初のコメントを書いてみませんか?

名前  クッキーに保存 
エントリーナビ
WebService::SimpleでAmazon Web API」は、
Perl カテゴリーの記事です。


関連エントリー
Amazon A2S(ECS)のカテゴリCheat Sheet
Amazon ECS3.0をECS4.0に移行する方法
PerlモジュールAtom::XMLのインストール
PerlのバージョンアップとCPAN豆知識
PerlでOpenID - Net::OpenID::Consumerインストール

トラックバック
このエントリーへトラックバックするURL (言及リンクのないトラックバックは無効です)