从总结局采集最新的省市区或县多少lehuguoji乐虎国际网址

1八-0一-2八早晨陆:30的列车,从新乡回老家,票难买啊。青睐动~
宣称:文中提到到的数据和第2方接口、url仅供就学生运动用,请勿它用~

这几天都在磨着搭建本地质度量试环境,看到省市区数据表里面是空的,想着在此之前的老多少还是一三年收集的,含省市区县四级数据共肆.100000条,时间久了,使用进度中窥见有个别新的城市名称数据库中并未,县级数据一向就不曾用到过,想着照旧再一次采集壹份。

新采集的省市区数量有358九条,此番并不曾把县级数据采过来,须要的时候再添加也挺好。

多少来自

国家计算局总结标准《2016年计算用区划代码和城市和乡村分割代码(截止201六年0九月二二十八日)》,这么些是2017-05-1陆揭发的,当前是流行的。

lehuguoji乐虎国际网址 1

多少收集

对于数据搜集,依据办事亟待,对于部分小的数据收集功用有个别接触。因为对html和js熟些,很早以前就用IE浏览器对当地html文件辅助任意跨域ajax请求数据、和支撑读写Excel文件,就间接写叁个html文件作为采集工具给外人利用,批量询问人士资料、考试结果如何的效用。所以采集省市区数量首要用的js。

一. 抓取原始数据

打开网页http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/index.htmllehuguoji乐虎国际网址,省份的数据就有了,进入市级页面,然后进入区级页面,还能进来县级页面。整个流程地址结构十一分简单,数据格式也很好提取。

进去网页后打开浏览器控制台,执行上边代码,那段代码仅仅包涵采集省市区的,把县级的阉割掉了,一三年的老代码有县级的。很早在此以前写的代码,风格有些丑,然而能能健康使用就是好的,那么些采访是“单线程的”,因为这个多少少,速度并十分的快:

/*
获取城市名称http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016/index.html
*/
(function(){
if(!window.URL){
    throw new Error("浏览器版本太低");
};
function ajax(url,True,False){
    var ajax=new XMLHttpRequest();
    ajax.timeout=1000;
    ajax.open("GET",url);
    ajax.onreadystatechange=function(){
        if(ajax.readyState==4){
            if(ajax.status==200){
                True(ajax.responseText);
            }else{
                False();
            }
        }
    }
    ajax.send();
}
function msg(){
    console.log.apply(console, arguments);
}

function cityClass(name,url,code){
    this.name=name;
    this.url=url;
    this.code=code;
    this.child=[];
    this.tryCount=0;
}
cityClass.prototype={
    getValue:function(){
        var obj={name:this.name,code:this.code,child:[]};
        for(var i=0;i<this.child.length;i++){
            obj.child.push(this.child[i].getValue());
        }
        return obj;
    }
}

function load_all(True){
    var path="http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2016";
    ajax(path+"/index.html",function(text){
        var reg=/href='(.+?)'>(.+?)<br/ig,match;
        var idx;
        if((idx=text.indexOf("<tr class='provincetr'>"))+1){
            reg.lastIndex=idx;
            while(match=reg.exec(text)){
                var url=match[1];
                if(url.indexOf("//")==-1 && url.indexOf("/")!=0){
                    url=path+"/"+url;
                }
                var name=match[2];
                DATA.push(new cityClass(name,url,0));
            }
            True();
        }else{
            msg("未发现省份数据");
        }
    },function(){
        msg("读取省份列表出错","程序终止");
    });
}
function load_shen(True, False){
    var city=DATA[JD.shen];
    city.tryCount++;
    if(city.tryCount>3){
        msg("读取省份["+city.name+"]超过3次");
        False();
        return;
    };

    function get(){
        msg("读取省份["+city.name+"]", getJD());
        save();

        city.child[JD.si].tryCount=0;
        load_si(function(){
            JD.shen++;
            if(JD.shen>=DATA.length){
                JD.shen=0;
                True();
                return;
            };
            DATA[JD.shen].tryCount=0;

            load_shen(True,False);
        },function(){
            False();
        });
    }

    if(city.child.length){
        get();
    }else{
        ajax(city.url,function(text){
            var reg=/<tr class='citytr'>.+?href='(.+?)'>(.+?)<.+?'>(.+?)</ig;
            var match;
            while(match=reg.exec(text)){
                var url=match[1];
                if(url.indexOf("//")==-1 && url.indexOf("/")!=0){
                    url=city.url.substring(0,city.url.lastIndexOf("/"))+"/"+url;
                }
                var code=match[2];
                var name=match[3];
                city.child.push(new cityClass(name,url,code));
            }

            JD.si=0;
            get();
        },function(){
            load_shen(True,False);
        });
    };
}

function load_si(True,False){
    var shen=DATA[JD.shen];
    var city=shen.child[JD.si];
    city.tryCount++;
    if(city.tryCount>3){
        msg("读取城市["+city.name+"]超过3次");
        False();
        return;
    };


    function get(){
        msg("___读取城市["+city.name+"]", getJD());

        city.child[JD.xian].tryCount=0;
        JD.si++;
        if(JD.si>=shen.child.length){
            JD.si=0;
            True();
            return;
        };
        shen.child[JD.si].tryCount=0;

        load_si(True,False);
    }

    if(city.child.length){
        get();
    }else{
        ajax(city.url,function(text){
            var reg=/class='(?:countytr|towntr)'.+?<\/tr>/ig;
            var match;
            while(match=reg.exec(text)){
                var reg2=/class='(?:countytr|towntr)'.+?(?:<td><a href='(.+?)'>(.+?)<.+?'>(.+?)<|<td>(.+?)<.+?<td>(.+?)<)/ig;
                var match2;
                if(match2=reg2.exec(match[0])){
                    var url=match2[1]||"";
                    if(url.indexOf("//")==-1 && url.indexOf("/")!=0){
                        url=city.url.substring(0,city.url.lastIndexOf("/"))+"/"+url;
                    }
                    var code=match2[2]||match2[4];
                    var name=match2[3]||match2[5];
                    city.child.push(new cityClass(name,url,code));
                }else{
                    msg("未知城市模式:");
                    msg(city.url);
                    msg(match[0]);
                    throw new Error("end");
                }
            }

            JD.xian=0;
            get();
        },function(){
            load_si(True,False);
        });
    };
}


function getJD(){
    var str="省:"+(JD.shen+1)+"/"+DATA.length;
    var shen=DATA[JD.shen];
    if(shen){
        str+=" 市:"+(JD.si+1)+"/"+shen.child.length;
        var si=shen.child[JD.si];
        if(si){
            str+=" 县:"+(JD.xian+1)+"/"+si.child.length;
        }else{
            str+=" 县:"+JD.xian;
        }
    }else{
        str+=" 市:"+JD.si+" 县:"+JD.xian;
    }
    return str;
}
function save(){

}

var DATA=[];
var JD;
window.RunLoad=function(shen,si,xian){
    RunLoad.T1=Date.now();
    JD={
        shen:shen||0
        ,si:si||0
        ,xian:xian||0
    }

    function get(){
        DATA[JD.shen].tryCount=0;
        load_shen(function(){
            console.log("完成:"+(Date.now()-RunLoad.T1)/1000+"秒");
            save();

            var data=[];
            for(var i=0;i<DATA.length;i++){
                data.push(DATA[i].getValue());
            }

            var url=URL.createObjectURL(
                new Blob([
                    new Uint8Array([0xEF,0xBB,0xBF])
                    ,"var CITY_LIST="
                    ,JSON.stringify(data,null,"\t")
                ]
                ,{"type":"text/plain"})
            );
            var downA=document.createElement("A");
            downA.innerHTML="下载查询好城市的文件";
            downA.href=url;
            downA.download="data.txt";
            document.body.appendChild(downA);
            downA.click();

            msg("--完成--");
        },function(){
            save();
            msg("当前进度:", getJD());
        });
    }

    var data=localStorage["load_data"];
    if(data){
        DATA=JSON.parse(data);
        get();
    }else{
        load_all(get);
    }
}
})();//@ sourceURL=console.js


//立即执行代码
RunLoad()

征集截图:

lehuguoji乐虎国际网址 2

二. 拍卖数量和拼音标注

数据处理就大约些了,比如编号格式化、名称格式化等。

拼音标注:这几个供给找二个接口对文字实行拼音翻译,唯有四个渴求:明斯克能正常的翻译成chong
qing即可,翻译成zhong
qing的就low了。满意这一个规格,百度上探寻到的翻译小网址五分四就被干掉了。

浏览器中打开找到的翻译接口http://www.qqxiuzi.cn/zh/pinyin/,截止到当下是能健康调用的,因为要用ajax请求数据,在页面里面就从没有过跨域的难点,查看网页源码,把token值记录下来,这几个网址翻译请求须要带这几个token,注意~刷新页面要重新获得:

lehuguoji乐虎国际网址 3

拼音那个因为数据量比较多,选择了“四个线程”采集,先把第3步采集到的公文打开,把数量复制到打开的翻译网址浏览器控制台里面实践(也等于把数据导入),然后实施下边代码:

/*
拼音翻译
http://www.qqxiuzi.cn/zh/pinyin/

http://www.qqxiuzi.cn/zh/pinyin/show.php
POST
t=汉字&d=1&s=null&k=1&b=null&h=null&u=null&v=1&y=null&z=null&token=页面token请求一次获取

先加载数据
    控制台输入data.txt
*/
window.PageToken=window.PageToken||"";
var FixTrim=function(name){
    return name.replace(/^\s+|\s+$/g,"");
};
var CITY_LIST2;
var QueryPinYin=function(end){
    if(!window.PageToken){
        console.error("Need PageToken");
        return;
    };
    var ids=[];

    var fixCode=function(o){
        if(o.deep==0){
            o.orgCode="0";
        }else{
            o.orgCode=o.code;
            if(o.deep==1){
                o.code=o.code.substr(o,4);
            }else{
                o.code=o.code.replace(/(000000|000)$/g,"");//有少部分区多3位
            };
        };
        return o;
    };
    var fix=function(o,p){
        var name=o.name;
        if(o.deep==0){
            name=name.replace(/(市|省|(维吾尔|壮族|回族)?自治区)$/ig,"");
        }else if(o.deep==1){
            if(name=="市辖区"){
                name=p.o2.name;
            }else if(/行政区划$/ig.test(name)){
                name="直辖市";
            }else if(name.length>2){
                name=name.replace(/市$/ig,"");
            };
        }else{
            if(name.length>2 && name!="市辖区"
                && !/(自治.|地区|矿区)$/.test(name)){//直接排除会有同名的
                name=name.replace(/(市|区|县|镇|管委会|街道办事处)$/ig,"");
            };
        };
        var o2={
            name:name
            ,ext_name:o.name
            ,id:+o.code||0
            ,ext_id:+o.orgCode
            ,pid:p&&+p.code||0
            ,deep:o.deep
        };
        o.o2=o2;
        return o2;
    };
    for(var i=0;i<CITY_LIST.length;i++){
        var shen=CITY_LIST[i];
        shen.deep=0;
        for(var i2=0;i2<shen.child.length;i2++){
            var si=shen.child[i2];
            if(!shen.code){
                shen.code=si.code.substr(0,2);
                ids.push(fix(fixCode(shen)));
            };
            si.deep=1;
            ids.push(fix(fixCode(si),shen));


            for(var i3=0;i3<si.child.length;i3++){
                var qu=si.child[i3];
                qu.deep=2;
                ids.push(fix(fixCode(qu),si));
            };
        };
    };
    CITY_LIST2=ids;
    //console.log(JSON.stringify(ids,null,"\t"))
    //return;

    var idx=-1;
    var run=function(stack){
        stack=+stack||0;
        idx++;
        if(idx>=ids.length){
            thread--;
            if(thread==0){
                end();
            };
            return;
        };

        var idx_=idx;
        var id=ids[idx];
        if(id.P){
            stack++;
            if(stack%50==0){
                setTimeout(function(){run()});
            }else{
                run(stack);
            };
            return;
        };

        var name=id.name;
        var tryCount=0;
        var tryLoad=function(){
            $.ajax({
                url:"/zh/pinyin/show.php"
                ,data:"t="+encodeURIComponent(name)+"&d=1&s=null&k=1&b=null&h=null&u=null&v=1&y=null&z=null&token="+PageToken
                ,type:"POST"
                ,dataType:"text"
                ,timeout:1000
                ,error:function(e){
                    if(tryCount>3){
                        console.error("--QueryPinYin error--"+e);
                        run();
                        return;
                    };
                    tryCount++;
                    tryLoad();
                }
                ,success:function(txt){
                    txt=FixTrim(txt.replace(/<.+?>/g,"").replace(/\s+/g," "));
                    id.P=txt;
                    console.log("--"+idx_+"-QueryPinYin "+name+":"+txt+" --");
                    run();
                }
            });
        };
        tryLoad();
    };

    var thread=4;
    run();
    run();
    run();
    run();
};


var ViewDown=function(){
    console.log("完成:"+(Date.now()-RunPinYin.T1)/1000+"秒");
    window.CITY_LIST_PINYIN=CITY_LIST2;
    var url=URL.createObjectURL(
        new Blob([
            new Uint8Array([0xEF,0xBB,0xBF])
            ,"var CITY_LIST_PINYIN="
            ,JSON.stringify(CITY_LIST2,null,"\t")
        ]
        ,{"type":"text/plain"})
    );
    var downA=document.createElement("A");
    downA.innerHTML="下载查询好城市的文件";
    downA.href=url;
    downA.download="data-pinyin.txt";
    document.body.appendChild(downA);
    downA.click();
};

var RunPinYin=function(){
    RunPinYin.T1=Date.now();
    QueryPinYin(ViewDown);
};


//立即执行代码
if(window.CITY_LIST){
    if(!PageToken){
        PageToken=prompt("Token");
    };
    RunPinYin();
}else{
    console.error("data.txt未输入");
};

此刻候会提示输入token,把刚刚找到的token粘贴进去,然后就起来工作了:

lehuguoji乐虎国际网址 4

还挺快的,二分钟多点全体翻译完成。

叁. 格式化成CSV

多少总体有了,导出成相比较健康使用的格式,CSV最佳了。那几个导出相比简单,任意网页控制台把第3部保存的文书打开,复制数据到任意网页控制台,然后输入以下代码:

/*
格式并且输出为csv

先加载数据
    控制台输入data-pinyin.txt

导入数据库:
    文件格式Unicode,文字为字符流
    检查id重复项,修正id
    转入area_city
    增加港澳台、海外两个省级
    检查名称重复项,修正名称
        select * from area_city where len(name)=1
        select pid,name,count(*) from area_city group by pid,name having COUNT(*)>1
*/

var FixTrim=function(name){
    return name.replace(/^\s+|\s+$/g,"");
};
function CSVName(name){
    return '"'+FixTrim(name).replace(/"/g,'""')+'"';
};

var CITY_CSV=["id,pid,deep,name,pinyin_prefix,pinyin,ext_id,ext_name"];
for(var i=0;i<CITY_LIST_PINYIN.length;i++){
    var o=CITY_LIST_PINYIN[i];
    var pf="";
    var pinyin=FixTrim(o.P).toLowerCase();
    var ps=pinyin.split(" ");
    for(var j=0;j<ps.length&&j<3;j++){
        pf+=ps[j].substr(0,j==0?2:1);
    };

    CITY_CSV.push(o.id+","+o.pid+","+o.deep+","+CSVName(o.name)
        +","+CSVName(pf)+","+CSVName(o.P)
        +","+CSVName(o.ext_id+"")+","+CSVName(o.ext_name));
};

var url=URL.createObjectURL(
    new Blob([
        new Uint8Array([0xEF,0xBB,0xBF])
        ,CITY_CSV.join("\n")
    ]
    ,{"type":"text/plain"})
);
var downA=document.createElement("A");
downA.innerHTML="下载查询好城市的文件";
downA.href=url;
downA.download="ok_data.csv";
document.body.appendChild(downA);
downA.click();

OK,数据总体搞完:

lehuguoji乐虎国际网址 5

数据难点

  1. id编号和国家总括局的号子基本壹致,方便现在更新。

  2. id重复项如今是未曾(已优化过了),可是在此以前采集后直接对计算局的编号进行简要收缩后会有再度现象(算是精度丢失)。

  3. 拼音前缀取的是率先个字前三个字母和后三个字首字母,意图是让第二个字相同名称的尽量能排序在壹块。排序1:黑龙江helj、湖北hub、湖南hun;排序2:湖北hb、黑龙江hlj、湖南hn,排序一胜出。

  4. 因为区名字是直接去掉市、区后缀,存在那么几对名字变得精光相同的,供给手动吧市区后缀加上,不然会发出没不寻常。

  5. 最后数额已上传了1份到CSDN,含全部代码和本文书档案:http://download.csdn.net/download/xiangyuecn/10226964

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图