Skip to content

Instantly share code, notes, and snippets.

@nao-pon
Forked from koyopro/amazon-csv.js
Last active April 6, 2020 08:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nao-pon/23e78b756dcd2c7654002ccaf1d62154 to your computer and use it in GitHub Desktop.
Save nao-pon/23e78b756dcd2c7654002ccaf1d62154 to your computer and use it in GitHub Desktop.
// 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 cur = 0;
var all = false;
var $;
function init(num) {
$ = jQuery;
if(typeof num !== 'number') {
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 = $('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(++cur);
}).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='https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/src/FileSaver.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 = [];
var cnt = 0;
$(dom).find('div.order').each(function(){
cnt++;
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.shipment span.a-color-price')[0]).text();
if (priceText && priceText.match) {
priceText = priceText.match(/[0-9]/g);
} else {
return true;
}
if (!priceText) {
return true;
}
var price = Number(priceText.join(''));
console.log(item, price);
results.push({'date':dateText,'item':item,'price':price});
});
if (cnt) {
df.resolve(results);
} else {
df.reject();
}
}).fail(function() {
df.reject();
});
return df.promise();
}
function get(num) {
var df = $.Deferred();
$.ajax({
url: 'https://www.amazon.co.jp/gp/your-account/order-history/?ie=UTF8&orderFilter=year-'+year+'&search=&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);
df.reject();
});
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('<html><head><title>Amazon to CSV</title>');
generator.document.write('</head><body>');
generator.document.write('<pre>');
generator.document.write(escapeHtml(content));
generator.document.write('</pre>');
generator.document.write('</body></html>');
generator.document.close();
return generator;
}
var entityMap = {
"&": "&amp;",
"<": "&lt;",
">": "&gt;",
'"': '&quot;',
"'": '&#39;',
"/": '&#47;'
};
var entityPattern = new RegExp("[&<>\"'\/]", "g");
function escapeHtml(string) {
return String(string).replace(entityPattern, function (s) {
return entityMap[s];
});
}
if(typeof window.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();
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment