根据 IP 获取省市名称
根据 ip
获取地理定位,曾尝试了 laravel
的torann/geoip
包,不是很准确。还可以 百度 API
调用获取地理信息的方法。本文介绍两种方法,一种是 tp3.2.3
中的一个包,另一种是组件 zoujingli/ip2region
1
thinkphp3.2
中的一个包,是否是tp框架自带的不很清楚。这个包获取定位的原理是内置了省市数据库 UTFWry.dat
。
laravel 项目如何使用
我放在了项目 app
同级目录 sdk
下。为了能够使用,composer.json
中需将 IpLocation.class.php
添加到 classmap
自动加载中,以便该文件中包含的类能够在被调用时被自动加载(如果不太明白为何能自动加载,参考 Laravel Composer 自动加载原理)。
"autoload": {
"classmap": [
"database/seeds",
"database/factories",
"sdk/Org/Net/IpLocation.class.php"
]
},
添加后执行 composer dump-autoload
基本使用
$ip = new \Org\Net\IpLocation('UTFWry.dat');
$location = $ip->getlocation('223.104.1.100');
dd($location);
1. 标准返回值
我们拿 广东深圳 的 ip 做示例
# 打印结果
array:5 [
"ip" => "223.104.1.100"
"beginip" => "223.104.1.0"
"endip" => "223.104.1.255"
"country" => "广东省深圳市"
"area" => "移动"]
2. 个别地区返回值有所不同,左侧为示范ip,右侧为返回地区名称
# 直辖市
'223.104.3.155',//北京市
'223.104.7.155',//天津市
'223.104.25.155',//重庆市
'223.104.5.200',//上海市徐汇区
# 自治区
'223.104.15.100',//内蒙古呼和浩特市
'223.104.29.100',//宁夏银川市
'223.104.30.100',//新疆乌鲁木齐市
'211.139.74.100',//西藏拉萨市
'218.204.63.100',//广西百色市
'1.32.192.100',//香港
'60.246.49.100',//澳门
封装一个返回地区id的方法函数
经常使用的话,一般喜欢放在 app\Helpers.php
中,
<?php
function get_ip_location($ip){
$ip_driver = new \Org\Net\IpLocation('UTFWry.dat');
$location = $ip_driver->getlocation($ip);
$location = $location['country']; //广东省深圳市
// 如果没有查询到的默认返回值
$default = ['p_id'=>1,'c_id'=>0,'locname'=>'北京'];
// 如果有市 那么市后边的字符删除 只保留到市
$city_strpos = mb_strpos($location, '市');
if($city_strpos){
$location = mb_substr($location, 0, $city_strpos + 1);
}
// 如果是直辖市,若匹配到直接返回,不继续匹配 “区”
$spacial = ['北京','上海','天津','重庆'];//北京市/天津市/重庆市/上海市徐汇区
foreach ($spacial as $bj) {
if( strpos($location, $bj) !== false ){
$province_name = $bj;
$province_id = DB::table('loc_province')->where('name',$province_name)->value('province_id');
return ['p_id'=>$province_id,'c_id'=>0,'locname'=>$bj.'市'];
}
}
// 其他标准查询
$expect_ids = [36,37,38,39,69]; //排除北京、、以及想要排除的地区
$province_name = $city_name = ''; //初始化
$province_id = $city_id = 0;
// 所有省数据
$all_province = DB::table('loc_province')->whereNotIn('id', $expect_ids)->get();
foreach ($all_province as $prov) {
$name = $prov->name;
$prov_pos = mb_strpos($location, $name);
// 如果匹配到目标
if( $prov_pos !== false ){
$province_id = $prov->province_id;
$province_name = $name;
// 从字符串中去除省名称,并把省字去掉
$location = mb_substr($location, $prov_pos + mb_strlen($name));
$location = str_replace('省','',$location);
// 如果有“市”,那么就提取出市的名称
if($location && mb_strpos($location, '市')){
$city_name = rtrim($location, '市');
}
if($city_name){
$city_id = DB::table('loc_city')->where('name',$city_name)->value('cid');
}else{
$city_id = 1; // 默认省会
}
break;
}
}
if($province_name){
return ['p_id'=>$province_id,'c_id'=>$city_id,'locname'=>$province_name.$city_name];
}else{
return $default;
}
}
2. zoujingli/ip2region
function get_ip_region($ip){
$ip2region = new \Ip2Region();
$ip_info = $ip2region->btreeSearch($ip);
$ip_arr = explode('|',$ip_info['region']);
$province_name = str_replace('省','',$ip_arr[2]);
$city_name = str_replace('市','',$ip_arr[3]);
$province_id = DB::table('province')->where('name',$province_name)->value('province_id');
if(!$province_id){
return ['p_id'=>1,'c_id'=>0,'locname'=>'北京','ip'=>$ip];
}
$spacial = ['北京','上海','天津','重庆'];//北京市/天津市/重庆市/上海市徐汇区
if(in_array($province_name, $spacial)){
return ['p_id'=>$province_id,'c_id'=>0,'locname'=>$province_name,'ip'=>$ip];
}
if($city_name){
$db_city_id = DB::table('city')->where('name',$city_name)->value('cid');
$city_id = $db_city_id;
}else{
$city_id = 1;
$city_name = DB::table('city')->where('cid',$city_id)->value('name');
}
return ['p_id'=>$province_id,'c_id'=>$city_id,'locname'=>$city_name,'ip'=>$ip];
}
测试
$testips = [
'223.104.3.155',//北京市
'223.104.7.155',//天津市
'223.104.25.155',//重庆市
'223.104.5.200',//上海市徐汇区
'223.104.15.100',//内蒙古呼和浩特市
'223.104.29.100',//宁夏银川市
'223.104.30.100',//新疆乌鲁木齐市
'211.139.74.100',//西藏拉萨市
'218.204.63.100',//广西百色市
'1.32.192.100',//香港
'60.246.49.100',//澳门
'223.104.1.100', //广东省深圳市
];
echo "<pre>";
foreach ($testips as $ip) {
print_r(get_ip_location($ip));
}
检查结果
Array
(
[p_id] => 1
[c_id] => 0
[locname] => 北京市
)
Array
(
[p_id] => 3
[c_id] => 0
[locname] => 天津市
)
Array
(
[p_id] => 4
[c_id] => 0
[locname] => 重庆市
)
Array
(
[p_id] => 2
[c_id] => 0
[locname] => 上海市
)
Array
(
[p_id] => 7
[c_id] => 1
[locname] => 内蒙古呼和浩特
)
Array
(
[p_id] => 29
[c_id] => 1
[locname] => 宁夏银川
)
Array
(
[p_id] => 31
[c_id] => 1
[locname] => 新疆乌鲁木齐
)
Array
(
[p_id] => 26
[c_id] => 1
[locname] => 西藏拉萨
)
Array
(
[p_id] => 21
[c_id] => 13
[locname] => 广西百色
)
Array
(
[p_id] => 32
[c_id] => 1
[locname] => 香港
)
Array
(
[p_id] => 33
[c_id] => 1
[locname] => 澳门
)
Array
(
[p_id] => 20
[c_id] => 2
[locname] => 广东深圳
)
END
本作品采用《CC 协议》,转载必须注明作者和本文链接
ip和地区的对应关系是一直变化的
如果用这个包,那么UTFWry.dat文件也要更新吧?
用这个 他不香吗 gitee.com/lionsoul/ip2region
IP是动态IP,时间长了,就失效了