设为首页 收藏本站
查看: 657|回复: 0

[经验分享] [智能架构系列]PHP获取用户IP所在地的信息

[复制链接]

尚未签到

发表于 2015-8-29 09:26:03 | 显示全部楼层 |阅读模式
//update 20120418

更新添加了淘宝的IP库,GET请求返回的是json

http://ip.taobao.com/service/getIpInfo.php?ip=121.127.205.7

这个推荐使用。



//update 20120112

本篇文章所涉及到的代码已经更新到了 http://code.google.com/p/buddy/ 项目中了,大家可以从这个项目中获取代码。

Buddy 你身边的伙伴, 旨在减少我们开发者的工作,让我们有更多的时间来学感兴趣的技术,让我们有更多的时间来陪陪家人!



最近发现百度提供的API已经下线了,无法从API中获取地域信息了,很是郁闷,只有依赖于纯真IP库了。以下贴出代码和方法,希望对大家有所帮助

这个需要下载存在IP库,然后将在构造方法里面修改文件所在的位置就好了




<?php
// +----------------------------------------------------------------------
// | Buddy Framework
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://buddy.woshimaijia.com/ All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: xinqiyang <xinqiyang@gmail.com>
// +----------------------------------------------------------------------

/**
*  IP location Query class
*  <code>
*  $ip = Iplocation::instance();
*    $r = $ip->getlocation('123.120.1.160');
*    </code>
*   
*/
class Iplocation
{
    /**
     * QQWry.Dat file point
     *
     * @var resource
     */
    private $fp;
    /**
     * first ip
     *
     * @var int
     */
    private $firstip;
    /**
     * last address
     *
     * @var int
     */
    private $lastip;
    /**
     * total ip count
     *
     * @var int
     */
    private $totalip;
    /**
     * construct
     *
     * @param string $filename
     * @return IpLocation
     */
    public function __construct($filename='QQWry.Dat') {
        $this->fp = 0;
        if (($this->fp = fopen(dirname(__FILE__).DIRECTORY_SEPARATOR.'Resource/'.$filename, 'rb')) !== false) {
            $this->firstip = $this->getlong();
            $this->lastip = $this->getlong();
            $this->totalip = ($this->lastip - $this->firstip) / 7;
        }
    }
    /**
     * getlong
     *
     * @access private
     * @return int
     */
    private function getlong() {
        $result = unpack('Vlong', fread($this->fp, 4));
        return $result['long'];
    }
    /**
     * return 3 bit
     * @access private
     * @return int
     */
    private function getlong3() {
        $result = unpack('Vlong', fread($this->fp, 3).chr(0));
        return $result['long'];
    }
    /**
     * return packip address
     *
     * @access private
     * @param string $ip
     * @return string
     */
    private function packip($ip) {
        return pack('N', intval(ip2long($ip)));
    }
    /**
     * return read string
     *
     * @access private
     * @param string $data
     * @return string
     */
    private function getstring($data = "") {
        $char = fread($this->fp, 1);
        while (ord($char) > 0) {        // string store use c formate use \0 end
            $data .= $char;             // link the string
            $char = fread($this->fp, 1);
        }
        return $data;
    }
    /**
     * return area info
     *
     * @access private
     * @return string
     */
    private function getarea() {
        $byte = fread($this->fp, 1);   
        switch (ord($byte)) {
            case 0:                    
                $area = "";
                break;
            case 1:
            case 2:                     
                fseek($this->fp, $this->getlong3());
                $area = $this->getstring();
                break;
            default:                 
                $area = $this->getstring($byte);
                break;
        }
        return $area;
    }
    /**
     * return ip location info
     * $r['contry']  $r['area']
     * @access public
     * @param string $ip
     * @return array
     */
    public function getlocation($ip='') {
        if (!$this->fp) return null;         
        if(empty($ip)) $ip = getip();
        $location['ip'] = gethostbyname($ip);  
        $ip = $this->packip($location['ip']);
        $l = 0;                        
        $u = $this->totalip;           
        $findip = $this->lastip;      
        while ($l <= $u) {
            $i = floor(($l + $u) / 2);
            fseek($this->fp, $this->firstip + $i * 7);
            $beginip = strrev(fread($this->fp, 4));
            if ($ip < $beginip) {
                $u = $i - 1;
            }
            else {
                fseek($this->fp, $this->getlong3());
                $endip = strrev(fread($this->fp, 4));
                if ($ip > $endip) {
                    $l = $i + 1;
                }
                else {
                    $findip = $this->firstip + $i * 7;
                    break;
                }
            }
        }
        fseek($this->fp, $findip);
        $location['beginip'] = long2ip($this->getlong());
        $offset = $this->getlong3();
        fseek($this->fp, $offset);
        $location['endip'] = long2ip($this->getlong());
        $byte = fread($this->fp, 1);
        switch (ord($byte)) {
            case 1:
                $countryOffset = $this->getlong3();
                fseek($this->fp, $countryOffset);
                $byte = fread($this->fp, 1);
                switch (ord($byte)) {
                    case 2:
                        fseek($this->fp, $this->getlong3());
                        $location['country'] = $this->getstring();
                        fseek($this->fp, $countryOffset + 4);
                        $location['area'] = $this->getarea();
                        break;
                    default:
                        $location['country'] = $this->getstring($byte);
                        $location['area'] = $this->getarea();
                        break;
                }
                break;
            case 2:
                fseek($this->fp, $this->getlong3());
                $location['country'] = $this->getstring();
                fseek($this->fp, $offset + 8);
                $location['area'] = $this->getarea();
                break;
            default:
                $location['country'] = $this->getstring($byte);
                $location['area'] = $this->getarea();
                break;
        }
        if ($location['country'] == " CZ88.NET") {
            $location['country'] = "Unknow";
        }
        if ($location['area'] == " CZ88.NET") {
            $location['area'] = "";
        }
        //change gbk to utf8
        $location['country'] = mb_convert_encoding($location['country'], 'UTF8','GBK');
        $location['area'] = mb_convert_encoding($location['area'], 'UTF8','GBK');
        return $location;
    }
   
    /**
     * excute complete then close file handler
     *
     */
    public function __destruct() {
        if ($this->fp) {
            fclose($this->fp);
        }
        $this->fp = 0;
    }
   
}



最近项目中用到了获取用户IP所在地的信息,主要是为了从IP去判断用户所在的城市,现在的城市信息基本上有分几种

一种是用ID编号来关联城市的,还有使用缩写的代码来关联城市的。



我们通过IP去获取所在的用户的  城市的详细信息,比如运行以下的结果得到的是 "福建省福州市 电信"

可以得到用户的 省市及所使用的网络接入的信息



这里调用的是百度的开放查询接口,通过网页的方式去查询然后从返回的结果中去匹配我们所需要的信息,效果还行,代码在下面,还是能凑合着用的。






var_dump(getAddress('202.101.98.54','福州'));
function getAddress($ip=null,$address='') {
$url = "http://open.baidu.com/ipsearch/s?wd={$ip}&tn=baiduip";
$res = mb_convert_encoding(HttpRequest($url), 'UTF-8', 'GBK');
//var_dump($res);
if ( preg_match('#来自:<b>(.+)</b>#Ui', $res, $m) ) {
if (is_int(strpos($m[1], $address))) {
return $m[1];
}
}
}

function HttpRequest($url, $data=array()) {
$ch = curl_init();
if (is_array($data) && $data) {
$formdata = http_build_query($data);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formdata);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
return curl_exec($ch);
}

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-105767-1-1.html 上篇帖子: php动态创建表单 下篇帖子: nginx php空白页 fastcgi_param
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表