2003 年 7 月 27 日 (日) 自宅

さて、数日ぶりのAmazon Web サービスの話題です。 7 月 15 日に書いた、 AWS が返す XML 中の「¥」マークのコードが、 UTF-8 的に不正なエンコーディングがされているために、 expat などの XML パーサが well-formed な XML でないと訴えて異常終了してしまう問題が解決されました (Amazon からのアナウンス)。素晴らしい。

ということで、このバグへのワークアラウンドが不可能であるために、 SOAP を用いることをあきらめて XML/HTTP でアクセスしていたのですが、 もはやその必要はないことになりました。 SOAP を使ってみましょう。

ということで、 AWS や Perl, SOAP::Lite のマニュアル類や各種ドキュメントなどを見ながら、 必死に Perl 5.8.0 でこんな感じでテストプログラムを書いてみました (何せ SOAP 使うのは初めてなもので…。 でも試行錯誤のわりには、結構シンプルに仕上がっている。 SOAP って素敵かも)。

データがどんな形で返されるか良くわからないので、 Data::Dumper でダンプしてみることにします。

#!/usr/local/bin/perl

# Amazon Web サービス SOAP テストスクリプト
# Encoding: UTF-8 (unix)
# Don't save this script as Shift-JIS or EUC-jp!!
#
# Copyright (c) 2003 by 
#    細川達己 (Tatsumi Hosokawa) <hosokawa@FromTo.Cc>,
#    All rights reserved.

use SOAP::Lite;
#use SOAP::Lite +trace => 'debug';   # for debugging
use Data::Dumper;
use strict;

my $keyword = '広末涼子';
my $category = 'books-jp';
my $result = amazonSoapQuery($keyword, 'lite', $category);

print Dumper($result);


sub amazonSoapQuery($$$) {
  my ($keyword, $type, $category) = @_;
  my $tag = 'MYTAG';                 # Fill your "associate ID"
  my $devt = 'MYDEVT';               # Fill your "developer token"

  my $wsdl = 'http://soap.amazon.com/schemas3/AmazonWebServices.wsdl';
  my %sort_keys =
    (
     'books-jp' => '+daterank',
     'music-jp' => '-orig-rel-date',
     'classical-jp' => '-orig-rel-date',
     'vhs-jp' => '-orig-rel-date',
     'dvd-jp' => '-orig-rel-date',
     'software-jp' => '-release-date',
     'videogames-jp' => '-release-date',
    );
  my $sort = $sort_keys{$category} ? $sort_keys{$category}:'';

  my $s = SOAP::Lite->service($wsdl);

  my $res = $s -> KeywordSearchRequest(
      SOAP::Data->name('KeywordSearchRequest')
                ->type('KeywordRequest')
                ->value(\SOAP::Data->value(
            SOAP::Data->name('keyword' => $keyword),
            SOAP::Data->name('page'    => '1'),
	    SOAP::Data->name('mode'    => $category),
	    SOAP::Data->name('tag'     => $tag),
	    SOAP::Data->name('type'    => $type),
	    SOAP::Data->name('devtag'  => $devt),
	    SOAP::Data->name('sort'    => $sort),
	    SOAP::Data->name('locale'  => 'jp'),
	    SOAP::Data->name('format'  => 'xml'),
	    SOAP::Data->name('version' => '1.0'),
          )
      )
   );

  return $res;
}

さて、これ、どんな結果を返すかな?

% ./soaptest.pl
$VAR1 = bless( {
         'Details' => [
                bless( {
                        'OurPrice' => "\x{a5} 1,900",
                        'ImageUrlLarge' => 'http://images-jp.amazon.com/images/P/4757714750.09.LZZZZZZZ.jpg',
                        'Availability' => "\x{901a}\x{5e38}2\x{65e5}\x{9593}\x{4ee5}\x{5185}\x{306b}\x{767a}\x{9001}\x{3057}
                        \x{307e}\x{3059}\x{3002}",
                        'Catalog' => 'Book',
                        'Asin' => '4757714750',
                        'ListPrice' => "\x{a5} 1,900",
                        'Authors' => [
                                       "\x{4e38}\x{8c37} \x{5609}\x{9577}"
                                      ],
                        'ImageUrlMedium' => 'http://images-jp.amazon.com/images/P/4757714750.09.MZZZZZZZ.jpg',
                        'Url' => 'http://www.amazon.co.jp/exec/obidos/ASIN/4757714750/MYTAG?dev-t=MYDEVT',
                        'Manufacturer' => "\x{30a8}\x{30f3}\x{30bf}\x{30fc}\x{30d6}\x{30ec}\x{30a4}\x{30f3}",
                        'ProductName' => "\x{5e83}\x{672b}\x{6dbc}\x{5b50} New York RH Avenue 2003",
                        'ImageUrlSmall' => 'http://images-jp.amazon.com/images/P/4757714750.09.THUMBZZZ.jpg'
                        }, 'Details' ),
                 bless( {
                        'OurPrice' => "\x{a5} 2,000",
                        'ImageUrlLarge' => 'http://images-jp.amazon.com/images/P/4894950316.09.LZZZZZZZ.jpg',
                        'Availability' => "\x{3053}\x{306e}\x{30da}\x{30fc}\x{30b8}\x{306f}\x{3001}\x{5728}\x{5eab}\x{72b6}
                        \x{6cc1}\x{306b}\x{5fdc}\x{3058}\x{3066}\x{5e38}\x{306b}\x{66f4}\x{65b0}\x{3055}\x{308c}\x{307e}
                        \x{3059}\x{306e}\x{3067}\x{3001}\x{8cfc}\x{5165}\x{3092}\x{691c}\x{8a0e}\x{3057}\x{3066}\x{3044}
                        \x{308b}\x{5834}\x{5408}\x{306f}\x{3001}\x{5b9a}\x{671f}\x{7684}\x{306b}\x{3054}\x{89a7}\x{304f}
                        \x{3060}\x{3055}\x{3044}\x{3002}",
                        'Catalog' => 'Book',
                        'Asin' => '4894950316',
                        'ListPrice' => "\x{a5} 2,000",
                        'ImageUrlMedium' => 'http://images-jp.amazon.com/images/P/4894950316.09.MZZZZZZZ.jpg',
                        'Url' => 'http://www.amazon.co.jp/exec/obidos/ASIN/4894950316/MYTAG?dev-t=MYDEVT',
                        'Manufacturer' => "\x{30cf}\x{30b4}\x{30ed}\x{30e2}",
                        'ProductName' => "\x{5e83}\x{672b}\x{6dbc}\x{5b50}\x{30ab}\x{30ec}\x{30f3}\x{30c0}\x{30fc} 2003",
                       'ImageUrlSmall' => 'http://images-jp.amazon.com/images/P/4894950316.09.THUMBZZZ.jpg'
                        }, 'Details' ),
.... (同様の Details が並ぶ) ....
                 ],
        'TotalResults' => '20',
        'TotalPages' => '2'
      }, 'ProductInfo' );

わお! いい感じ。 ということは、簡単にアクセスできそうだな。 ちょっと最初の部分を改造してみよう。

ちなみに、「binmode STDOUT, ':utf8'」を入れないと、 漢字の表示時に「Wide character in print at ./soaptest.pl line 30.」 というエラーが出てしまう (解決法は FAQ のようで、Google で知りました… man perluniintro にも書いてあるけどね)。 なるほど、 しかしいつの間に (一生縁はないと思っていた) binmode にそんな機能が (^^;。 Perl らしいと言えば Perl らしいが…。

use SOAP::Lite;
#use SOAP::Lite +trace => 'debug';   # for debugging
use strict;

binmode STDOUT, ':utf8';

my $keyword = '広末涼子';
my $category = 'books-jp';
my $result = amazonSoapQuery($keyword, 'lite', $category);

my $totalresults = $result->{TotalResults};
my $details = $result->{Details};
my $num = $#$details + 1;

print "* $totalresults results found (this page contains $num results) *\n";

foreach my $detail (@$details) {
  my $title = $detail->{ProductName};
  my $url = $detail->{Url};
  print "$title ($url)\n";
}

さて、じゃあ実行してみるかい! ……いいねぇ、これ。やっぱりプログラムの見易さと、 見通しの良さは XML/HTTP の時とは全然違う。 素晴らしい。やっぱり SOAP 使おうっと。

% ./soaptest.pl | perl -Mencoding=utf8,STDOUT,euc-jp -pe1
* 20 results found (this page contains 10 results) *
広末涼子 New York RH Avenue 2003 (http://www.amazon.co.jp/exec/obidos/ASIN/4757714750/MYTAG?dev-t=MYDEVT)
広末涼子カレンダー 2003 (http://www.amazon.co.jp/exec/obidos/ASIN/4894950316/MYTAG?dev-t=MYDEVT)
メラニー・ジェーン (http://www.amazon.co.jp/exec/obidos/ASIN/4789716937/MYTAG?dev-t=MYDEVT)
Happy20thBirthday広末涼子写真集―ヒロスエ、ハタチ (http://www.amazon.co.jp/exec/obidos/ASIN/4838782829/MYTAG?dev-t=MYDEVT)
広末 (http://www.amazon.co.jp/exec/obidos/ASIN/4048835955/MYTAG?dev-t=MYDEVT)
HIATARI RYOーKOー―広末涼子トークエッセイ (http://www.amazon.co.jp/exec/obidos/ASIN/4847013123/MYTAG?dev-t=MYDEVT)
広末涼子CFスペシャル (http://www.amazon.co.jp/exec/obidos/ASIN/4575471747/MYTAG?dev-t=MYDEVT)
広末涼子 全曲集 (http://www.amazon.co.jp/exec/obidos/ASIN/4810834719/MYTAG?dev-t=MYDEVT)
relax―広末涼子写真集 (http://www.amazon.co.jp/exec/obidos/ASIN/4847025253/MYTAG?dev-t=MYDEVT)
ポップスミニal 広末涼子 MajiでKoiする5秒前 (http://www.amazon.co.jp/exec/obidos/ASIN/4883640191/MYTAG?dev-t=MYDEVT)

でも、若干レスポンスが XML/HTTP より遅い気がするのは SOAP::Lite の初期化に WSDL 使ってしまっているせいかな? (まあ、たとえ仮にそうだとしても、 一回の実行で何度も SOAP アクセスするなら気にならなくなるはずだが) 今度いろいろ試してみよう。

ってなことで、たぶんまだこのネタ続く。


この話題、戻る← 2003/07/23 『AWS: 微妙に改造』


このサイトへのリンクには何ら許可は必要ありません。 ただし、無断で写真をダウンロードして他の場所に掲載したり、 画像加工の素材として利用するなど、再配布に当たる行為はしないようにしてください。 また、このサイトへのリンクであることを明示すること無しに <img src="..."> などで他のページの内部に画像ファイルを取り込むことも、 ご遠慮下さい。