さて、Amazon Web サービスの件の続き (前回はこちら) です。
前回でやっと、 XML/HTTP 経由で日本語のキーワード検索をかけられるようになったわけですが、 ちょっと気になるのは順番です。 マニュアルを読むと順序は optional パラメータになっていて、 標準だともっとも基本的な「売れてる順」になるのかな?
どうやら、ソートに関しては「sort=...」という記述を、 URI のリソースパスの部分に入れればいいみたいなんだけど、 その部分はドキュメンテーションがイマイチ。 Amazon.co.jp のページのソースを見て想像すると、 「sort=+daterank」と入れれば、 「発売日の新しい順」でのソートができるようだ。 ということで、ちょっと改造してみよう。
# Hack: Following parameter is needed to pass Japanese UTF-8 encoded
# characters to AWS. I don't know why it is needed, and it has no
# effects on English queries (as far as I experienced).
# See, http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=2704.1&ctx=0
my $jphack = '&__mk_ja_JP=' . uri_escape('カタカナ');
my $resource = "/onca/xml3?t=$tag&dev-t=$devt&KeywordSearch=$esckeyword&"
. "mode=$category&type=$type&page=1&f=xml&locale=jp$jphack";
my $sort = '+daterank'; # Hack: Following parameter is needed to pass Japanese UTF-8 encoded # characters to AWS. I don't know why it is needed, and it has no # effects on English queries (as far as I experienced). # See, http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=2704.1&ctx=0 my $jphack = '&__mk_ja_JP=' . uri_escape('カタカナ'); my $xsort = ''; if ($sort) { $xsort = '&sort=' . uri_escape($sort); } my $resource = "/onca/xml3?t=$tag&dev-t=$devt&KeywordSearch=$esckeyword&" . "mode=$category&type=$type&page=1$xsort&f=xml&locale=jp" . "$jphack";
さて、これが「広末涼子」in books-jp の検索にどう影響を与えるだろうか? 結果はこうだ。
実際に Amazon の和書のページから同様の検索を行うと、 この検索結果が正しいことがわかる。 とはいっても、広末涼子では果たしてデータが正しいのか、 私の知識範囲では判断できないので (笑)、 「椎名林檎」 in music-jp で検索してみよう。 検索キーワードの部分をこう変更してみる。
my $keyword = "椎名林檎"; # Search keyword my $type = 'lite'; my $category = 'music-jp';
さて、結果はいかに?
おい…、何の順番かわからないよ…。一頻り悩んでいろいろ試すと、 books-jp の範囲では問題なく発売日順の検索ができることがわかった。 要するに、ソート順はカテゴリ依存の部分があるようだ。 マニュアルをよく読むと、確かにそれらしき記述はあるのだが、 不明な個所がたくさんあるので、Amazon.co.jp のページのソースを読むことで、 ある程度判明。結果はこんな感じ。結構メチャクチャ。
| Amazon.co.jp カテゴリ名 | 発売日ソートキーワード |
|---|---|
| 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 |
よし、それではさっきの「椎名林檎」 in music-jp の検索をもう一度やってみよう。 ソートのキーワードを -orig-rel-date に書き換えるぞ。
my $sort = '-orig-rel-date';
結果はどうだ? 今度は OK みたいだな! 『茎 (STEM)』が 2 つ入っているのは限定版と通常版だね。素晴らしい。
てなことで、この部分はもう少し汎用的に、こんな風に変えてみるかな?
# Hack: Following parameter is needed to pass Japanese UTF-8 encoded
# characters to AWS. I don't know why it is needed, and it has no
# effects on English queries (as far as I experienced).
# See, http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=2704.1&ctx=0
my $jphack = '&__mk_ja_JP=' . uri_escape('カタカナ');
# "sort" key for newer products depends on the categories...
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 $xsort = '';
if ($sort_keys{$category}) {
$xsort = '&sort=' . uri_escape($sort_keys{$category});
}
my $resource = "/onca/xml3?t=$tag&dev-t=$devt&KeywordSearch=$esckeyword&"
. "mode=$category&type=$type&page=1$xsort&f=xml&locale=jp"
. "$jphack";
うーむ、なかなか難儀だな…。 とりあえず、もう少し体裁を直して、 本日までの作業状態をまとめてみよう。 さしあたって、こんな感じだ。 関数「amazonXmlHttpQuery()」にまとめてみた。
#!/usr/local/bin/perl
# Amazon Web サービス XML/HTTP テストスクリプト
# 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 strict;
my $keyword = '広末涼子';
my $type = 'lite';
my $category = 'books-jp';
print amazonXmlHttpQuery($keyword, $type, $category);
use Net::HTTP::NB;
use URI::Escape;
use IO::Select;
# Database query to Amazon.co.jp database via XML/HTTP
# (newer products in keyword search results)
sub amazonXmlHttpQuery($$$) {
my ($keyword, $type, $category) = @_;
my $esckeyword = uri_escape($keyword);
my $tag = 'MYTAG'; # Fill your "associate ID"
my $devt = 'MYDEVT'; # Fill your "developer token"
my $host = 'xml.amazon.com';
# Hack: Following parameter is needed to pass Japanese UTF-8 encoded
# characters to AWS. I don't know why it is needed, and it has no
# effects on English queries (as far as I experienced).
# See, http://forums.prospero.com/n/mb/message.asp?webtag=am-assocdevxml&msg=2704.1&ctx=0
my $jphack = '&__mk_ja_JP=' . uri_escape('カタカナ');
# "sort" key for newer products depends on the categories...
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 $xsort = '';
if ($sort_keys{$category}) {
$xsort = "&sort=" . uri_escape($sort_keys{$category});
}
my $resource = "/onca/xml3?t=$tag&dev-t=$devt&KeywordSearch=$esckeyword&"
."mode=$category&type=$type&page=1$xsort&f=xml&locale=jp"
."$jphack";
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";
}
return $r;
}
たぶん、まだ続くよ (このページって、期せずして「Google ホイホイ」化している? うちのページは Google ランク高いみたいなので、 あまりうかつなこと書けないんだが ^^;)。
この話題、戻る← 2003/07/22 『AWS: 日本語キーワード検索文字化け』
この話題、続く→ 2003/07/23 『AWS: 微妙に改造』