乐白家娱乐loo666.com


[原创.数据可视化系列的七]阿里比作品技术展示

乐百家loo777时寒冰:三导致给房价回归合理价

乐百家loo777抓取国家统计局全国划分代码

近年干活着需以全国划分代码,感觉国家统计局供的数据比较权威,而且为算比较新(截止至2014年10月31日),所以打算把这些多少抓下去。

立是国家统计局提供的查询页面:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2014/index.html

率先分析下页面

<table class='provincetable' width=775>
    <tr>
        <td colspan=8 height=1 style='FONT-SIZE: 5px'>&nbsp;</td>
    </tr>
    <tr class='provincehead'>
        <td colspan=8 align='center' style='FONT-SIZE: 16px' height=39 vAlign='center' background='images/tiao.jpg'>
            <strong>2014年统计用区划代码和城乡划分代码(截止2014年10月31日)</strong></td>
    </tr>
    <tr>
        <td colspan=8 height=50 style='FONT-SIZE: 12px'>   统计用区划代码和城乡划分代码说明:统计用区划代码和城乡划分代码所涉及的数据,是国家统计局开展统计调查所涉及的区划范围,未包括我国台湾省、香港特别行政区、澳门特别行政区。
            <br>
        </td>
    </tr>
    <tr class='provincetr'>
        <td><a href='11.html'>北京市<br/></a></td>
        <td><a href='12.html'>天津市<br/></a></td>
        <td><a href='13.html'>河北省<br/></a></td>
        <td><a href='14.html'>山西省<br/></a></td>
        <td><a href='15.html'>内蒙古自治区<br/></a></td>
        <td><a href='21.html'>辽宁省<br/></a></td>
        <td><a href='22.html'>吉林省<br/></a></td>
        <td><a href='23.html'>黑龙江省<br/></a></td>
    </tr>
。。。
</table>

页面比较根本,用jsoup解析没有什么困难,所有的地面信息都是坐落一个table中的,但是会产生几沾不同,第一,一级地方信息是于第四个tr开始之,其它等级的地方信息是从第二只tr开始之;第二,每一级地方信息的tr的class不一致;第三,最后一级地方及市辖区td中的子元素不同等。

鉴于大部分地带信息的体裁都是平,所以可以生出一个大约的思绪,可以拿全国之地面信息看做成一株树,比如我们得以以中华当作是及时株树之清节点,然后遍历这棵树,将节点依次插入。

故此节点要定义name也即是地区称,id地区代码,childNodes该地域的生一级地方节点,还有一个即是url,我们使用url访问页面。

产生了此思路我们虽足以拓展遍历了。

PageFetcher根据url抓到手到页面,ContentParser页面解析器解析页面。

万一将节点插入树中,我们首先要组织一个含有子节点的清节点,然后递归遍历所有节点。

由由页面中收获到的链接是一个相对路径,所以我们得将拖欠链接拼接成一个总体的url,并经过递归传递,当该节点的url为空并且该节点代码的第7各类到第10各类的价也000时常,说明该节点也叶子节点,就见面跳出循环不再为生递归。

    public void loadRegionNode(RegionNode regionNode, String superUrl) {

        String url = subUrl(superUrl) + regionNode.getUrl();

        FetchedPage fetchedPage = pageFetcher.getContentFromUrl(url);

        List<RegionNode> list;
        //首页数据已经预先加载
        if (regionNode.getChildNode() == null) {

            list = contentParser.parseHTML(fetchedPage);

        } else {
            list = regionNode.getChildNode();
        }

        //当list为null时则可能遍历到叶子节点
        if (list != null && list.size() > 0) {

            //将子节点插入
            regionNode.setChildNode(list);

            for (RegionNode node : list) {
                //该节点为叶子节点且为最后一级
                if(node.getUrl() == null && !node.getId().substring(6,12).equals("000000") ){
                    break;
                }

                loadRegionNode(node, url);
            }
        }
    }

因各地方页面样式的异,可以下jsoup定义一个页面解析器,不同等级的地方使用不同之剖析策略,所以可以以ContentParser中进行判定,分别解析

    public static List<RegionNode> parseHTML(FetchedPage fetchedPage) {
        //当抓取的页面为空或者返回状态码不是200返回空
        if (fetchedPage == null || fetchedPage.getStatusCode() != 200) {
            return null;
        }
        List<RegionNode> regionNodeList = new ArrayList<RegionNode>();
        Document doc = Jsoup.parse(fetchedPage.getContent());
        //获取当前页面中的地区节点
        Elements tableSet = doc.getElementsByTag("TABLE");
        Element regionTable = tableSet.get(4);
        Elements trSet = regionTable.getElementsByTag("tr");
        for (int i = 1; i < trSet.size(); i++) {
            Element tr = trSet.get(i);
            Elements elements = tr.getAllElements();

            //当子元素数量等于3时,说明为没有子节点的市辖区
            if (elements.size() == 3) {
                Element codeTdTag = elements.get(1);
                Element nameTdTag = elements.get(2);
                String name = nameTdTag.text();
                String code = codeTdTag.text();
                RegionNode regionNode = new RegionNode();
                regionNode.setRegionName(name);
                regionNode.setId(code);
                regionNodeList.add(regionNode);
                System.out.println("code:"+code+";name:"+name);
                continue;
            }

            //当子元素数量等于4时,说明为叶子节点
            if (elements.size() == 4) {
                Element codeTdTag = elements.get(1);
                Element nameTdTag = elements.get(3);
                String name = nameTdTag.text();
                String code = codeTdTag.text();
                RegionNode regionNode = new RegionNode();
                regionNode.setRegionName(name);
                regionNode.setId(code);
                regionNodeList.add(regionNode);
                System.out.println("code:"+code+";name:"+name);
                continue;
            }
            Element codeATag = elements.get(2);
            Element nameATag = elements.get(4);
            String href = codeATag.attr("href");
            String code = codeATag.text();
            String name = nameATag.text();
            RegionNode regionNode = new RegionNode();
            regionNode.setId(code);
            regionNode.setRegionName(name);
            regionNode.setUrl(href);
            regionNodeList.add(regionNode);
            System.out.println("code:"+code+";name:"+name+";href:"+href);
        }
        return regionNodeList;
    }

约需要等一个小时,一个完好的树形结构的地方信息就是抓取完成了,然后我们得依据需要保留成json或者xml文件,或者直接保存到数据库被。

源码已经上传到我之github:https://github.com/gordonFm/regionSpider,编译即可运行,数据是以json格式保存之。

相关文章

No Comments, Be The First!
近期评论
    文章归档
    功能
    网站地图xml地图