在各類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
在遍歷的過程當中能夠將數據寫到文件、數據等一系列操做,這個按照我的須要增長便可。 網絡