本文目录导读:

在PHP项目中解析地址并拆分为省/市/区字段,常见有以下几种方案:
使用正则表达式(简单场景)
适用于格式比较规范的地址:
function parseAddress($address) {
$pattern = '/(?P<province>[^省]+省|新疆|西藏|内蒙古|广西|宁夏|北京|天津|上海|重庆)(?P<city>[^市]+市|自治州|地区|盟)(?P<district>[^区]+区|县|市|旗|自治县)/u';
preg_match($pattern, $address, $matches);
return [
'province' => $matches['province'] ?? '',
'city' => $matches['city'] ?? '',
'district' => $matches['district'] ?? '',
'detail' => str_replace([$matches['province'] ?? '', $matches['city'] ?? '', $matches['district'] ?? ''], '', $address)
];
}
// 使用示例
$address = "广东省广州市天河区天河路123号";
$result = parseAddress($address);
print_r($result);
基于行政区划字典库(推荐方案)
1 准备行政区划数据
// provinces.php - 省级数据
$provinces = [
'北京', '天津', '上海', '重庆',
'河北', '山西', '辽宁', '吉林',
'黑龙江', '江苏', '浙江', '安徽',
'福建', '江西', '山东', '河南',
'湖北', '湖南', '广东', '广西',
'海南', '四川', '贵州', '云南',
'西藏', '陕西', '甘肃', '青海',
'宁夏', '新疆', '台湾', '香港', '澳门'
];
// cities.php - 市级数据(部分示例)
$cities = [
'广州', '深圳', '珠海', '汕头',
'佛山', '韶关', '湛江', '肇庆',
// ... 完整数据可购买或使用公开数据集
];
2 实现解析函数
class AddressParser {
private $provinces;
private $provinceMap;
private $cityMap;
public function __construct() {
$this->provinces = [
'北京', '天津', '上海', '重庆',
'河北省', '山西省', '辽宁省',
// ... 完整数据
];
$this->initMaps();
}
private function initMaps() {
// 建立别名映射
$this->provinceMap = [
'北京' => '北京市', '上海' => '上海市',
'广东' => '广东省', '广州' => '广东省',
// ... 更多映射
];
$this->cityMap = [
'广州' => '广州市', '深圳' => '深圳市',
'北京区' => '北京市', // 部分特殊处理
];
}
public function parse($address) {
$result = [
'province' => '',
'city' => '',
'district' => '',
'detail' => $address
];
// 1. 提取省份
$result['province'] = $this->extractProvince($address);
// 2. 提取城市
$result['city'] = $this->extractCity($address, $result['province']);
// 3. 提取区县
$result['district'] = $this->extractDistrict($address);
// 4. 清理详细地址
$result['detail'] = $this->cleanDetail($address, $result);
return $result;
}
private function extractProvince($address) {
// 匹配"省"或特殊直辖市
foreach ($this->provinceMap as $keyword => $province) {
if (strpos($address, $keyword) !== false) {
return $province;
}
}
return '';
}
private function extractCity($address, $province = '') {
// 根据省份缩小范围查找
if ($province) {
// 从已知城市库中匹配
$cities = $this->getCitiesByProvince($province);
foreach ($cities as $city) {
if (strpos($address, $city) !== false) {
return $city;
}
}
}
// 通用匹配
$pattern = '/([^市]+市)/u';
preg_match($pattern, $address, $matches);
return $matches[1] ?? '';
}
private function extractDistrict($address) {
$pattern = '/([^区]+区|[^县]+县|[^市]+市)/u';
preg_match($pattern, $address, $matches);
return $matches[1] ?? '';
}
private function cleanDetail($address, $parsed) {
$replacements = array_filter([
$parsed['province'],
$parsed['city'],
$parsed['district']
]);
foreach ($replacements as $part) {
$address = str_replace($part, '', $address);
}
return trim($address);
}
}
// 使用示例
$parser = new AddressParser();
$address = "广东省广州市天河区体育西路123号";
$result = $parser->parse($address);
print_r($result);
使用第三方API服务(最准确)
class AddressApiParser {
private $apiKey;
public function __construct($apiKey) {
$this->apiKey = $apiKey;
}
public function parse($address) {
// 使用百度地图API示例
$url = "https://api.map.baidu.com/geocoding/v3/";
$params = [
'address' => $address,
'output' => 'json',
'ak' => $this->apiKey
];
$response = $this->curlGet($url, $params);
$data = json_decode($response, true);
if ($data['status'] == 0) {
$components = $data['result']['addressComponent'];
return [
'province' => $components['province'],
'city' => $components['city'],
'district' => $components['district'],
'detail' => str_replace(
[$components['province'], $components['city'], $components['district']],
'',
$address
)
];
}
return null;
}
private function curlGet($url, $params) {
$url .= '?' . http_build_query($params);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
}
// 使用示例
$apiKey = 'your_baidu_api_key';
$parser = new AddressApiParser($apiKey);
$result = $parser->parse("广东省广州市天河区体育西路123号");
综合推荐方案
class SmartAddressParser {
private $apiParser;
private $localParser;
public function __construct($apiKey = null) {
$this->localParser = new AddressParser();
if ($apiKey) {
$this->apiParser = new AddressApiParser($apiKey);
}
}
public function parse($address) {
// 优先使用本地解析(快速且无需API调用)
$result = $this->localParser->parse($address);
// 如果本地解析不完整,使用API
if (empty($result['province']) && $this->apiParser) {
$apiResult = $this->apiParser->parse($address);
if ($apiResult) {
$result = $apiResult;
}
}
return $result;
}
}
// 使用
$parser = new SmartAddressParser('your_api_key');
$addresses = [
"广东省广州市天河区天河路123号",
"北京市朝阳区建国路88号",
"上海市浦东新区陆家嘴金融贸易区"
];
foreach ($addresses as $address) {
$result = $parser->parse($address);
echo "原地址: {$address}\n";
echo "省: {$result['province']}\n";
echo "市: {$result['city']}\n";
echo "区: {$result['district']}\n";
echo "详细: {$result['detail']}\n\n";
}
注意事项
-
特殊地区处理:
- 直辖市(北京、上海等)
- 自治州、地区
- 省直辖县级市
- 新疆兵团等特殊行政区划
-
性能考虑:
- 本地解析快速但准确率较低
- API解析准确但依赖网络且可能有费用
-
数据更新:
- 行政区划会变动,需要定期更新数据
- 关注民政部发布的行政区划调整通知
建议根据项目需求选择合适的方案,对于电商、物流等对准确性要求高的场景,推荐使用API方案或结合字典库的混合方案。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播