php处理IP转城市功能,可复用

说明:

1、先通过百度ip转城市接口获取到数据,再保存数据库,下次再查询就可以直接查询缓存了。

2、使用这种方式就可以通过第三方库边访问过程中边边自建自己的ip城市数据库。

3、建议3-5年清一下数据库,再重新获取最新数据,因为ip的变动性会造成准确性的问题。

效果如图

准确率取决于第二方库(百度、高德地图的数据)

 

步骤如下:

一、数据库

自建IP城市库

CREATE TABLE `ad_city_ipv2` (
  `ID` int NOT NULL AUTO_INCREMENT,
  `start_ip` double DEFAULT NULL,
  `end_ip` double DEFAULT NULL,
  `province` varchar(255) DEFAULT NULL,
  `city` varchar(255) DEFAULT NULL,
  `isp` varchar(255) DEFAULT NULL,
  `start_ip1` varchar(255) DEFAULT NULL,
  `end_ip1` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `idx_startip1` (`start_ip1`),
  KEY `idx_startipendip` (`start_ip`,`end_ip`)
) ENGINE=InnoDB AUTO_INCREMENT=114630 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=DYNAMIC COMMENT='自建IP城市库';

二、后端代码

public function getDataWithIp($ip){
        if($ip == 'Unknow'){
            return array('province'=>'', 'city'=>'');
        }
        $_ip = sprintf("%u", ip2long($ip));
        $ipcache = Mem::get('user_ip2long_'.$_ip);
        if($ipcache === false){
            $sql = "SELECT province,city FROM `".$this->table."` WHERE start_ip <= ? AND end_ip >= ?  Limit 5";
            $pd = $this->createCommand($sql);
            $pd->execute(array($_ip,$_ip));
            $rs = $pd->fetchAll(PDO::FETCH_ASSOC);
            $ipcache = array();
            if(!empty($rs)){
                foreach($rs as $v){
                    $province = $v['province'];
                    if(strpos($v['city'], '/') !== false){
                        $pos = mb_strpos($v['city'], '/', 0, 'utf8');
                        $city = mb_substr($v['city'], 0, $pos, 'utf-8');
                        break;
                    }elseif(strpos($v['city'], '(') !== false){
                        $pos = mb_strpos($v['city'], '(', 0, 'utf8');
                        if($pos > 0){
                            $city = mb_substr($v['city'], 0, $pos, 'utf-8');
                            break;
                        }
                    }elseif($v['city'] === null){
                        continue;
                    }else{
                        $city = $v['city'];
                        break;
                    }
                }
                $ipcache['province'] = $province;
                $ipcache['city'] = isset($city) ? $city : '';
            }else{
                $ip_section3_start = $_ip - $_ip%256;
                $ip_section3_end = $ip_section3_start + 255;

                $url = 'http://api.map.baidu.com/location/ip?ak=avG2C8Mqh6RqB7SVpx1KgNqLG1NEsxyf&coor=bd09ll&ip='.$ip;
                $result = file_get_contents($url);
                $_result = json_decode($result, true);
                Tool::log2(LOG_PATH."getDataWithIp.txt", $_result, $ip);
                if($_result['status'] == 0){
                    $ipcache['province'] = self::processWholeProvince($_result['content']['address_detail']['province']);
                    $ipcache['city'] = !empty($ipcache['province'])?$_result['content']['address_detail']['city']:'';

                    if($ipcache['province'] && $ipcache['city']) {
                        $insert_data = array(
                            "start_ip" => $ip_section3_start,
                            "end_ip" => $ip_section3_end,
                            "province" => $ipcache['province'],
                            "city" => $ipcache['city'],
                            "isp" => '',
                            "start_ip1" => long2ip($ip_section3_start),
                            "end_ip1" => long2ip($ip_section3_end),
                        );
                        // Tool::log2(LOG_PATH."getDataWithIp.txt", $insert_data, $ip);
                        $this->insert($insert_data);
                    }else{
                        $ipcache['province'] = '';
                        $ipcache['city'] = '';
                    }
                }else{
                    $ipcache['province'] = '';
                    $ipcache['city'] = '';
                }
                Tool::log2(LOG_PATH."getDataWithIp.txt", [$_ip, $ipcache], $ip);
            }

            //把诸如"广州市"后面的市字去掉,统一
            if(!empty($ipcache['province'])){
                $province_city = include(ROOT_PATH."/configs/province_city.config.inc.php");
                $cityStr = $province_city[$ipcache['province']];
                $cityArr = explode('|', $cityStr);
                if(!empty($ipcache['city'])){
                    $simple_city = mb_substr($ipcache['city'], 0, 2, 'utf-8');
                    foreach($cityArr as $v){
                        if(strpos($v, $simple_city) !== false){
                            $_tmp['city'] = $v;
                            break;
                        }
                    }
                    empty($_tmp['city']) && $_tmp['city'] = '';
                }else{
                    $_tmp['city'] = '';
                }
            }else{
                $_tmp['city'] = '';
            }
            $ipcache['city'] = $_tmp['city'];
            Mem::set('user_ip2long_'.$_ip, $ipcache, 300);
        }

        if(empty($ipcache['province']) || empty($ipcache['city'])) {
            Tool::log2(LOG_PATH."getDataWithIp.txt", [$ipcache], $ip);
        }
        
        return $ipcache;
    }

province_city.config.inc.php

<?php
return array(
'北京'=>'北京|东城|西城|朝阳|丰台|石景山|海淀|门头沟|房山|通州|顺义|昌平|大兴|平谷|怀柔|密云|延庆',
'天津'=>'天津|和平|河东|河西|南开|河北|红桥|滨海新区|东丽|西青|津南|北辰|宁河|武清|静海|宝坻|蓟县',
'河北'=>'石家庄|唐山|秦皇岛|邯郸|邢台|保定|张家口|承德|沧州|廊坊|衡水',
'山西'=>'太原|大同|阳泉|长治|晋城|朔州|晋中|运城|忻州|临汾|吕梁',
'内蒙古'=>'呼和浩特|包头|乌海|赤峰|通辽|鄂尔多斯|呼伦贝尔|巴彦淖尔|乌兰察布|兴安|锡林郭勒|阿拉善',
'辽宁'=>'沈阳|大连|鞍山|抚顺|本溪|丹东|锦州|营口|阜新|辽阳|盘锦|铁岭|朝阳|葫芦岛', 
'吉林'=>'长春|吉林|四平|辽源|通化|白山|松原|白城|延边', 
'黑龙江'=>'哈尔滨|齐齐哈尔|鸡西|鹤岗|双鸭山|大庆|伊春|佳木斯|七台河|牡丹江|黑河|绥化|大兴安岭', 
'上海'=>'上海|黄浦|卢湾|徐汇|长宁|静安|普陀|闸北|虹口|杨浦|闵行|宝山|嘉定|浦东新区|金山|松江|奉贤|青浦|崇明',
'江苏'=>'南京|无锡|徐州|常州|苏州|南通|连云港|淮安|盐城|扬州|镇江|泰州|宿迁', 
'浙江'=>'杭州|宁波|温州|嘉兴|湖州|绍兴|金华|衢州|舟山|台州|丽水', 
'安徽'=>'合肥|芜湖|蚌埠|淮南|马鞍山|淮北|铜陵|安庆|黄山|滁州|阜阳|宿州|巢湖|六安|亳州|池州|宣城', 
'福建'=>'福州|厦门|莆田|三明|泉州|漳州|南平|龙岩|宁德', 
'江西'=>'南昌|景德镇|萍乡|九江|新余|鹰潭|赣州|吉安|宜春|抚州|上饶', 
'山东'=>'济南|青岛|淄博|枣庄|东营|烟台|潍坊|济宁|泰安|威海|日照|莱芜|临沂|德州|聊城|滨州|菏泽', 
'河南'=>'郑州|开封|洛阳|平顶山|安阳|鹤壁|新乡|焦作|濮阳|许昌|漯河|三门峡|南阳|商丘|信阳|周口|驻马店|济源', 
'湖北'=>'武汉|黄石|十堰|宜昌|襄阳|鄂州|荆门|孝感|荆州|黄冈|咸宁|随州|恩施|仙桃|潜江|天门|神农架', 
'湖南'=>'长沙|株洲|湘潭|衡阳|邵阳|岳阳|常德|张家界|益阳|郴州|永州|怀化|娄底|湘西', 
'广东'=>'广州|韶关|深圳|珠海|汕头|佛山|江门|湛江|茂名|肇庆|惠州|梅州|汕尾|河源|阳江|清远|东莞|中山|潮州|揭阳|云浮', 
'广西'=>'南宁|柳州|桂林|梧州|北海|防城港|钦州|贵港|玉林|百色|贺州|河池|来宾|崇左', 
'海南'=>'海口|三亚|五指山|琼海|儋州|文昌|万宁|东方|定安|屯昌|澄迈|临高|白沙|昌江|乐东|陵水|保亭|琼中|西沙|南沙|中沙', 
'重庆'=>'重庆|万州|涪陵|渝中|大渡口|江北|沙坪坝|九龙坡|南岸|北碚|两江新区|万盛|双桥|渝北|巴南|长寿|綦江|潼南|铜梁|大足|荣昌|璧山|梁平|城口|丰都|垫江|武隆|忠县|开县|云阳|奉节|巫山|巫溪|黔江|石柱|秀山|酉阳|彭水|江津|合川|永川|南川', 
'四川'=>'成都|自贡|攀枝花|泸州|德阳|绵阳|广元|遂宁|内江|乐山|南充|眉山|宜宾|广安|达州|雅安|巴中|资阳|阿坝|甘孜|凉山', 
'贵州'=>'贵阳|六盘水|遵义|安顺|铜仁|黔西南|毕节|黔东南|黔南', 
'云南'=>'昆明|曲靖|玉溪|保山|昭通|丽江|普洱|临沧|楚雄|红河|文山|西双版纳|大理|德宏|怒江|迪庆', 
'西藏'=>'拉萨|昌都|山南|日喀则|那曲|阿里|林芝', 
'陕西'=>'西安|铜川|宝鸡|咸阳|渭南|延安|汉中|榆林|安康|商洛', 
'甘肃'=>'兰州|嘉峪关|金昌|白银|天水|武威|张掖|平凉|酒泉|庆阳|定西|陇南|临夏|甘南', 
'青海'=>'西宁|海东|海北|黄南|海南|果洛|玉树|海西', 
'宁夏'=>'银川|石嘴山|吴忠|固原|中卫', 
'新疆'=>'乌鲁木齐|克拉玛依|吐鲁番|哈密|昌吉|博尔塔拉|巴音郭楞|阿克苏|克孜勒苏|喀什|和田|伊犁|塔城|阿勒泰|石河子|阿拉尔|图木舒克|五家渠'
);

?>
public static function processWholeProvince($p){
        $array = array(
                '北京市'=>'北京',
                '天津市'=>'天津',
                '河北省'=>'河北',
                '山西省'=>'山西',
                '内蒙古自治区'=>'内蒙古',
                '辽宁省'=>'辽宁',
                '吉林省'=>'吉林',
                '黑龙江省'=>'黑龙江',
                '上海市'=>'上海',
                '江苏省'=>'江苏',
                '浙江省'=>'浙江',
                '安徽省'=>'安徽',
                '福建省'=>'福建',
                '江西省'=>'江西',
                '山东省'=>'山东',
                '河南省'=>'河南',
                '湖北省'=>'湖北',
                '湖南省'=>'湖南',
                '广东省'=>'广东',
                '广西壮族自治区'=>'广西',
                '海南省'=>'海南',
                '重庆市'=>'重庆',
                '四川省'=>'四川',
                '贵州省'=>'贵州',
                '云南省'=>'云南',
                '西藏自治区'=>'西藏',
                '陕西省'=>'陕西',
                '甘肃省'=>'甘肃',
                '青海省'=>'青海',
                '宁夏回族自治区'=>'宁夏',
                '新疆维吾尔自治区'=>'新疆',
                '香港特别行政区'=>'香港',
                '澳门特别行政区'=>'澳门',
                '台湾省'=>'台湾'
            );
        return !empty($array[$p])?$array[$p]:'';
    }

其他解决方案:

可以使用QQ的早期开源的纯真数据库脚本,准确性也很高。具体方案可以网上搜索一下。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值