Instantly share code, notes, and snippets.

Embed
What would you like to do?
Amazonで一年間に使った金額と、注文履歴のTSVを出力するブックマークレット【2015年版】
// Amazonの注文履歴をTSV形式で出力するスクリプト
//
// 2015-01-01 時点での DOM 構造に対応, GoogleCrome, Opera でテスト済。
// formatEntry関数を書き換えれば自由な書式で出力できます。
//
// 参考:
// - Amazonの注文履歴をCSV形式にして出力するスクリプト
// https://gist.github.com/arcatdmz/8500521
// - Amazon で使った金額の合計を出す奴 (2014 年バージョン)
// https://gist.github.com/polamjag/866a8af775c44b3c1a6d
(function(){
// 各注文履歴をTSVフォーマットにして返す
var datePattern = new RegExp("(\\d{4})年(\\d{1,2})月(\\d{1,2})日");
function formatEntry(entry) {
console.log(entry);
entry.date.match(datePattern);
var year = RegExp.$1;
var month = RegExp.$2; if (month.length <= 1) month = "0" + month;
var day = RegExp.$3; if (day.length <= 1) day = "0" + day;
var date = "" + year + "/" + month + "/" + day;
var arr = [date, entry.name, entry.author, entry.url];
return arr.join('\t') + "\n";
}
function popup(content) {
var generator=window.open('','name','height=250,width=700');
generator.document.write('<html><head><title>Amazon to TSV</title>');
generator.document.write('</head><body>');
generator.document.write('<pre>');
generator.document.write(content);
generator.document.write('</pre>');
generator.document.write('</body></html>');
generator.document.close();
return generator;
}
var itemDelimiter = " / ";
var total = {};
var year = '2014';
var all = false;
function init(num) {
if(typeof num !== 'number') {
var num = 0;
$('<div/>').css({
position: 'fixed',
left: 0,
top: 0,
width: '100%',
height: '100%',
zIndex: 1000,
backgroundColor: 'rgba(0,0,0,.7)',
color: '#fff',
fontSize: 30,
textAlign: 'center',
paddingTop: '15em'
}).attr('id', '___overlay').text('Amazonいくら使った?').appendTo('body');
year = window.prompt('何年分の注文を集計しますか?\n - 半角数字4桁で入力してください\n - 全期間を集計する場合は「all」と入力します', year);
if(year === 'all') {
all = true;
year = jQuery('div.top-controls select option:last').val().match(/[0-9]/g).join('');
} else if(!/^[0-9]{4}$/.test(year)) {
alert('正しい数値を入力してください');
$('#___overlay').remove();
return false;
}
year = Number(year);
}
// 第二引数を true にすると各商品とかエラーを逐一表示する
var progress = load(num, false);
$('#___overlay').text(year+'年の集計中… / '+(num+1)+'ページ目');
progress.done(function(results){
if (typeof total[year] === 'undefined') {
total[year] = results;
} else {
total[year] = total[year].concat(results);
}
init(num+1);
}).fail(function(){
if(all && new Date().getFullYear() > year) {
year++;
init(0);
} else {
var _total = 0;
var _content = "";
jQuery.each(total, function(year, results){
var yen = 0;
jQuery.each(results, function(){
yen += this.price;
$.each(this.items, function(i, item){
_content += formatEntry(item);
});
});
_total += yen;
});
// result
$('#___overlay').remove();
alert('合計 ' + _total + '');
popup(_content);
console.log('合計 ' + _total + '');
}
});
}
function load(num, verbose) {
var df = jQuery.Deferred();
var page = get(num, verbose);
page.done(function(data){
var dom = jQuery.parseHTML(data);
var results = [];
jQuery(dom).find('div.order').each(function(){
var box = jQuery(this);
var dateText = jQuery(box.find('div.order-info span.value')[0]).text().trim();
var items = [];
var pubarr = box.find("div.a-row > span.a-size-small");
box.find("div.a-row > a.a-link-normal").each(function(j) {
var item = {};
item.name = $(this).text().trim();
item.path = $(this).attr('href').trim();
item.url = 'https://www.amazon.co.jp' + item.path;
item.date = dateText;
item.author = $(pubarr[j*2]).text().trim().replace(/(\n)/g, '');
items.push(item);
});
var priceText = jQuery(box.find('div.order-info span.value')[1]).text();
var price = Number(priceText.match(/[0-9]/g).join(''));
if (verbose) console.log(item, price);
results.push({'date':dateText,'items':items,'price':price});
});
if(results.length <= 0) df.reject();
else df.resolve(results);
});
return df.promise();
}
function get(num) {
var df = jQuery.Deferred();
jQuery.ajax({
url: 'https://www.amazon.co.jp/gp/css/order-history?digitalOrders=1&unifiedOrders=1&orderFilter=year-'+year+'&startIndex='+num*10,
beforeSend: function (xhr){
xhr.setRequestHeader('X-Requested-With', {toString: function(){ return ''; }});
},
})
.success(function(data){
df.resolve(data);
})
.fail(function(jqXHR, msg){
if (verbose) console.log("fail", msg);
});
return df.promise();
}
if(typeof jQuery !== 'function') {
var d=document;
var s=d.createElement('script');
s.src='//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js';
s.onload=init;
d.body.appendChild(s);
} else {
init();
}
})();
@vvakame

This comment has been minimized.

Show comment
Hide comment
@vvakame

vvakame Mar 10, 2015

item.price = $(this).parent().parent().parent().parent().parent().parent().parent().parent().parent().parent().parent().find(".order-info").find(".a-span2").find(".a-size-base").find(".value").text().trim();

ものすごい雑に上記のコードをL120とかに突っ込んだら金額も抜けました。助かりましたありがとうございます!

vvakame commented Mar 10, 2015

item.price = $(this).parent().parent().parent().parent().parent().parent().parent().parent().parent().parent().parent().find(".order-info").find(".a-span2").find(".a-size-base").find(".value").text().trim();

ものすごい雑に上記のコードをL120とかに突っ込んだら金額も抜けました。助かりましたありがとうございます!

@OHM79

This comment has been minimized.

Show comment
Hide comment
@OHM79

OHM79 Oct 1, 2017

ChromeでデベロッパーツールのConsoleに上記コードをコピペして使用するかと思いますが、
デベロッパーツールを別ウィンドウにしているとwindow.prompt()が表示されず、入力結果が空扱いで動作するようです。
ですので、使用時はデベロッパーツールをamazonを表示しているウィンドウにドッキングして使用すると問題なく動作します。

自分としてはブックマークレットの形式にすると使いやすいかと思います。

window.prompt() will not activate parent page - Chrome Platform Status

OHM79 commented Oct 1, 2017

ChromeでデベロッパーツールのConsoleに上記コードをコピペして使用するかと思いますが、
デベロッパーツールを別ウィンドウにしているとwindow.prompt()が表示されず、入力結果が空扱いで動作するようです。
ですので、使用時はデベロッパーツールをamazonを表示しているウィンドウにドッキングして使用すると問題なく動作します。

自分としてはブックマークレットの形式にすると使いやすいかと思います。

window.prompt() will not activate parent page - Chrome Platform Status

@g495

This comment has been minimized.

Show comment
Hide comment
@g495

g495 Sep 7, 2018

Issue:「非表示にした注文」がある場合、全期間(all)での集計できない

「非表示にした注文」がある場合、全期間(all)での集計ができません。

「非表示にした注文」がある場合、注文履歴の期間選択部分が以下の画像のようになり、

スクショ

div.top-controls 配下の最後の <option> 要素が「非表示にした注文」になってしまい、

init(num) の以下のコードの option:last の部分で、「非表示にした注文」が取得されてしまい集計の開始年(画像では2015年)が取得できません。

if(year === 'all') {
    all = true;
    year = jQuery('div.top-controls select option:last').val().match(/[0-9]/g).join('');
} else if ~

上記のコードを以下のようにすると、とりあえず「非表示にした注文」があっても動くと思います。

if(year === 'all') {
  all = true;
  var oldestYear = jQuery('div.top-controls select option:last').val();
  // 「非表示にした注文」(archived)がある場合、最後から2番目の<option>要素が最も古い年に対応する
  if(oldestYear === 'archived') {
      oldestYear = jQuery('div.top-controls select option:nth-last-child(2)').val();
  }
  year = oldestYear.match(/[0-9]/g).join('');
}else if ~

g495 commented Sep 7, 2018

Issue:「非表示にした注文」がある場合、全期間(all)での集計できない

「非表示にした注文」がある場合、全期間(all)での集計ができません。

「非表示にした注文」がある場合、注文履歴の期間選択部分が以下の画像のようになり、

スクショ

div.top-controls 配下の最後の <option> 要素が「非表示にした注文」になってしまい、

init(num) の以下のコードの option:last の部分で、「非表示にした注文」が取得されてしまい集計の開始年(画像では2015年)が取得できません。

if(year === 'all') {
    all = true;
    year = jQuery('div.top-controls select option:last').val().match(/[0-9]/g).join('');
} else if ~

上記のコードを以下のようにすると、とりあえず「非表示にした注文」があっても動くと思います。

if(year === 'all') {
  all = true;
  var oldestYear = jQuery('div.top-controls select option:last').val();
  // 「非表示にした注文」(archived)がある場合、最後から2番目の<option>要素が最も古い年に対応する
  if(oldestYear === 'archived') {
      oldestYear = jQuery('div.top-controls select option:nth-last-child(2)').val();
  }
  year = oldestYear.match(/[0-9]/g).join('');
}else if ~
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment