各級(省市縣鎮村)行政區域獲取

      在各類WEB應用中,會填寫我的或者企業的地址信息,以下圖所示,是京東上填寫收貨地址的頁面截圖。 php

      小弟最近也碰到了相似的問題,須要獲得全部省份,每一個省份下屬的市區,沒事市區下屬的縣、鄉鎮、村這些數據。這方面的數據最權威的莫過於國家統計局(http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/index.html)給出的統計,目前國家統計局給出的最新數據是截止到2013年8月13日的數據,沒有香港、澳門特別行政區,沒有釣魚島,沒有三沙市,也沒有臺灣,若是須要能夠單獨加上,以下圖所示: html

      小弟藉助simple_html_dom.php(可在https://github.com/samacs/simple_html_dom下載)這個庫完成頁面的抓取和解析,在這裏,將代碼和你們來分享一下。 git

<?php
include_once ('./simple_html_dom.php');

/* 市、縣、鎮、村這些頁面相似,頁面中的樣式有所區別,這裏給出這些差別 */
define('CITY_CLASS',    'citytr');
define('COUNTY_CLASS',  'countytr');
define('TOWN_CLASS',    'towntr');
define('VILLAGE_CLASS',  'villagetr');

/* 國家統計局行政區域統計的首頁 */
$rootUrl = 'http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/index.html';

/*
 * 從rootUrl中獲取前綴信息,去掉最後面的index.html
 *
 * @param   null
 * @access  public
 * @return  string
 */
function getRootUrlPrefix()
{
    global $rootUrl;
    return preg_replace('/^(http:.*)index(\.html)$/', "$1", $rootUrl);
}

/*
 * 根據rootUrl獲取省份/直轄市代碼
 *
 * @param   null
 * @access  public
 * @return  array       各個省份的code
 */
function getProvinceCode()
{
    global $rootUrl;

    $replaceEreg = '/^([0-9]{2,})\.html$/';
    $province = array();
    $provinceIdx = 0;

    $html = file_get_html($rootUrl);
	
	/* 若是抓取頁面失敗,則10秒後嘗試從新抓取 */
    while (($html = file_get_html($rootUrl)) == false)
    {
        sleep(10);
    }
    foreach($html->find('a') as $ele)
    {
        /* 匹配html文檔中每一個省份對應的URL */
        if (!preg_match($replaceEreg, $ele->href))
        {
            continue;
        }

        /* 獲取每一個省份的名稱 */
        $name = preg_replace('/^(.*)<br.*$/', "$1", $ele->innertext);

        /* 每一個省份的超連接爲: 省份代碼+.html, 從連接中去掉.html, 獲得省份代碼 */
        if ($code = preg_replace($replaceEreg, "$1", $ele->href))
        {
            $province[$provinceIdx]['code'] = $code;
            $province[$provinceIdx]['name'] = iconv('GB2312', 'UTF-8', $name);
            $province[$provinceIdx]['href'] = $ele->href;
            ++$provinceIdx;
        }

        /* 根據省份代碼和rootUrl改造該省份/直轄市的頁面url */
    }
    $html->clear();
    unset($html);

    return $province;
}

/*
 * 獲取某個省份的市、縣、鎮、村代碼
 *
 * @param   string      省份/直轄市代碼
 * @param   string      市、縣、鎮、村的頁面樣式,該變量爲citytr,對於縣,該變量爲countytr,即爲文件開頭定義的幾個宏
 * @param   int         省份代碼,獲取區縣以及區縣如下級別的行政區域code時,須要設置省份代碼(用於構造頁面的URL)
 * @param   int         市代碼,獲取鄉鎮以及鄉鎮如下的行政區域code時,須要設置省份代碼(用於構造頁面的URL)
 * @access  public
 * @return  array       該省份各個市區的代碼
 */
function getAreaCode($url, $trClass, $provinceCode = './', $cityCode = './')
{
    $area = array();
    $areaIdx = 0;
    $code = -1;

    /* 構造獲取城市代碼的url */
    $areaUrl = getRootUrlPrefix() . $provinceCode . '/' . $cityCode . '/' . $url;

    /* 若是抓取頁面失敗,則10秒後嘗試從新抓取 */
    while (($html = file_get_html($areaUrl)) == false)
    {
        sleep(10);
    }
	
	/* 根據頁面特色解析出咱們要的信息 */
    foreach($html->find("tr[class=$trClass] > td") as $td)
    {
        /* td中包含a */
        if ($a = $td->find('a'))
        {
            foreach ($a as $aa)
            {
                if (preg_match('/^[0-9]{12}$/', $aa->innertext))
                {
                    $code = $aa->innertext;
                    ++$areaIdx;
                }
                else
                {
                    $area[$areaIdx]['code'] = $code;
                    $area[$areaIdx]['name'] = iconv('GB2312', 'UTF-8', $aa->innertext);
                    $area[$areaIdx]['href'] = $aa->href;
                }
            }
        }
        else /* td中不包含a */
        {
            if (preg_match('/^[0-9]{12}$/', $td->innertext))
            {
                $code = $td->innertext;
                ++$areaIdx;
            }
            else
            {
                $area[$areaIdx]['code'] = $code;
                $area[$areaIdx]['name'] = iconv('GB2312', 'UTF-8', $td->innertext);
            }
        }
    }

    $html->clear();
    unset($html);
    return $area;
}
     將上面的代碼保存爲areaCode.php文件, 而後咱們能夠經過以下代碼遍歷獲取到省市縣鎮村這些信息,以下所示。
<?php
include_once ('./areaCode.php');

define('LEVEL_PROVINCE',    1);
define('LEVEL_CITY',        2);
define('LEVEL_COUNTY',      3);
define('LEVEL_TOWN',        4);
define('LEVEL_VILLAGE',     5);

/* 控制獲取的區域級別,根據須要進行設置,若是須要獲取到村這個級別,可進行以下設置 */
$getLevel = LEVEL_VILLAGE;

/* 獲取省份信息 */
$provinces = getProvinceCode();
//printArray($provinces);

/* 遍歷每一個省,獲取下屬的市 */
foreach ($provinces as $provinceKey => $province)
{
    //作你想作的事情
    if (!isset($province['href']))
    {
        continue;
    }

    if ($getLevel < CITY_CLASS)
    {
        continue;
    }

    /* 市 */
    $citys = getAreaCode($province['href'], CITY_CLASS);
    //printArray($citys);
    foreach ($citys as $cityKey => $city)
    {
        //作你想作的事情
        if (!isset($city['href']))
        {
            continue;
        }
        if ($getLevel < LEVEL_COUNTY)
        {
            continue;
        }
        /* 區縣 */
        $countys = getAreaCode($city['href'], COUNTY_CLASS);
        //printArray($countys);
        foreach ($countys as $countyKey => $county)
        {
            //作你想作的事情
            if (!isset($county['href']))
            {
                continue;
            }
            if ($getLevel < LEVEL_TOWN)
            {
                continue;
            }

            $towns = getAreaCode($county['href'], TOWN_CLASS, sprintf("%02d", $province['code']));
            //printArray($towns);
            foreach ($towns as $townKey => $town)
            {
                //作你想作的事情
                if (!isset($town['href']))
                {
                    continue;
                }
                if ($getLevel < LEVEL_VILLAGE)
                {
                    continue;
                }

                $villages = getAreaCode($town['href'], VILLAGE_CLASS, sprintf("%02d", $province['code']), substr($city['code'], 2, 2));
                //printArray($villages);exit;
                foreach ($villages as $villageKey => $village)
                {
                    //作你想作的事情
                }
            }
        }
    }
}

      執行該腳本須要的時間比較長,須要採用命令行的形式執行,若是獲取到鎮這一級別,差很少須要40分鐘(和具體的電腦配置及其網絡也有關係),我沒有完整的獲取過村這個級別的數據。 github

      在遍歷的過程當中能夠將數據寫到文件、數據等一系列操做,這個按照我的須要增長便可。 網絡

相關文章
相關標籤/搜索