Radish Network Speed Testing の測定結果をダウンロード

  • /*
     * @title Radish Network Speed Testing の測定結果をダウンロード
     * @description 「みんなの測定結果」の絞り込み検索後に実行すると、指定した期間のデータをCSVファイルとしてダウンロードできる。
     * @include http://netspeed.studio-radish.com/cgi-bin/netspeed/openresult/openresult.cgi?*
     * @license MIT License
     */
    
    (function(w, d) {
    'use strict';
    
    var DEFAULT_PERIOD_MONTH = 1,
        period_month,
        max_date = new Date(),
        max_date_string;
    
    max_date.setDate(max_date.getDate() - 1);
    max_date_string = prompt('基準日(YYYY/MM/DD・デフォルト:昨日)', max_date.getFullYear() + '/' + (max_date.getMonth() + 1) + '/' + max_date.getDate());
    
    if (max_date_string === null) {
        return;
    }
    max_date_string = max_date_string.replace(/^\s*|\s*$/g, '').replace(/[0-9-/]/g, function(s){return String.fromCharCode(s.charCodeAt(0) - 0xfee0);}).replace(/-/g, '/');
    
    if ( max_date_string.match(/^\d{4}\/\d{1,2}\/\d{1,2}$/) ) {
        try {
            max_date = new Date(max_date_string);
        }
        catch (e) {
            max_date = new Date();
        }
    }
    else {
        max_date = new Date();
    }
    max_date_string = max_date.getFullYear() + '/' + (max_date.getMonth() + 1) + '/' + max_date.getDate();
    
    period_month = prompt('収集期間: n(ヶ月) (※基準日(' + max_date_string + ')から、nヶ月前までの測定データが対象)', DEFAULT_PERIOD_MONTH);
    
    if (period_month === null) {
        return;
    }
    period_month = parseInt(period_month, 10);
    
    if (period_month <= 0) {
        period_month = DEFAULT_PERIOD_MONTH;
    }
    
    function collect_data() {
        if (!w.jQuery) {
            setTimeout(collect_data, 100);
            return;
        }
        var $ = w.jQuery;
        
        function change_speed_to_Mbps(speed) {
            if (!$.trim(speed).match(/([\d.]+)\s*(\w?)bps/i)) {
                return speed;
            }
            var value = RegExp.$1,
                unit = RegExp.$2;
            
            switch (unit.toUpperCase()) {
                case 'K':
                    value /= 1000.0;
                    break;
                case 'M':
                    break;
                case 'G':
                    value *= 1000.0;
                    break;
                case 'T':
                    value *= 1000000.0;
                    break;
                default:
                    value /= 1000000.0;
                    break;
            }
            return value;
        }
        
        function get_filter_info(body) {
            var searchform = body.find('form#searchformid'),
                option_text_list = [];
            
            searchform.find('select').each(function() {
                var select = $(this),
                    value = select.val();
                
                select.find('option[value=' + value + ']').each(function() {
                    var option = $(this),
                        text = option.text().replace(/[─│┌┐┘└├┬┤┴┼]/g, '');
                    
                    option_text_list.push(text);
                });
            });
            
            var zipcode = '';
            
            searchform.find('input').each(function() {
                var input = $(this),
                    type = input.attr('type'),
                    name = input.attr('name'),
                    value = input.val();
                
                switch (type) {
                    case 'checkbox':
                        option_text_list.push( value + '=' + (input.prop('checked') ? 'ON' : 'OFF') );
                        break;
                    case 'text':
                        if (name == 'zipcode1') {
                            zipcode += value;
                        }
                        else if (name == 'zipcode2') {
                            zipcode += '-' + value;
                            option_text_list.push(zipcode);
                        }
                        break;
                }
            });
            
            return option_text_list.join('・');
        }
    
        function get_date_string(date) {
            return date.getFullYear() + '/' + (parseInt(date.getMonth(),10) + 1) + '/' + date.getDate();
        }
        
        function get_time_string(date) {
            return date.getHours() + ':' + date.getMinutes();
        }
        
        function get_date(speed_data) {
            if ( !speed_data.match(/(\d{4})\/(\d{1,2})\/(\d{1,2})[\s()a-zA-Z]+(\d{1,2}):(\d{1,2})/) ) {
                return null;
            }
            return new Date(RegExp.$1, RegExp.$2 - 1, RegExp.$3, RegExp.$4, RegExp.$5);
        }
        
        function get_any_value(data, title, terminator) {
            if ( !data.match(title + '\\s*[::]\\s*(.*?)' + terminator) ) {
                return '';
            }
            return $.trim(RegExp.$1);
        }
        
        function get_server(speed_data) {
            return get_any_value(speed_data, '測定サーバー', '\\*詳細情報\\*');
        }
        
        function get_service_type(speed_data2) {
            return get_any_value(speed_data2, '使用回線', '\\n');
        }
        
        function get_isp(speed_data2) {
            return get_any_value(speed_data2, 'プロバイダ', '\\n');
        }
        
        function get_area(speed_data2) {
            return get_any_value(speed_data2, '測定地', '\\n');
        }
        
        function get_speed_info(table) {
            var topic_id = $.trim(table.find('a[href *= "openresult.cgi?topic"]').first().text()),
                NA = '',
                downlink_speed = NA,
                uplink_speed = NA,
                speed_list = [],
                speed_data = table.find('div.speeddata').first().text(),
                speed_data2 = table.find('div.speeddata2').first().text();
            
            table.find('span.graphmarker').each(function(){
                speed_list.push(change_speed_to_Mbps($(this).text()));
            });
            if (table.find('nobr:contains(下り)').size() < 1) {
                speed_list.unshift(NA);
            }
            if (table.find('nobr:contains(上り)').size() < 1) {
                speed_list.push(NA);
            }
            if (2 <= speed_list.length) {
                downlink_speed = speed_list[0];
                uplink_speed = speed_list[1];
            }
            
            return {
                topic_id : topic_id
            ,   date : get_date(speed_data)
            ,   server : get_server(speed_data)
            ,   service_type : get_service_type(speed_data2)
            ,   isp : get_isp(speed_data2)
            ,   area : get_area(speed_data2)
            ,   downlink_speed : downlink_speed
            ,   uplink_speed : uplink_speed
            };
        }
        
        var get_page_info = (function() {
            var next_url_dict = {}, topic_id_dict = {};
            
            return function(page_root, since_date, until_date) {
                var speed_info_list = [],
                    next_url = null,
                    first_date = new Date();
                
                page_root.find('table.graphscale').each(function() {
                    var table = $(this).parents('table').eq(1),
                        speed_info = get_speed_info(table),
                        target_date = speed_info.date,
                        topic_id = speed_info.topic_id;
                    
                    if (!speed_info.date) {
                        console.log('日付不正: ' + topic_id);
                        return;
                    }
                    if (topic_id_dict[topic_id]) {
                        console.log('topic_id重複: ' + topic_id);
                        return;
                    }
                    topic_id_dict[topic_id] = true;
                    
                    if (target_date < first_date) {
                        first_date = target_date;
                    }
                    if (target_date < since_date || until_date <= target_date) {
                        console.log('期間外: ' + topic_id);
                        return;
                    }
                    speed_info_list.push(speed_info);
                });
                
                if (since_date <= first_date) {
                    next_url = page_root.find('a[href *= "openresult.cgi"]:contains(過去のデータへ)').first().attr('href');
                    if (next_url_dict[next_url]) {
                        next_url = null;
                    }
                    next_url_dict[next_url] = true;
                }
                
                return {
                    speed_info_list : speed_info_list
                ,   next_url : next_url
                }
            };
        })();
        
        (function() {
            var searchform = $('form#searchformid'),
                speed_info_list = [],
                since_date,
                until_date,
                download_link_id = 'data-to-csv',
                download_link = $('a#' + download_link_id),
                page_number = 1,
                link_text = '【#PAGE#ページ目データ: #COUNT# 件 (合計:#TOTAL# 件)】';
            
            until_date = new Date(max_date.getTime());
            until_date.setDate(max_date.getDate() + 1);
            since_date = new Date(until_date.getTime());
            since_date.setMonth(until_date.getMonth() - period_month);
            
            if (0 < download_link.size()) {
                download_link.remove();
            }
            download_link = $('<a/>')
                .attr('id', download_link_id)
                .css({
                    'margin-left' : '32px'
                ,   'font-size' : '16px'
                ,   'background-color' : 'yellow'
                });
            
            $('div.title1').append(download_link);
            
            function get_csv_line(csv_columns) {
                var output_columns = [];
                $.each(csv_columns, function(index, csv_column) {
                    output_columns.push('"' + (typeof csv_column == 'string' ? csv_column.replace(/"/g, '""') : csv_column) + '"');
                });
                return output_columns.join(',');
            }
            
            function finish(body) {
                var csv_lines = [];
                
                csv_lines.push(get_csv_line([
                    get_date_string(since_date)
                ,   '~'
                ,   get_date_string(max_date)
                ,   '絞り込み条件:'
                ,   get_filter_info(body)
                ]));
                
                csv_lines.push(get_csv_line([
                    'Topic ID'
                ,   '測定日'
                ,   '時刻'
                ,   '測定サーバー'
                ,   '使用回線'
                ,   'プロバイダ'
                ,   '測定地'
                ,   '下り速度(Mbps)'
                ,   '上り速度(Mbps)'
                ]));
            
                $.each(speed_info_list, function(index, speed_info) {
                    var date = speed_info.date;
                    
                    csv_lines.push(get_csv_line([
                        speed_info.topic_id
                    ,   get_date_string(date)
                    ,   get_time_string(date)
                    ,   speed_info.server
                    ,   speed_info.service_type
                    ,   speed_info.isp
                    ,   speed_info.area
                    ,   speed_info.downlink_speed
                    ,   speed_info.uplink_speed
                    ]));
                });
                
                var csv = csv_lines.join('\n'),
                    bom = new Uint8Array([0xEF, 0xBB, 0xBF]),
                    blob = new Blob([bom, csv], {'type' : 'text/csv'}),
                    file_name = 'netspeed.studio-radish.com_' + period_month + 'months_' + (new Date().getTime()) + '.csv',
                    data_url = (w.URL || w.webkitURL).createObjectURL(blob);
                
                download_link
                    .attr('download', file_name)
                    .attr('href', data_url);
                
                if (w.navigator.msSaveOrOpenBlob) {
                    function open_dialog() {
                        w.navigator.msSaveOrOpenBlob(blob, file_name);
                    }
                    download_link.click(open_dialog).click();
                }
                else {
                    download_link.get(0).click();
                }
            }
            
            function get_body(html) {
                if (!html) {
                    return $('body');
                }
                var html = html.replace(/(?:^[\s\S]*?<body.*?>|<\/body>[\s\S]*$)/gi, ''),
                    body = $('<div/>').html(html);
                return body;
            }
            
            function load_page(body) {
                var page_info = get_page_info(body, since_date, until_date);
                
                $.merge(speed_info_list, page_info.speed_info_list);
                
                download_link.text(
                    link_text
                        .replace(/#PAGE#/g, page_number)
                        .replace(/#COUNT#/g, page_info.speed_info_list.length)
                        .replace(/#TOTAL#/g, speed_info_list.length)
                );
                
                if (!page_info.next_url) {
                    finish(body);
                    return;
                }
                page_number ++;
                
                $.get(page_info.next_url, function(html){
                    load_page( get_body(html) );
                }, 'html');
            }
            /*
            //load_page( get_body() ); // 現在表示している絞り込み条件で取得
            // [2015.08.17] [検索]ボタン押下と1頁表示件数[設定]の手間がかかるため、これを自動化
            */
            // 絞り込み条件を設定して検索した結果を取得
            $.get(searchform.attr('action'), searchform.serializeArray(), function(html) {
                // 1頁表示件数を設定した結果を取得
                // ※ 元の HTML(FORM要素) が valid でないため、細工して作り直している
                var body = get_body(html),
                    select = body.find('select[name="size"]'),
                    form_clone = select.parents(':has(form)').first().find('form').clone(),
                    input_clone_list = select.parents(':has(input[type="hidden"])').first().find('input').clone(),
                    select_clone = select.clone();
                
                select_clone.val( select_clone.find('option').last().val() );
                form_clone.append(select_clone).append(input_clone_list);
                
                $.get(form_clone.attr('action'), form_clone.serializeArray(), function(html) {
                    load_page( get_body(html) );
                }, 'html')
            }, 'html');
        })();
    }
    
    var script = d.createElement('script');
    script.src = '//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js';
    d.body.appendChild(script);
    
    collect_data();
    
    })(window, document);
    
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2015/08/17 15:49:47 - 2015-08-17
  2. 2015/08/17 15:49:34 - 2015-08-17
  3. 2015/08/17 12:09:43 - 2015-08-17
  4. 2015/08/17 12:09:29 - 2015-08-17
  5. 2015/08/15 20:55:31 - 2015-08-15
  6. 2015/08/14 08:22:03 - 2015-08-14
  7. 2015/08/14 06:44:15 - 2015-08-14
  8. 2015/08/14 06:35:46 - 2015-08-14
  9. 2015/08/14 06:32:02 - 2015-08-14
  10. 2015/08/14 01:06:45 - 2015-08-14
  11. 2015/08/14 00:36:27 - 2015-08-14
  12. 2015/08/13 22:55:36 - 2015-08-13
  13. 2015/08/13 22:44:49 - 2015-08-13
  14. 2015/08/13 22:37:43 - 2015-08-13
  15. 2015/08/13 21:58:37 - 2015-08-13
  16. 2015/08/13 21:57:14 - 2015-08-13
  17. 2015/08/13 21:56:34 - 2015-08-13
  18. 2015/08/13 21:55:38 - 2015-08-13