2018年8月18日土曜日

Googleスプレッドシートで Google Apps Script を使って Amazon API から価格を取得してみた。

Google スプレッドシートで、Google Apps Script から Amazon API を使用して、価格を読み込みに挑戦しました。
以前から出来ることは知っていましたが、やり方が全くわかりませんでした。
今日はまとまった時間が取れたので、下のページを参考に試行錯誤でやってました。

【参考】Amazon Product Advertising API を Google Apps Scriptで使う

若干の変更を加える必要がありましたが、価格の読み込みに成功しました。
ISBNから取得を紹介するページは多くありましたが、ASINで検索する方法の紹介が見当たらなかったので少し苦労しましたが難しい部分はありませんでした。
もう少し作り込んで近日中にコードを下に貼り付けていきたいと思います。

最近は時間が無いのでスキマ時間にPCで遊ぶくらいしかできない。。。

次のスキマ時間はいつだ!?

2018/8/18
APIを読み込んで価格の取得方法はわかりました。
取得した価格をスプレッドシートへ入力する方法もわかりました。
前回の価格と今回の価格を比較して、安ければメールを送る方法もわかりました。
トリガーから、時間主導型のイベントを設定して動作させる方法がわかりました。

さて、ここからが問題。。。この前の Prime Day で欲しかったものをまとめて買ったので価格チェックをしたい商品が思い浮かばない。

2019/5/5
nanVeさん、コメントありがとうございます。
2019年1月頃に、利用ポリシーの変更があり、それから動かなくなっています。
愛用していたのに残念。。。この記事を放置していて、アドバイス出来ずごめんなさい。
時期未定ですが、動くように修正して記事を改訂します。


function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [
    {
      name : "AmazonAPIを実行",
      functionName : "amazonFunction"
    }
  ];
  sheet.addMenu("スクリプト実行", entries);
  //メインメニュー部分に[スクリプト実行]メニューを作成して、
  //下位項目のメニューを設定している
};


function callAmazonAPI(asin) {
  // Amazon API を読み込んで、価格を抽出する。
  
  var associate_tag_id = "アソシエイトのタグID";
  var access_key_id    = "アクセスキー";
  var secret_key       = "シークレットキー";
  var endpoint = "webservices.amazon.co.jp";
  var uri = "/onca/xml";
  
  var params = {
    Service: "AWSECommerceService",
    Version: "2013-08-01",
    Operation: "ItemSearch",
    AWSAccessKeyId: access_key_id,
    AssociateTag: associate_tag_id,
    SearchIndex: "All",
    Timestamp: new Date().toISOString(),
    Keywords: "asin= " + asin,
    //ResponseGroup: "ItemAttributes,Offers"
    ResponseGroup: "Offers"
  };

  // ソートが必要
  var sort_params = Object.keys(params).sort();
  sort_params = sort_params.map(function(key) {
    return key + "=" + encodeURIComponent(params[key]);
  });

  var canonical_query_string = sort_params.join("&");
  var string_to_sign = "GET\n" + endpoint + "\n" + uri + "\n" + canonical_query_string;

  // 署名が必要
  var signature = Utilities.base64Encode(Utilities.computeHmacSha256Signature(string_to_sign, secret_key));

  // リクエストのURL
  var request_url = 'http://' + endpoint + uri + '?' + canonical_query_string + '&Signature=' + encodeURIComponent(signature);

  // レスポンス取得
 // 503エラーでもレスポンスを受け取れるようにmuteHttpExceptionsをtrueにする
  var response = UrlFetchApp.fetch(request_url, {muteHttpExceptions: true});
  var responseCode = response.getResponseCode();
  var responseBody = response.getContentText();
  var document = XmlService.parse(responseBody);
  var prise = '';
  var name = XmlService.getNamespace('http://webservices.amazon.com/AWSECommerceService/2013-08-01');
  var root = document.getRootElement();
  
  if (responseCode === 200) {
    var items = root.getChild('Items', name).getChildren('Item', name);
    for(var i = 0; i < items.length; i++) {
      // xmlからitemの情報を取得 
      prise = items[i].getChild('OfferSummary', name).getChild('LowestNewPrice', name).getChild('Amount', name).getText();
      return prise
    }
  } else {
    // エラー時はxmlのnamespaceが異なる
    ns = XmlService.getNamespace('http://ecs.amazonaws.com/doc/2013-08-01/');
    var message = root.getChild('Error', name).getChild('Message', name);
    return message.getText();
  }

}

function amazonFunction () {
  // Amazon API から取得した価格をスプレッドシートへ入力し、値段が安ければメールを送信する。

  var book = SpreadsheetApp.getActiveSpreadsheet();
  var sheetData = book.getSheetByName("シート1");

  var rowASIN  = 1;
  var colPrise = 2;

  var colStartData = 2
  var colEndData = sheetData.getDataRange().getLastColumn()
  var rowEndData = sheetData.getDataRange().getLastRow()

  sheetData.getRange( rowEndData+1, 1 ).setValue(new Date().toLocaleString())
  
  for (var i = colStartData; i <= colEndData; i += 1) {
    
      var asin  = sheetData.getRange( rowASIN, i ).getValue();
      var price = callAmazonAPI( asin )
      sheetData.getRange( rowEndData+1, i ).setValue(price);
  }
  
  checkPrice() //価格を比較して安ければメールを送信
}

function checkPrice(){
  // 商品の価格を前後比較する。
  var book = SpreadsheetApp.getActiveSpreadsheet();
  var sheetData = book.getSheetByName("シート1");

  var colStartData = 2
  var rowItemName  = 2
  var colEndData = sheetData.getDataRange().getLastColumn()
  var rowEndData = sheetData.getDataRange().getLastRow()
  
  for (var i = colStartData; i <= colEndData; i += 1) {
    // 前後データを取得する
    var itemName = sheetData.getRange( rowItemName , i ).getValue().replace(/\r?\n/g,"") // 改行を除去する。
    var prePrice = Number(sheetData.getRange( rowEndData-1, i ).getValue());
    var nowPrice = Number(sheetData.getRange( rowEndData  , i ).getValue());
    var dtPrice  = prePrice - nowPrice
    
    if( dtPrice > 0 ) {
      // 価格が安くなったらメールを送る。
      var title = itemName + "が、"+String(dtPrice)+"円、安くなっています。"
      var body  = "ご主人さま\n\nAmazonの価格を調べたら\n"+title+"\n\nどうされますか?\n\n前回の価格 "+String(prePrice)+"円\n今回の価格 "+String(nowPrice)+"円"
      MailApp.sendEmail('メールアドレス', title, body);
    }
  }
}

//function myFunction () {
//  Browser.msgBox("確認", "Hello GAS World.", Browser.Buttons.OK);
//}


1 件のコメント:

  1. はじめまして、GASでやりたいことを探していたら漂着致しました。
    GASは今日から初めたくらいの初心者です。VBEは数年やってます。
    スプレッドシートのA列にASINを記入し、アソシエイトタグ等は記入しました。
    onOpen で起動し認証しましたが、シート1に価格が表示されませんでした。

    お忙しいところ恐縮ですがご教授よろしくお願いいたします。

    返信削除

2年ぶりに更新

 最後の記事が21年3月でしたので、27ヶ月ぶり。 2020年頃から始まったコロナ禍から在宅ワークがなくなり、通常運転に慣れてきた頃。 そろそろ新しい趣味を探していこうと思っています。 さて何するかな。。。