// Amazonの注文履歴をCSV形式にして出力するスクリプト // // 以下のスクリプトを参考に作成されました。 // http://moroya.hatenablog.jp/entry/2013/06/03/225935 // // CSVに成型しているのは14行目から定義されているformatEntryという関数なので、これを書き換えれば自由な書式で出力できます。 (function(){ // 各注文履歴をCSVフォーマットにして返す var datePattern = new RegExp("(\\d{4})年(\\d{1,2})月(\\d{1,2})日"); function formatEntry(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 item = entry.item.split("\"").join("\"\""); //for private use: return year + month + day + ",,," + entry.price + ",\"Amazon: " + item + "\"\n"; //for public use: //return year + "-" + month + "-" + day + "," + entry.price + ",\"" + item + "\"\n"; } // 一つの注文に含まれる複数の物品名をつなぐ文字列 var itemDelimiter = " / "; var total = {}; var year = '2014'; var all = false; function init(num) { if(typeof num !== 'number') { num = 0; $('
').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 = $('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); } var progress = load(num); $('#___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 txt = 'あなたは\n'; var _contents = ""; var _total = 0; $.each(total, function(year, results){ var yen = 0; $.each(results, function(){ yen += this.price; _contents += formatEntry(this); }); txt += year + '年 合計' + addFigure(yen) + '円分\n'; _total += yen; }); if(all) txt += '総計' + addFigure(_total) + '円分\n'; popup(_contents).alert(txt + 'の買い物をAmazonでしました!'); var saveAsCsv = function() { var blob = new Blob([_contents], {type: "text/plain; charset=utf-8"}); saveAs(blob, "amazon.csv"); }; if(typeof saveAs !== 'function') { var d=document; var s=d.createElement('script'); s.src='//cdn.rawgit.com/eligrey/FileSaver.js/master/FileSaver.min.js'; s.onload=saveAsCsv; d.body.appendChild(s); } else { saveAsCsv(); } $('#___overlay').remove(); } }); } function load(num) { var df = $.Deferred(); var page = get(num); page.done(function(data){ var dom = $.parseHTML(data); var results = []; $(dom).find('div.order').each(function(){ var box = $(this); var dateText = $(box.find('div.order-info span.value')[0]).text(); var items = []; box.find('div.a-row>a.a-link-normal').each(function(){ items.push($(this).text().trim()); }); var item = items.join(itemDelimiter); var priceText = $(box.find('div.order-info span.value')[1]).text(); var price = Number(priceText.match(/[0-9]/g).join('')); console.log(item, price); results.push({'date':dateText,'item':item,'price':price}); }); if(results.length <= 0) df.reject(); else df.resolve(results); }); return df.promise(); } function get(num) { var df = $.Deferred(); $.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){ console.log("fail",msg); }); return df.promise(); } function addFigure(str) { var num = new String(str).replace(/,/g, ""); while(num != (num = num.replace(/^(-?\d+)(\d{3})/, "$1,$2"))); return num; } function popup(content) { var generator=window.open('','name','height=250,width=700'); generator.document.write('');
generator.document.write(escapeHtml(content));
generator.document.write('');
generator.document.write('');
generator.document.close();
return generator;
}
var entityMap = {
"&": "&",
"<": "<",
">": ">",
'"': '"',
"'": ''',
"/": '/'
};
var entityPattern = new RegExp("[&<>\"'\/]", "g");
function escapeHtml(string) {
return String(string).replace(entityPattern, function (s) {
return entityMap[s];
});
}
if(typeof $ !== '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();
}
})();