程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> 抓取國家統計局全國區劃代碼,抓取國家統計局區劃

抓取國家統計局全國區劃代碼,抓取國家統計局區劃

編輯:JAVA綜合教程

抓取國家統計局全國區劃代碼,抓取國家統計局區劃


最近工作中需要用到全國區劃代碼,感覺國家統計局提供的數據比較權威,而且也算比較新(截止到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格式保存的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved