您的位置:首页 > 其它

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

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

在各种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;

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

在遍历的过程中可以将数据写到文件、数据等一系列操作,这个按照个人需要增加即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: