スキーとネットとロードバイクと旅。

群馬で自由人からリーマンになった恋する男の趣味に生きるブログ。

Amazonのapiを叩いて商品情報を取得の備忘録

Amazonの商品情報を取得するapiProduct Advertising APIという名前なんですが、いつの間にか名前が変わったんですね。昔はAmazon Associates Web Serviceって名前だった気がするんですが、EC2とかのサービスと明確に分けたかったんでしょうか。

日本語のドキュメントもあるんですが、なんか読みにくい。というか、まとまっていない感じがします。楽天のapiとかのほうが、日本人としてはとっつきやすいですね。中身を理解してしまえば同じですが。

で、忘れないように俺的備忘録。この辺のサイトを参考にしました。
http://www.ajaxtower.jp/ecs/
https://images-na.ssl-images-amazon.com/images/G/09/associates/paapi/dg/index.html?UnderstandingImagesSuppliedbyA2S.html
http://ringoon.jp/2009/05/09/memo-amazon-product-advertisin.html

ソース(GETで検索キーワードを受け取ってapiでリクエスト、XMLをパースして画像とタイトルとリンクを取得)

<?php 

	if(isset($_GET["submit"])){
	
		$keyword=$_GET["keyword"];
		
	//access key id とsecret accesskey
	$access_key_id="自分のアクセスキー";
	$secret_access_key="シークレットアクセスキー";

	//RFC3986形式でURLエンコーディング
	function urlencode_rfc3986($str){
		return str_replace("%7E","~",rawurlencode($str));
	}
	
	//基本的なリクエストを作成
	$baseurl = 'http://ecs.amazonaws.jp/onca/xml';
	$params=array();
	$params["Service"]="AWSECommerceService";
	$params["AWSAccessKeyId"]="$access_key_id";
	$params["Version"]="2009-03-31";
	$params["Operation"]="ItemSearch";
	$params["SearchIndex"]="Books";
	$params["Keywords"]=$keyword;
	$params["AssociateTag"]="idealtypes-22";
        $params["ResponseGroup"]="ItemAttributes,Images";
	
	//タイムスタンプパラメータ追加
	//時間表記はISO8601形式、タイムゾーンはUTC(GNT)
	$params["Timestamp"]=gmdate("Y-m-d\TH:i:s\Z");
	
	//パラメータの順序を昇順に並び替え
	ksort($params);
	
	//canonical stringを作成
	$canonical_string="";
	foreach($params as $k => $v){
		$canonical_string.="&".urlencode_rfc3986($k)."=".urlencode_rfc3986($v);
	}
	$canonical_string=substr($canonical_string,1);
	
	//署名作成
	//規定の文字フォーマット作成
	//HMAC-SHA256 を計算
	//BASE64 エンコード
	
	$parsed_url=parse_url($baseurl);
	$string_to_sign="GET\n{$parsed_url["host"]}\n{$parsed_url["path"]}\n{$canonical_string}";
	$signature=base64_encode(hash_hmac("sha256",$string_to_sign,$secret_access_key,true));
	
	//URLを作成
	//リクエストの末尾に署名を追加
	$url=$baseurl."?".$canonical_string."&Signature=".urlencode_rfc3986($signature);

	//パースする
	$xml=simplexml_load_file($url);
	
	$html_table.="<table border='1'>";
	foreach($xml->Items->Item as $value){
		$html_table.='<tr><td><a href="'.$value->DetailPageURL.'"><img src="'.$value->SmallImage->URL.'"></a></td><td><a href="'.$value->DetailPageURL.'">'.$value->ItemAttributes->Title.'</a></td></tr>';
	}

	$html_table.="</table>";
	}
?>

注意点

2009年に仕様変更がありまして、リクエストURLの中にタイムスタンプと署名を追加しなければならなくなりました。タイムスタンプはそのままくっつけてますが、署名は所定の形式でエンコードする必要があります。また、署名自体がリクエストURLや指定したパラメータ、アクセスキーを元に作成されていますので、都度署名を生成する必要があります。
署名生成の際にリクエストURLを利用しますが、base64_encode関数に値を渡すときにAmazon所定の形式(改行コードを入れた形)で値を渡さないといけないんですね。

リクエストURLで取得したい情報グループ(ResponseGroup)をあらかじめ指定しないとxmlには含まれないで返ってくる

楽天の商品検索apiなどではリクエストして戻ってくるXMLはほぼ同じ構造ですが、Amazonの場合はリクエストで取得したい情報を指定してあげないとレスポンスのXMLに入ってきません。この情報の指定は、グループ単位(ResponseGroup)で行います。逆に言えば、何も指定しなければ、非常に基本的な情報のみ戻ってきます。必要に応じて最適なResponseGroupを指定することで、無駄なXMLの取得を避けられます。

ResponseGroupはこの辺を確認するといいですね。
http://www.ajaxtower.jp/ecs/responsegroup/

以上、備忘録でした。