最終回としてAmazon APIを使って簡単なサンプルを作っていきましょう!
エントリーのサブタイトルで「最安値やランキング取得できるよ」と言っているので、最安値を取得するサービス(※サービスとも言いがたいものがですが)を作ってみようと思います。
では、いってみましょう!

サービスの概要とAPIの制限の確認
作成する前に、どういったサービスを作るのかと、Amazon APIでどこまで実現できるのかを確認しておきます。
前回までで、Amazon APIのおおよその概要やプログラミングのイメージはできていると思います。
ただ、いざ作ろうとなるとパラメーターの組み合わせの制限とかあって、思ったのができねーじゃねーかってことがよくあります。
今回作るサービスではAmazon APIの仕様から実現できるところと実現できないところをハッキリと明示します。
ですので、パラメーターがごちゃごちゃで良くわからないという方は切り分けの部分も合わせて参考にしてもらえればと思います。
作っていくサービス
Amazonの商品群をキーワードで検索して価格が安い順番に並び替えるサービスです。
文字にすると簡単です。あとは、Amazon APIの仕様とにらめっこして実現できることと、実現できないところを切り分けていきます。
利用するパラメーター
Amazon APIではリクエストURLを作成してAmazonサーバーにアクセスし、結果をレスポンスしてもらうという仕組みでした。
前回(「Amazon API」の使い方⑥-パラメーターの種類とか編-)は、パラメーターとして必須のものとオプションとしてつけるものを紹介しました。
商品を検索して安い順に並び替えるには、どういったパラメーターが必要になりそうか確認しておきましょう。
必須のパラメーターとだいたいつけてるパラメーター
- Service(必須)
- AWSAccessKeyId(必須)
- Operation(必須)
- Timestamp(必須)
- Signature(必須)
- AssociateTag(必須)
- Version
- ResponseGroup
パラメーターの意味がわからない方は、第6回を参考にしてください。
「Amazon API」の使い方⑥-パラメーターの種類とか編-
商品検索で安い順に並び替えるために必要なパラメーター
商品を検索するので、Operationには、「ItemSearch」を指定します。
そして「ItemSearch」を指定することで選べるようになるパラメーターを指定していきます。
- SearchIndex(必須)
- Keywords
- Sort
- MinimumPrice
- ItemPage
「ItemSearch」に紐づくパラメーターについて1つずつ解説していきます。
SearchIndex
Operation=ItemSearchを指定した時に必須となるパラメーターです。
日本語でわかりやすく言うと、商品のカテゴリーを指定するところです。
Amazonで商品を検索する時にドロップダウンリストで選択できるところです。
カテゴリは1つしか選択できませんので、今回はDVDに絞って作っていきます。
SearchIndex=Video
どんな値が指定できるかは、以下のドキュメントから確認できます。(Amazonを実際に利用してもらうとイメージがわきやすい思います。)
→ Locale Information for the JP Marketplace – Product Advertising API
Keywords
実際に検索したキーワードです。
これは分かりやすいですね。
Keywords=[任意のキーワード]
Sort
並び替え方法を指定します。
これが少しクセモノで、「SearchIndex」のパラメーターで「すべて(All)」と「ブランド(Blended)」を指定した場合は利用できない仕様になっています。
つまり、Amazon APIで並び替えをしたい場合は、何らかのカテゴリーを指定しなければいけないということです。
「すべて」のカテゴリーの商品検索からは並び替えできません。
価格の安い順番に並び替えるので、「price」を指定します。
このソートの厄介なところが、新品と中古が両方ある場合は、どちらかの安い方でソートされてしまうところです。
新品の商品だけに絞ってソートや、中古の商品だけに絞ってソートができないようになってます。
Sort=price
MinimumPrice
名前から分かると思いますが、最低価格を指定します。
1,000円以上とかそういうやつですね。
つけないと、1円の商品が引っかかりすぎて嫌だったので、とりあえず100円以上で設定してみました。
MinimumPrice=100
ItemPage
Amazon APIは1度に最高で10件までの商品しか返してくれません。
11件目以降の商品が欲しい場合は、「ItemPage=2」などと指定して、2ページ目をもらう必要があります。
ブログとかでいうとページャーのイメージです。
Amazon APIの仕様として10ページまでの情報しか得られないようになっていて、
つまり、1回の取得限界が10件、そして取得ページの限界が10ページなので、
1回の検索に対して10件×10ページで合計100件までの商品しか取得できないということですね。
ItemPage=11と指定するとエラーになります。
今回は最安値を見つけられればいいので、1ページ目だけでいいでしょう。
ItemPage=1
実現できること、実現できないこと
長くなってきたので、一旦ここでまとめましょう。
カテゴリー「すべて」では並び替えできない!
カテゴリーが「すべて」の商品では最安値は取得できません。また、複数のカテゴリーを選択することもできません。
このことから、Amazon APIを利用して最安値を取得するには、特定のカテゴリーを指定する必要があります。
新品と中古は区別できない!
価格での並び替えは、新品の価格も中古の価格も混ざって行われます。
したがって、新品だけ中古だけと切り分けて並び替えることはできません。ごちゃまぜです。
最大取得件数は100件!
結果の最大取得件数は100件です。今回は、最安値を見つけるサービスなので問題はないと思いますが、検索結果をすべて利用したい場合はキーワードやカテゴリーの指定を工夫して100件以内に収める必要があります。
価格が取得できない商品がある!
あと理由は分かりませんが、価格を取得できない商品があります。(Amazonから返されるレスポンスに価格がない)
ただしソートの処理では、どこからか価格を引っ張っていてその価格に則ってソートされます。
なので、価格が含まれない商品(※Amazonのページにリンクで飛ぶと価格は存在する)が結果としてかえってきますが、
正直こちらでは何もできないので、プログラムで弾くかAmazonの対応を待つしかありません。
といったところでしょうか。
検索の機能としては不十分なところが多いですが、無料で利用させてもらってる身分としてはなんとも言えないので、
とりあえず、使える範囲で作っていきましょう!
ちなみに、Amazon APIで利用出来る機能は、Amazonのサイトで検索するときに利用できる機能となんら変わりありません。(自分が確認した範囲では。)
Amazon APIを叩いて「なんかしょぼい結果が返ってくるな」と思って、Amazonで同じように検索すると同じようなしょぼい結果が返ってきます。
要するに、Amazonの検索システムがしょぼi(ry、、、、おっと誰か来たようだ。
Amazon APIを使って最安値を取得しよう!
さて、長いこと前置きしましたが、実際に作っていきましょう!
とはいっても、利用するパラメータとかはまとまっているので第4回に作ったプログラムに当てはてたりすればつくれます。
キーワードはフォームに入力して、そのキーワードにマッチする商品の最安値を取得しましょう。
カテゴリーは「DVD」で固定します。
コピー<!DOCTYPE html>
<html lang="ja">
<head>
<title>Amazon APIテスト</title>
<meta charset="utf-8">
</head>
<body>
<?php
//Enter your IDs
define("Associate_tag", "*****"); // アソシエイトタグ
define("Access_Key_ID", "******************"); // アクセスキー
define("Secret_Access_Key", "**************************************"); // シークレットキー
ItemSearch("Video", "アナと雪の女王"); // Videosを選択、「アナと雪の女王」は好きなキーワードを選んでください。
//Set up the operation in the request
function ItemSearch($SearchIndex, $Keywords){
$baseurl = "https://webservices.amazon.co.jp/onca/xml";
// リクエストのパラメータ作成
$params = array();
$params["Service"] = "AWSECommerceService";
$params["AWSAccessKeyId"] = Access_Key_ID;
$params["Version"] = "2013-08-01";
$params["Operation"] = "ItemSearch";
$params["SearchIndex"] = $SearchIndex;
$params["Keywords"] = $Keywords;
$params["AssociateTag"] = Associate_tag;
$params["ResponseGroup"] = "ItemAttributes,Offers";
$params["Sort"] = "price";
$params["MinimumPrice"] = "100";
$params["ItemPage"] = "1";
/* 0.元となるリクエスト */
$base_request = "";
foreach ($params as $k => $v) {
$base_request .= "&" . $k . "=" . $v;
}
$base_request = $baseurl . "?" . substr($base_request, 1);
echo "【0.元となるリクエスト】<br>" . $base_request . "<br>";
/* 1.タイムスタンプを付ける */
$params["Timestamp"] = gmdate("Y-m-d\TH:i:s\Z");
$base_request .= "&Timestamp=" . $params['Timestamp'];
echo "【1.タイムスタンプを付ける】<br>" . $base_request . "<br>";
/* 2.「RFC 3986」形式でエンコーディング */
$base_request = "";
foreach ($params as $k => $v) {
$base_request .= '&' . $k . '=' . rawurlencode($v);
$params[$k] = rawurlencode($v);
}
$base_request = $baseurl . "?" . substr($base_request, 1);
echo "【2.「RFC 3986」形式でエンコーディング】<br>" . $base_request . "<br>";
/* 3.「&」とか消して改行 */
$base_request = preg_replace("/.*\?/", "", $base_request);
$base_request = str_replace("&", "\n", $base_request);
echo "【3.「&」とか消して改行】<br>" . $base_request . "<br>";
/* 4.パラメーター名で昇順ソート */
ksort($params);
$base_request = "";
foreach ($params as $k => $v) {
$base_request .= "&" . $k . "=" . $v;
}
$base_request = substr($base_request, 1);
$base_request = str_replace("&", "\n", $base_request);
echo "【4.パラメーター名で昇順ソート】<br>" . $base_request . "<br>";
/* 5.もう一度「&」でつなぐ */
$base_request = str_replace("\n", "&", $base_request);
echo "【5.もう一度「&」でつなぐ】<br>" . $base_request . "<br>";
/* 6.3行を頭に追加 */
$parsed_url = parse_url($baseurl);
$base_request = "GET\n" . $parsed_url['host'] . "\n" . $parsed_url['path'] . "\n" . $base_request;
//$base_request = "GET\nwebservices.amazon.com\n/onca/xml\n" . $base_request;
echo "【6.3行を頭に追加】<br>" . $base_request . "<br>";
/* 7.よく分からんエンコーディング */
$signature = base64_encode(hash_hmac('sha256', $base_request, Secret_Access_Key, true));
$signature = rawurlencode($signature);
echo "【7.よく分からんエンコーディング】<br>" . $signature . "<br>";
/* 8.「Signature」として最後に追加 */
$base_request = "";
foreach ($params as $k => $v) {
$base_request .= "&" . $k . "=" . $v;
}
$base_request = $baseurl . "?" . substr($base_request, 1) . "&Signature=" . $signature;
echo "【8.「Signature」として最後に追加】<br>" . $base_request . "<br>";
echo "<a href=\"" . $base_request . "\" target=\"_blank\">結果</a>";
$amazon_xml=simplexml_load_string(file_get_contents($base_request));
foreach($amazon_xml->Items->Item as $item) {
$item_title = $item->ItemAttributes->Title; // 商品名
$item_url = $item->DetailPageURL; // 商品へのURL
$item_new_price = $item->OfferSummary->LowestNewPrice->FormattedPrice; // 新品商品の価格
$item_used_price = $item->OfferSummary->LowestUsedPrice->FormattedPrice; // 中古商品の価格
$item_price = $item->Offers->Offer->OfferListing->Price->FormattedPrice; // Amazon商品の価格
echo "<p><a href=\"" . $item_url . "\" target=\"_blank\">" . $item_title . "</a><br>";
echo "(Amazon)" . $item_price . "<br>";
echo "(新品)" . $item_new_price . "<br>";
echo "(中古)" . $item_used_price . "</p>";
}
}
?>
</body>
</html>
本当に雑なプログラムですいません。
実行してもらうと、下の方に検索結果が出てきます。
価格が3つあります。中古の価格と、新品の価格、そしてAmazonが在庫として持っている商品の価格です。
中古と新品はAmazon以外の出品者の可能性もあります。
サービスを作りますと言いつつ、サービスとは言い難いものを紹介しましたが、とりあえずプログラムのイメージをつかんでもらえたらなと思います。
おわり
1年越しに最終回まで書き上げることができました。
果たして完結しているのかは怪しいところですが、Amazon APIを使って検索を行う方法はなんとなく理解できたのではないでしょうか。
もっと書きたいことはあるのですが、Amazon APIはパラメーターの組み合わせが複雑で書くのに大変労力がかかるのです・・・。
ということで、あとはご自身で勉強してください!
Amazon APIを理解する上で役立ちそうな公式のドキュメントを貼り付けてお別れです。
どうもありがとうございました。
日本語のAmazon APIガイド
→ Product Advertising API
英語のAmazon APIガイド
→ API Reference – Product Advertising API
検索時のパラメーターの組み合わせ一覧表
→ Locale Information for the JP Marketplace – Product Advertising API
ブラウズノード(Browse Node)をまとめてくれています。(今回は利用してませんが、いずれ使うときがくるはず!)
→ Amazon アソシエイト(アフィリエイト) – ヘルプ
第1回:アソシエイトタグの取得
第2回:アクセスキーとシークレットキーの取得
第3回:リクエストURL作成の概要
第4回:リクエストURLの作成(PHP)と結果(XML)の確認
第5回:リクエスト結果(XML)の表示
第6回:パラメーターの種類とか
最終回:実際に作ってみよう