我们相信:世界是美好的,你是我也是。平行空间的世界里面,不同版本的生活也在继续...

伴随着中国互联网的发展史,从当年的显IPQQ开始,大名鼎鼎的纯真数据库qqwry,就伴随着中国人的网络史而存在。当年的木子QQ,珊瑚虫QQ,后来的DZ论坛等等,都有qqwry的存在,这个数据库的名称是怎么来的,无从得知。qqwry.dat是谁维护的也不知晓。不过可以肯定的是:qqwry.dat应该是当年做站必备利器。

苏南大叔:纯真IP库最新版哪里下载?如何使用PHP解析纯真ip? - 纯真ip的php解析方式
纯真IP库最新版哪里下载?如何使用PHP解析纯真ip?(图2-1)

废话背景分析

最近,苏南大叔想做个ip相关的判断,所以就又想起了它。百度了一番,发现它居然有个官方站,

界面呢,以最新的网络观来说,略low。似乎有些苍白的感觉。不管如何,界面上面有个明显的下载按钮。点击之后,令我意外的是,居然是个exe。说好的dat文件呢?好吧,可能在exe里面包含着呢。不情愿的安装了exe后,果然在目录下面发现了期待的qqwry.dat。看着exe的界面上有个“升级”的按钮的份上,就保留了exe。嘿嘿,没准哪天还真心升级下呢。

苏南大叔:纯真IP库最新版哪里下载?如何使用PHP解析纯真ip? - qqwry
纯真IP库最新版哪里下载?如何使用PHP解析纯真ip?(图2-2)

然后百度个PHP解析的代码吧,发现了个大名鼎鼎的dz的,试了一下。貌似有问题,似乎其中的正则部分,有问题。而苏南大叔最不喜欢正则了,所以直接过了。然后又百度到了大名鼎鼎的thinkphp的作者liu21st的作品。马上膜拜一下下。下载回来试试,果然赞。

php解析代码

下面贴出苏南大叔修改过的@liu21st的ip代码解析,稍稍修改了下逻辑,能清楚的标识出国家是中国的情况,并且添加上了丢失的函数。大家喜欢就拿走好了。

class IpLocation {
    private $fp;
    private $firstip;
    private $lastip;
    private $totalip;
    public function __construct($filename = "data/qqwry.dat") {
        $this->fp = 0;
        if (($this->fp = fopen(dirname(__FILE__) . '/' . $filename, 'rb')) !== false) {
            $this->firstip = $this->getlong();
            $this->lastip = $this->getlong();
            $this->totalip = ($this->lastip - $this->firstip) / 7;
        }
    }
    private function getlong() {
        //将读取的little-endian编码的4个字节转化为长整型数
        $result = unpack('Vlong', fread($this->fp, 4));
        return $result['long'];
    }
    private function getlong3() {
        $result = unpack('Vlong', fread($this->fp, 3) . chr(0));
        return $result['long'];
    }
    private function packip($ip) {
        return pack('N', intval(ip2long($ip)));
    }
    private function getstring($data = "") {
        $char = fread($this->fp, 1);
        while (ord($char) > 0) {
            $data .= $char;
            $char = fread($this->fp, 1);
        }
        return $data;
    }
    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;
    }
    private $provinces = array("黑龙江省", "辽宁省", "吉林省", "河北省", "河南省", "湖北省", "湖南省", "山东省", "山西省", "陕西省","安徽省", "浙江省", "江苏省", "福建省", "广东省", "海南省", "四川省", "云南省", "贵州省", "青海省", "甘肃省","江西省", "台湾省", "内蒙古", "宁夏", "新疆", "西藏", "广西", "北京市", "上海市", "天津市", "重庆市", "香港", "澳门");
    public function getlocation($ip = '') {
        if (!$this->fp)
            return null;
        if (empty($ip))
            $ip = get_client_ip();
        $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 (trim($location['country']) == 'CZ88.NET') {
            $location['country'] = '未知';
        }
        if (trim($location['area']) == 'CZ88.NET') {
            $location['area'] = '';
        }
        $location['country'] = @iconv('gbk', 'utf-8', $location['country']);
        $location['area'] = @iconv('gbk', 'utf-8', $location['area']);
        foreach ($this->provinces as $v) {
            if (strpos($location['country'], $v) === 0) {
                $location['province'] = $v;
                $location['city'] = str_replace($v, '', $location['country']);
                break;
            }
        }
        if (empty($location['province']))
            $location['province'] = $location['country'];
        if (empty($location['city']))
            $location['city'] = $location['country'];
        //sunan moify
        if (in_array($location['province'], $this->provinces)) {
            $location['country'] = "中国";
        }
        return $location;
    }
    public function __destruct() {
        if ($this->fp) {
            fclose($this->fp);
        }
        $this->fp = 0;
    }
}
function get_client_ip() {
    if (getenv('HTTP_CLIENT_IP')) {
        $onlineip = getenv('HTTP_CLIENT_IP');
    } elseif (getenv('HTTP_X_FORWARDED_FOR')) {
        $onlineip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif (getenv('REMOTE_ADDR')) {
        $onlineip = getenv('REMOTE_ADDR');
    } else {
        $onlineip = $HTTP_SERVER_VARS['REMOTE_ADDR'];
    }
    return $onlineip;
}

header("Content-type: text/html; charset=utf-8");
$new = new IpLocation();
$ip = $new->getlocation();
//$ip = $new->getlocation("114.249.231.28");
print_r($ip);

结束语

更多php文章,请点击下面的链接:

如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留作者链接。

 【福利】 腾讯云最新爆款活动!1核2G云服务器首年50元!

 【源码】本文代码片段及相关软件,请点此获取更多信息

 【绝密】秘籍文章入口,仅传授于有缘之人   php    IP