各级(省市县镇村)行政区域获取

      在各类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

      在遍历的过程当中能够将数据写到文件、数据等一系列操做,这个按照我的须要增长便可。 网络

相关文章
相关标签/搜索