Amazon Product Advertising API へのリクエストURIのフォーマットが変更されました。
リクエストURIに署名の付加が必須となり、リクエスト側が署名を生成しなくてはいけません。
ex. http://xml-jp.amznxslt.com/onca/xml?…&Signature=*****
詳細はオフィシャルサイトに載っていますが、要は下記の2つの文字列を HMAC SHA256 という方式で符号化したものが署名です。
・”URIのクエリ(タイムスタンプを含む)”
・”アマゾンから発行される秘密キー”
ところが、これまでリクエストURI生成に使っていたホスティングサーバのPythonはバージョンが古く(早くバージョンアップしてほしい…)、 HMAC SHA256 符号化ができません。
Python 2.4 以前は標準で SHA256 を算出するモジュールが入っていないためです。
※Python 2.5 以降であれば hashlib モジュールが使えます。
仕方がないので、署名付きリクエストURIを生成するスクリプトはPerlで書き、それをPythonから実行し、URIを読み込むことにしました。
以下、PerlのURI生成スクリプト。
AmazonSignedRequestGenerator.pl:
#!/usr/bin/perl use strict; use warnings; use URI::Escape; use Digest::SHA qw(hmac_sha256_base64); #ISBNを受け取り、Amazon APIのリクエストURIを返す関数 sub GetSignedURIByISBN{ # Amazon Access Key ID my $accessKeyID = "Your AWS Access Key ID"; # Amazonから割り振られる秘密キー my $secretKey = "Your Secret Key"; # リクエスト先のホスト名 my $host = "xml-jp.amznxslt.com"; my $path = "/onca/xml"; # リクエストキーとパラメータを関連付けた連想配列を用意する my %reqParam = ( "Service" => "AWSECommerceService", "AWSAccessKeyId" => $accessKeyID, "Version" => "2007-10-29", "Operation" => "ItemLookup", "IdType" => "ISBN", "SearchIndex" => "Books", "ItemId" => $_[0], # 引数で受け取ったISBNが入る "ResponseGroup" => "Medium", "ContentType" => "text/xml", "Timestamp" => &GetTimeStamp() ); # リクエストキーとパラメータを結合したクエリを作成 my @queryList = (); foreach my $reqKey(sort(keys%reqParam)){ #アルファベット順にソート push(@queryList, URI::Escape::uri_escape($reqKey, "^A-Za-z0-9\-_.~")."=". URI::Escape::uri_escape($reqParam{$reqKey}, "^A-Za-z0-9\-_.~")); } my $query = join("&", @queryList); # 署名を作成 my $signature = hmac_sha256_base64("GET\n$host\n$path\n$query", $secretKey); $signature .= "=" while length($signature) % 4; # 署名の長さが4の倍数になるまで"="を付加 $signature = URI::Escape::uri_escape($signature, "^A-Za-z0-9\-_.~"); # リクエストURIを返す return "http://$host$path?$query&Signature=$signature"; } # 呼ばれた時刻のタイムスタンプを返す関数 sub GetTimeStamp { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = gmtime(); return sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", $year+1900, $mon+1, $mday, $hour, $min, $sec); } # コマンド引数からISBNを受け取り、リクエストURIを表示 print &GetSignedURIByISBN($ARGV[0]);
PerlのURI生成スクリプト実行例。
引数にISBNを指定すると、その書籍情報XMLのリクエストURIを出力する。
$ perl AmazonSignedRequestGenerator.pl 4091400019 http://xml-jp.amznxslt.com/onca/xml?AWSAccessKeyId="Your AWS Access Key ID"&ContentType=text%2Fxml&IdType=ISBN&ItemId=4091400019&Operation=ItemLookup&ResponseGroup=Medium&SearchIndex=Books&Service=AWSECommerceService&Timestamp=2009-10-02T04%3A34%3A01Z&Version=2007-10-29&Signature=V3SNWy7FwOUQJ%2F9TiNJLK55UMdNEWuw5qmqd%2FRsY6Y4%3D
Perlスクリプトを実行し、取得したURIで書籍情報XMLを取得するPythonスクリプト。
RequestTest.py:
#/usr/bin/python # -*- coding: utf-8 -*- import commands, urllib isbn = '4091400019' #PerlのURI生成スクリプトを実行して標準入力からURIを取得 requestURI = commands.getoutput('perl ./AmazonSignedRequestGenerator.pl %s' % (isbn)) #書籍情報XMLを取得 bookDataXML = urllib.urlopen(requestURI).read() #取得したXMLを出力 print bookDataXML
こんな感じで、PythonからPerlを呼び出して書籍情報を取得できます。
RequestTest.pyの8行目でAmazonSignedRequestGenerator.plを呼び出しているところがポイントです。
※これらのソースはサンプルなので、使用する場合は適宜エラー処理を行ってください。
Amazonオフィシャルサイト
Amazon Product Advertising API
Amazon アソシエイト(アフィリエイト) – ヘルプ
参考サイト
[を] Perl による自分用 Amazon Product Advertising API proxy「PAPAXY」
python 2.4でも使える感じの記述を見つけましたが、これは使えないのでしょうか?
http://trac.maruz.net/changeset/118/ATAmazon
コメントありがとうございます。
インストールできる環境であれば、Perlなど使わずにPythonだけで済ませたほうが楽ですね。
hashlib単体でインストールすることも出来るようです。
http://code.krypto.org/python/hashlib/