amazon_record2015.js amazon_record.js
1// Amazonの注文履歴をTSV形式で出力するスクリプト 1// Amazonの注文履歴をTSV形式で出力するスクリプト
2// 2//
3// 2015-01-01 時点での DOM 構造に対応, GoogleCrome, Opera でテスト済。 3// 2015-01-01 時点での DOM 構造に対応, GoogleCrome, Opera でテスト済。
4// formatEntry関数を書き換えれば自由な書式で出力できます。 4// formatEntry関数を書き換えれば自由な書式で出力できます。
5// 5//
6// 参考: 6// 参考:
7//  - Amazonの注文履歴をCSV形式にして出力するスクリプト 7//  - Amazonの注文履歴をCSV形式にして出力するスクリプト
8//    https://gist.github.com/arcatdmz/8500521 8//    https://gist.github.com/arcatdmz/8500521
9//  - Amazon で使った金額の合計を出す奴 (2014 年バージョン) 9//  - Amazon で使った金額の合計を出す奴 (2014 年バージョン)
10//    https://gist.github.com/polamjag/866a8af775c44b3c1a6d 10//    https://gist.github.com/polamjag/866a8af775c44b3c1a6d
11   
12(function(){ 11(function () {
13   
14    // 各注文履歴をTSVフォーマットにして返す 12    // 各注文履歴をTSVフォーマットにして返す
15    var datePattern = new RegExp("(\\d{4})年(\\d{1,2})月(\\d{1,2})日"); 13    var datePattern = new RegExp("(\\d{4})年(\\d{1,2})月(\\d{1,2})日");
16    function formatEntry(entry) { 14    function formatEntry(entry) {
17        console.log(entry); 15        console.log(entry);
18        entry.date.match(datePattern); 16        entry.date.match(datePattern);
19        var year = RegExp.$1; 17        var year = RegExp.$1;
20        var month = RegExp.$2; if (month.length <= 1) month = "0" + month; 18        var month = RegExp.$2;
21        var day = RegExp.$3; if (day.length <= 1) day = "0" + day; 19        if (month.length <= 1)
  20            month = "0" + month;
  21        var day = RegExp.$3;
  22        if (day.length <= 1)
  23            day = "0" + day;
22        var date = "" + year + "/" + month + "/" + day; 24        var date = "" + year + "/" + month + "/" + day;
23        var arr = [date, entry.name, entry.author, entry.url]; 25        var arr = [date, entry.name, entry.author, entry.url];
24        return arr.join('\t') + "\n"; 26        return arr.join('\t') + "\n";
25    } 27    }
26   
27    function popup(content) { 28    function popup(content) {
28        var generator=window.open('','name','height=250,width=700'); 29        var generator = window.open('', 'name', 'height=250,width=700');
29        generator.document.write('<html><head><title>Amazon to TSV</title>'); 30        generator.document.write('<html><head><title>Amazon to TSV</title>');
30        generator.document.write('</head><body>'); 31        generator.document.write('</head><body>');
31        generator.document.write('<pre>'); 32        generator.document.write('<pre>');
32        generator.document.write(content); 33        generator.document.write(content);
33        generator.document.write('</pre>'); 34        generator.document.write('</pre>');
34        generator.document.write('</body></html>'); 35        generator.document.write('</body></html>');
35        generator.document.close(); 36        generator.document.close();
36        return generator; 37        return generator;
37    } 38    }
38   
39    var itemDelimiter = " / "; 39    var itemDelimiter = " / ";
40    var total = {}; 40    var total = {};
41    var year = '2014'; 41    var year = '2014';
  42    var nyear = 2014;
42    var all = false; 43    var all = false;
43       
44    function init(num) { 44    function init(num) {
45        if(typeof num !== 'number') { 45        if (typeof num !== 'number') {
46            var num = 0; 46            var num = 0;
47            $('<div/>').css({ 47            $('<div/>').css({
48                position: 'fixed', 48                position: 'fixed',
49                left: 0, 49                left: 0,
50                top: 0, 50                top: 0,
51                width: '100%', 51                width: '100%',
52                height: '100%', 52                height: '100%',
53                zIndex: 1000, 53                zIndex: 1000,
54                backgroundColor: 'rgba(0,0,0,.7)', 54                backgroundColor: 'rgba(0,0,0,.7)',
55                color: '#fff', 55                color: '#fff',
56                fontSize: 30, 56                fontSize: 30,
57                textAlign: 'center', 57                textAlign: 'center',
58                paddingTop: '15em'  58                paddingTop: '15em' 
59            }).attr('id', '___overlay').text('Amazonいくら使った?').appendTo('body'); 59            }).attr('id', '___overlay').text('Amazonいくら使った?').appendTo('body');
60            year = window.prompt('何年分の注文を集計しますか?\n - 半角数字4桁で入力してください\n - 全期間を集計する場合は「all」と入力します', year); 60            year = window.prompt('何年分の注文を集計しますか?\n - 半角数字4桁で入力してください\n - 全期間を集計する場合は「all」と入力します', year);
61            if(year === 'all') { 61            if (year === 'all') {
62                all = true; 62                all = true;
63                year = jQuery('div.top-controls select option:last').val().match(/[0-9]/g).join(''); 63                year = jQuery('div.top-controls select option:last').val().match(/[0-9]/g).join('');
64            } else if(!/^[0-9]{4}$/.test(year)) { 64            }
  65            else if (!/^[0-9]{4}$/.test(year)) {
65                alert('正しい数値を入力してください'); 66                alert('正しい数値を入力してください');
66                $('#___overlay').remove(); 67                $('#___overlay').remove();
67                return false; 68                return false;
68            } 69            }
69            year = Number(year); 70            nyear = Number(year);
70        } 71        }
71        // 第二引数を true にすると各商品とかエラーを逐一表示する 72        // 第二引数を true にすると各商品とかエラーを逐一表示する
72        var progress = load(num, false); 73        var progress = load(num, false);
73        $('#___overlay').text(year+'年の集計中…  / '+(num+1)+'ページ目'); 74        $('#___overlay').text(nyear + '年の集計中…  / ' + (num + 1) + 'ページ目');
74        progress.done(function(results){ 75        progress.done(function (results) {
75            if (typeof total[year] ===  'undefined') { 76            if (typeof total[nyear] === 'undefined') {
76                total[year] = results; 77                total[nyear] = results;
77            } else { 78            }
78                total[year] = total[year].concat(results); 79            else {
  80                total[nyear] = total[nyear].concat(results);
79            } 81            }
80            init(num+1); 82            init(num + 1);
81        }).fail(function(){ 83        }).fail(function () {
82            if(all && new Date().getFullYear() > year) { 84            if (all && new Date().getFullYear() > nyear) {
83                year++; 85                nyear++;
84                init(0); 86                init(0);
85            } else { 87            }
  88            else {
86                var _total = 0; 89                var _total = 0;
87                var _content = ""; 90                var _content = "";
88                jQuery.each(total, function(year, results){  91                jQuery.each(total, function (nyear, results) { 
89                    var yen = 0; 92                    var yen = 0;
90                    jQuery.each(results, function(){ 93                    jQuery.each(results, function () {
91                        yen += this.price; 94                        yen += this.price;
92                        $.each(this.items, function(i, item){ 95                        $.each(this.items, function (i, item) {
93                            _content += formatEntry(item); 96                            _content += formatEntry(item);
94                        }); 97                        });
95                    }); 98                    });
96                    _total += yen; 99                    _total += yen;
97                }); 100                });
98                // result 101                // result
99                $('#___overlay').remove(); 102                $('#___overlay').remove();
100                alert('合計 ' + _total + ' 円'); 103                alert('合計 ' + _total + ' 円');
101                popup(_content); 104                popup(_content);
102                console.log('合計 ' + _total + ' 円'); 105                console.log('合計 ' + _total + ' 円');
103            } 106            }
104        }); 107        });
105    } 108    }
106       
107    function load(num, verbose) { 109    function load(num, verbose) {
108        var df = jQuery.Deferred(); 110        var df = jQuery.Deferred();
109        var page = get(num, verbose); 111        var page = get(num, verbose);
110        page.done(function(data){ 112        page.done(function (data) {
111            var dom = jQuery.parseHTML(data); 113            var dom = jQuery.parseHTML(data);
112            var results = []; 114            var results = [];
113   
114            jQuery(dom).find('div.order').each(function(){ 115            jQuery(dom).find('div.order').each(function () {
115                var box = jQuery(this); 116                var box = jQuery(this);
116                var dateText = jQuery(box.find('div.order-info span.value')[0]).text().trim(); 117                var dateText = jQuery(box.find('div.order-info span.value')[0]).text().trim();
117   
118                var items = []; 118                var items = [];
  119                var item = {};
119                var pubarr = box.find("div.a-row > span.a-size-small"); 120                var pubarr = box.find("div.a-row > span.a-size-small");
120                box.find("div.a-row > a.a-link-normal").each(function(j) { 121                box.find("div.a-row > a.a-link-normal").each(function (j) {
121                    var item = {}; 122                    item = {};
122                    item.name = $(this).text().trim(); 123                    item['name'] = $(this).text().trim();
123                    item.path = $(this).attr('href').trim(); 124                    item['path'] = $(this).attr('href').trim();
124                    item.url = 'https://www.amazon.co.jp' + item.path; 125                    item['url'] = 'https://www.amazon.co.jp' + item['path'];
125                    item.date = dateText; 126                    item['date'] = dateText;
126                    item.author = $(pubarr[j*2]).text().trim().replace(/(\n)/g, ''); 127                    item['author'] = $(pubarr[j * 2]).text().trim().replace(/(\n)/g, '');
127item.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(); 128                    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();
128                    items.push(item); 129                    items.push(item);
129                }); 130                });
130   
131                var priceText = jQuery(box.find('div.order-info span.value')[1]).text(); 131                var priceText = jQuery(box.find('div.order-info span.value')[1]).text();
132                var price = Number(priceText.match(/[0-9]/g).join('')); 132                var price = Number(priceText.match(/[0-9]/g).join(''));
133  133                if (verbose)
134                if (verbose) console.log(item, price); 134                    console.log(item, price);
135                results.push({'date':dateText,'items':items,'price':price}); 135                results.push({ 'date': dateText, 'items': items, 'price': price });
136            }); 136            });
137  137            if (results.length <= 0)
138            if(results.length <= 0) df.reject(); 138                df.reject();
139            else df.resolve(results); 139            else
  140                df.resolve(results);
140        }); 141        });
141        return df.promise(); 142        return df.promise();
142    } 143    }
143      144    function get(num, verbose) {
144    function get(num) {  
145        var df = jQuery.Deferred(); 145        var df = jQuery.Deferred();
146        jQuery.ajax({ 146        jQuery.ajax({
147            url: 'https://www.amazon.co.jp/gp/css/order-history?digitalOrders=1&unifiedOrders=1&orderFilter=year-'+year+'&startIndex='+num*10, 147            url: 'https://www.amazon.co.jp/gp/css/order-history?digitalOrders=1&unifiedOrders=1&orderFilter=year-' + year + '&startIndex=' + num * 10,
148            beforeSend: function (xhr){ 148            beforeSend: function (xhr) {
149                xhr.setRequestHeader('X-Requested-With', {toString: function(){ return ''; }});  149                //xhr.setRequestHeader('X-Requested-With', { toString: function () { return ''; } }); 
  150                function toString() { return ''; } 
  151                xhr.setRequestHeader('X-Requested-With', 'toString'); 
  152                //xhr.setRequestHeader('X-Requested-With', '');//NG 
150            }, 153            },
151        })  154            success: function (data) { 
152            .success(function(data){   
153                df.resolve(data); 155                df.resolve(data);
  156            }
154            }) 157        })
155            .fail(function(jqXHR, msg){ 158            .fail(function (jqXHR, msg) {
156                if (verbose) console.log("fail", msg); 159            if (verbose)
  160                console.log("fail", msg);
157            }); 161        });
158        return df.promise(); 162        return df.promise();
159    } 163    }
160       
161    if(typeof jQuery !== 'function') { 164    if (typeof jQuery !== 'function') {
162        var d=document; 165        var d = document;
163        var s=d.createElement('script'); 166        var s = d.createElement('script');
164        s.src='//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js'; 167        s.src = '//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js';
165        s.onload=init;  168        s.onload = function (e) { init(null); }; 
166        d.body.appendChild(s); 169        d.body.appendChild(s);
167    } else {  
168        init();  
169    } 170    }
170})(); 171    else { 
  172        init(null); 
  173    } 
  174})();
  175//# sourceMappingURL=amazon_record.js.map