2003 年 7 月 21 日 (月・海の日) 自宅

さて、Amazon Web サービスの話題、さらに続きます。 とりあえず、「¥」マークのバグの件で、 SOAP 経由でのアクセスはとりあえず放置して、XML/HTTP 経由でのアクセスを試みてみます。 とはいっても、discussion board の様子をみて、 いろいろな SOAP 経由のトラブルが起っているところをみると、 XML/HTTP 経由でアクセスした方がいろいろ今回のバグのようなものの対処も、 小回りが効くように思うため、無理に SOAP を使うこともないかな、 という気もしています (自分で SOAP サーバ側を直せるわけでもないし)。

てなことで、Perl を使っていく上で、何のクラスを用いるかはいろいろ重要ですが、 とりあえず HTTP 経由のアクセスには Net::HTTP::NB (Net::HTTP ノンブロッキング版) を用いることにしましょう。 これは、相手のサーバが落ちている可能性も考えたときに、 容易にタイムアウトさせるにはノンブロッキングの方が何かと便利かな、 ということです。ということで、基本型としてはこんな感じかな? (以下の解説では、今まで通りアソシエイト ID を MYTAG、 デベロッパートークンを MYDEVT と置きます)

このスクリプトは UTF-8 でセーブします。 また、Perl のバージョンは Unicode サポートの充実した Perl 5.8.0、 OS は FreeBSD 4.8-RELEASE を用いています (FreeBSD 4.x で Perl 5.8.0 を標準の Perl として用いる方法については、 以前のページを参照してください)。

#!/usr/local/bin/perl
use strict;
use Net::HTTP::NB;
use URI::Escape;
use IO::Select;

my $keyword = "dogs";      # Search keyword
my $type = 'lite';
my $category = 'books-jp';
my $esckeyword = uri_escape($keyword);
my $tag = 'MYTAG';         # Fill your "associate ID"
my $devt = 'MYDEVT';       # Fill your "developer token"
my $host = 'xml.amazon.com';
my $resource = "/onca/xml3?t=$tag&dev-t=$devt&KeywordSearch=$esckeyword&"
               . "mode=$category&type=$type&page=1&f=xml&locale=jp";

my $s = Net::HTTP::NB->new(Host => $host) || die $@;
$s->write_request(GET => $resource);

my $sel = IO::Select->new($s);

READ_HEADER: {
  die "Header timeout" unless $sel->can_read(10);
  my($code, $mess, %h) = $s->read_response_headers;
  redo READ_HEADER unless $code;
}

my $xmlresp = '';

while (1) {
  die "Body timeout" unless $sel->can_read(10);
  my $buf;
  my $n = $s->read_entity_body($buf, 1024);
  last unless $n;
  $xmlresp .= $buf;
}

my @xmlresp = split /\n/, $xmlresp;

my $x = 0;
my $r = '';
foreach my $i (@xmlresp) {
  $x++;

  # Hack: Replace invalid UTF-8 encoded Japanese Yen Symbol with 
  # another representation (0xa5 → "¥").

  $i =~ s!<(\w+)Price>(\xA5)(.*)</(\w+)Price>!<$1Price>¥$3</$4Price>!;
  $r .= "$i\n";
}

print $r;

注意すべき点としては、先日の「¥マークバグ」ですが、 結局次のような正規表現でことが足りているようです ($3 の前の「¥」は全角で入力する) この行のために UTF-8 でセーブしておく必要がある)。

$i =~ s!<(\w+)Price>(\xA5)(.*)</(\w+)Price>!<$1Price>¥$3</$4Price>!;

このプログラムを実行すると、次のような出力が得られます (改行のみ、多少整形しています)。

<?xml version="1.0" encoding="UTF-8"?>
<ProductInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="http://xml.amazon.com/schemas3/dev-lite.xsd">

      <Request>
<Args>
   <Arg value="jp" name="locale">
   </Arg>
   <Arg value="1" name="page">
   </Arg>
   <Arg value="dogs" name="KeywordSearch">
   </Arg>
   <Arg value="MYDEVT" name="dev-t">
   </Arg>
   <Arg value="MYTAG" name="t">
   </Arg>
   <Arg value="xml" name="f">
   </Arg>
   <Arg value="books-jp" name="mode">
   </Arg>
   <Arg value="lite" name="type">
   </Arg>
</Args>
      </Request>
   <TotalResults>27</TotalResults>
   <TotalPages>3</TotalPages>
   <Details url="http://www.amazon.co.jp/exec/obidos/ASIN/4088762525/MYTAG?dev-t=MYDEVT">
      <Asin>4088762525</Asin>
      <ProductName>DOGS</ProductName>
      <Catalog>Book</Catalog>
      <Authors>
         <Author>三輪 士郎</Author>
      </Authors>
      <Manufacturer>集英社</Manufacturer>
      <ImageUrlSmall>http://images-jp.amazon.com/images/P/4088762525.09.THUMBZZZ.jpg</ImageUrlSmall>
      <ImageUrlMedium>http://images-jp.amazon.com/images/P/4088762525.09.MZZZZZZZ.jpg</ImageUrlMedium>
      <ImageUrlLarge>http://images-jp.amazon.com/images/P/4088762525.09.LZZZZZZZ.jpg</ImageUrlLarge>
      <ListPrice>¥ 590</ListPrice>
      <OurPrice>¥ 590</OurPrice>
      <UsedPrice>¥ 315</UsedPrice>
   </Details>
   ...(略)...
</ProductInfo>

出力が well-formed な XML かを確認してみましょう。 Expat (ports/textproc/expat2) 付属の xmlwf は、何もエラーを発生しません。 きちんと well-formed になっているようです。

% ./xml1.pl > test.xml
% xmlwf test.xml
% 

しかし、キーワードを日本語にしてみると…。 あららら? 「There are no exact matches for the search.」と、怒られてしまいました。

<?xml version="1.0" encoding="UTF-8"?>
<ProductInfo>
<Request>
<Args>
  <Arg name="locale" value = "jp"/>
  <Arg name="page" value = "1"/>
  <Arg name="KeywordSearch" value = "文字化けしたキーワード"/>
  <Arg name="dev-t" value = "MYDEVT"/>
  <Arg name="t" value = "MYTAG"/>
  <Arg name="f" value = "xml"/>
  <Arg name="mode" value = "books-jp"/>
  <Arg name="type" value = "lite"/>
  </Args>
</Request>
<ErrorMsg>There are no exact matches for the search.</ErrorMsg>
</ProductInfo>

どうも検索キーワードに日本語を入れると、 化けて渡されているようです。 しかし、GET する URI をチェックすると、 UTF-8 で正確にキーワードが渡されているのは確かなようです。 さて、この問題やいかに? 解決は次回に続く。


この話題、戻る← 2003/07/21 『AWS: XEmacs 21.4.x で UTF-8 を使う』

この話題、続く→ 2003/07/22 『AWS: 日本語キーワード検索文字化け』


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