本文目录导读:

在PHP项目中拆分省市区街道地址,有几种常见的方法:
使用正则表达式(简单场景)
function splitAddress($address) {
$pattern = '/(?<province>[^省]+省|[^自治区]+自治区|北京|天津|上海|重庆)';
$pattern .= '(?<city>[^市]+市|[^自治州]+自治州|地区|区划)';
$pattern .= '(?<district>[^区]+区|[^县]+县|[^旗]+旗)';
$pattern .= '(?<street>.+)?/';
preg_match($pattern, $address, $matches);
return [
'province' => $matches['province'] ?? '',
'city' => $matches['city'] ?? '',
'district' => $matches['district'] ?? '',
'street' => $matches['street'] ?? ''
];
}
使用地址分词库(推荐)
安装 jieba-php(如果是纯PHP项目)
composer require fukuball/jieba-php
使用示例
require_once '/path/to/vendor/autoload.php';
use Fukuball\Jieba\Jieba;
use Fukuball\Jieba\Finalseg;
class AddressParser {
private $jieba;
private $provinceCityDict;
public function __construct() {
Jieba::init();
Finalseg::init();
// 预加载省市区词典
$this->provinceCityDict = $this->loadAddressDictionary();
}
private function loadAddressDictionary() {
return [
'provinces' => ['北京', '天津', '上海', '重庆', '河北省', '山西省', ...],
'cities' => ['石家庄市', '唐山市', '秦皇岛市', ...],
'districts' => ['长安区', '桥西区', '新华区', ...]
];
}
public function parse($address) {
$segments = Jieba::cut($address, true);
$result = [
'province' => '',
'city' => '',
'district' => '',
'street' => ''
];
foreach ($segments as $segment) {
if ($this->isProvince($segment)) {
$result['province'] = $segment;
} elseif ($this->isCity($segment)) {
$result['city'] = $segment;
} elseif ($this->isDistrict($segment)) {
$result['district'] = $segment;
} else {
$result['street'] .= $segment;
}
}
return $result;
}
}
使用第三方API服务
高德地图API
function parseAddressWithAMap($address) {
$apiKey = 'your_api_key';
$url = "https://restapi.amap.com/v3/geocode/geo?key={$apiKey}&address=" . urlencode($address);
$response = file_get_contents($url);
$data = json_decode($response, true);
if ($data['status'] == '1' && !empty($data['geocodes'])) {
$geocode = $data['geocodes'][0];
return [
'province' => $geocode['province'] ?? '',
'city' => $geocode['city'] ?? '',
'district' => $geocode['district'] ?? '',
'formatted_address' => $geocode['formatted_address'] ?? ''
];
}
return null;
}
完整的分词工具类
class AddressSplitter {
private $provinceKeywords = ['省', '自治区', '直辖市'];
private $cityKeywords = ['市', '自治州', '地区'];
private $districtKeywords = ['区', '县', '县级市', '旗'];
public function split($address) {
$address = trim($address);
// 处理直辖市
if ($this->isMunicipality($address)) {
return $this->handleMunicipality($address);
}
$result = [
'province' => '',
'city' => '',
'district' => '',
'street' => $address
];
// 提取省份
$provinceEnd = $this->findKeywordEnd($address, $this->provinceKeywords);
if ($provinceEnd !== false) {
$result['province'] = substr($address, 0, $provinceEnd);
$address = substr($address, $provinceEnd);
}
// 提取城市
$cityEnd = $this->findKeywordEnd($address, $this->cityKeywords);
if ($cityEnd !== false) {
$result['city'] = substr($address, 0, $cityEnd);
$address = substr($address, $cityEnd);
}
// 提取区县
$districtEnd = $this->findKeywordEnd($address, $this->districtKeywords);
if ($districtEnd !== false) {
$result['district'] = substr($address, 0, $districtEnd);
$address = substr($address, $districtEnd);
}
$result['street'] = trim($address);
return $result;
}
private function findKeywordEnd($text, $keywords) {
foreach ($keywords as $keyword) {
$pos = mb_strpos($text, $keyword);
if ($pos !== false) {
return $pos + mb_strlen($keyword);
}
}
return false;
}
private function isMunicipality($address) {
$municipalities = ['北京', '天津', '上海', '重庆'];
foreach ($municipalities as $municipality) {
if (mb_strpos($address, $municipality) === 0) {
return true;
}
}
return false;
}
private function handleMunicipality($address) {
$result = [
'province' => '',
'city' => '',
'district' => '',
'street' => ''
];
// 提取直辖市名称
if (mb_strpos($address, '北京市') === 0) {
$result['province'] = '北京市';
$result['city'] = '北京市';
$address = substr($address, 9); // 去掉"北京市"
} elseif (mb_strpos($address, '天津市') === 0) {
// 类似处理
}
// ... 处理其他直辖市
return $result;
}
}
// 使用示例
$splitter = new AddressSplitter();
$address = "河北省石家庄市长安区中山路100号";
$result = $splitter->split($address);
print_r($result);
数据库方案
创建地址词典表并查询:
CREATE TABLE address_dictionary (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
level ENUM('province', 'city', 'district', 'street') NOT NULL,
parent_id INT DEFAULT NULL
);
-- 查询示例
SELECT name FROM address_dictionary
WHERE level = 'province'
AND POSITION(name IN ?) > 0;
建议
- 简单项目:使用正则表达式或自定义规则
- 中等项目:使用结巴分词 + 地址词典
- 高精度需求:使用高德、百度等地图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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播