以前に PHP で同様のコードを作ったことがあった(知る人ぞ知る)のですが、訳あって Node.js で動かしたくなって移植に挑戦しました。

2017120600


Amazon の Product Advertising API はどちらかというと「AWS ではない Amazon の API」で、エンジニアには馴染みのない人がいるかもしれませんが、アフィリエイトのための商品情報を集める場合に使う API です。こちらで紹介している方法を使うなどして、事前にアクセスキーとアクセスシークレットを取得した上で利用します:
http://dotnsf.blog.jp/archives/1064227473.html


ここで取得したアクセスキーとアクセスシークレットを(7、8行目に)使い、以下のような Node.js コード(amazon.js)を作りました:
//. amazon.js
var crypto = require( 'crypto' );
var request = require( 'request' );
var urlencode = require( 'urlencode' );
var xml2js = require( 'xml2js' );

var aws_key = 'aws_key'; //. アクセスキー
var aws_secret = 'aws_secret'; //. アクセスシークレット

var node = '52905051'; //. スキンケアのカテゴリコード


var request_url = 'http://ecs.amazonaws.jp/onca/xml?';
var local_dt = new Date();
var dt = local_dt.toISOString();  //. GMT timestamp

//. パラメータ
var params = 'AWSAccessKeyId=' + aws_key + '&BrowseNode=' + node;
params += ( '&MaximumPrice=1000&MinimumPrice=1&Operation=ItemSearch&ResponseGroup=ItemAttributes%2CSmall%2CImages&SearchIndex=Beauty&Service=AWSECommerceService&Timestamp=' + urlencode( dt ) + '&Version=2009-01-06' );

//. 署名
var str = 'GET\necs.amazonaws.jp\n/onca/xml\n' + params;
var hash = crypto.createHmac( 'sha256', aws_secret );
hash.update( str );
var hashed_str = hash.digest( 'base64' );

request_url += ( params + '&Signature=' + urlencode( hashed_str ) );

var options = { url: request_url, headers: { 'Host': 'ecs.amazonaws.jp' }, method: 'GET' };

request( options, ( err, res, body ) => {
  if( err ){
    console.log( 'error: ' );
    console.log( err );
  }else{
    //. XML で送られてくる結果を JSON 化して解析
    xml2js.parseString( body, ( err0, xml ) => {
      if( err0 ){
        console.log( err0 );
      }else{
        if( xml && xml.ItemSearchResponse && xml.ItemSearchResponse.Items ){
          var Items = xml.ItemSearchResponse.Items[0];

          var totalpages = Items.TotalPages[0];
          for( var idx = 0; idx < Items.Item.length; idx ++ ){
            var Item = Items.Item[idx];

            var image_url = '', manufacturer = '', brand = '', title = '', listprice = '', ean = '', asin = '';

            try{
              image_url = Item.MediumImage[0].URL[0];
            }catch( e ){
            }
            try{
              manufacturer = Item.ItemAttributes[0].Manufacturer[0];
            }catch( e ){
            }
            try{
              brand = Item.ItemAttributes[0].Brand[0];
            }catch( e ){
            }
            try{
              title = Item.ItemAttributes[0].Title[0];
            }catch( e ){
            }
            try{
              listprice = Item.ItemAttributes[0].ListPrice[0].Amount[0];
            }catch( e ){
            }
            try{
              ean = Item.ItemAttributes[0].EAN[0];
            }catch( e ){
            }
            try{
              asin = Item.ASIN[0];
            }catch( e ){
            }

            if( listprice == '' ){
              listprice = 0;
            }

            console.log( 'ean = ' + ean + ', title = ' + title + ', image_url = ' + image_url + ', manufacturer = ' + manufacturer + ', brand = ' + brand + ', listprice = ' + listprice + ', asin = ' + asin );
          }
        }
      }
    });
  }
});

10行目に検索する商品のカテゴリーブラウズノードを指定します。上記のデフォルト状態では「スキンケア製品」を意味する '52905051' が指定されていますが、変更することもできます。その場合は以下のサイトからブラウズノード一覧をダウンロード&参照し、希望のカテゴリーのノード番号に書き換えて使ってください:
https://affiliate.amazon.co.jp/help/topic/t100


コードの内容はカテゴリや価格帯(今回の例では1円以上1000円未満)を含めた URL に署名付きのパラメータを付けてアクセスし、XML で取得した結果を JSON に変換して取り出す、というシンプルなものです。署名の方法について Node.js でのサンプルがなかったので、別の言語向けに書かれたものを移植して作ってみました。なお、この API では1回の実行で条件を満たす商品を最大10個同時に取得できます。今回のコードでは指定したカテゴリーの商品を10個だけ取得するようになっています(ページング非対応です)。

このコード(amazon.js)を node コマンドで実行すると、以下のように指定したカテゴリーの商品情報を取得して表示します:
$ node amazon.js

ean = 3253581244760, title = ロクシタン(L'OCCITANE) ボンメールソープ ヴァーベナ 100g, image_url = https://images-fe.ssl-images-amazon.com/images/I/41QyQaO75HL._SL160_.jpg, manufacturer = ロクシタンジャポン, brand = ロクシタン(L'OCCITANE), listprice = 864, asin = B00AJFBDKM
ean = 3253581244777, title = ロクシタン(L'OCCITANE) ボンメールソープ ラベンダー 100g, image_url = https://images-fe.ssl-images-amazon.com/images/I/412BXX-d86L._SL160_.jpg, manufacturer = ロクシタンジャポン, brand = ロクシタン(L'OCCITANE), listprice = 864, asin = B00BMW80M0
  :
  :

今回紹介した Amazon Product Advertising API は(特にアフィリエイトサイトの管理を自動化する場合などに)非常に有用なのですが、サイトトップによると「セルフサービスでのご利用を前提としており、Amazon での技術的なサポートは現在行っておりません」とのことです。ハードル高め:
2017120601


自分は「ねっぴ」(http://neppi.co/)の運用を通じて 2014 年くらいから本格的に使っていて、最新情報を追いかけながらとかいうわけではないのですが、ノウハウなども分かってきた所もあるので、こういった場を通じて(今回みたいな形で)少しずつコミュニティに還元できればと思っています。