码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-06-24 16:55:42      阅读:208      评论:0      收藏:0      [点我收藏+]

标签:

      在各种WEB应用中,会填写个人或者企业的地址信息,如下图所示,是京东上填写收货地址的页面截图。

技术分享

      小弟最近也碰到了类似的问题,需要得到所有省份,每个省份下属的市区,没事市区下属的县、乡镇、村这些数据。这方面的数据最权威的莫过于国家统计局(http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2013/index.html)给出的统计,目前国家统计局给出的最新数据是截止到2013年8月13日的数据,没有香港、澳门特别行政区,没有钓鱼岛,没有三沙市,也没有台湾,如果需要可以单独加上,如下图所示:

技术分享

      小弟借助simple_html_dom.php(可在https://github.com/samacs/simple_html_dom下载)这个库完成页面的抓取和解析,在这里,将代码和大家来分享一下。

<?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分钟(和具体的电脑配置及其网络也有关系),我没有完整的获取过村这个级别的数据。

      在遍历的过程中可以将数据写到文件、数据等一系列操作,这个按照个人需要增加即可。

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

标签:

原文地址:http://my.oschina.net/ricky716/blog/470228

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!