php基于纯真IP数据库实现IP地址信息查询

php基于纯真IP数据库实现IP地址信息查询

最近在学习php,记录下这个php基于纯真IP数据库实现IP地址信息查询的实现方法。

注意:这个模块纯真ip数据库需要离线下载,不然的话访问会出错!!!文章结尾会附上最新的纯真ip数据库。

部分参考博主——孟坤博客

这里还增加了访客浏览器,系统,自动获取访客ip功能的实现!!

后续更新:增加了显示时间,天气,温度,以及历史上的今天功能!!

#显示效果

#也可以通过访问查看效果——传送门

#首先先新建一个IPQuery.class.php文件

<?php

header("Conten-type:text/html;charset=utf-8");
class IPQuery{
private $fh; //ip数据库文件句柄
private $first;//第一条索引
private $last;//最后一台哦索引
private $total;//总索引
private $dbfile = __DIR__ . DIRECTORY_SEPARATOR . 'qqwry.dat'; //数据库文件存放位置 其中_DIR_表示当前脚本路径,DIRECTORY_SEPARATOR在php中统一为反斜杠\
private $dbExpires=86400*10; //数据库文件有效期10天,如果无需自动更新,则设置为0
//构造函数
function _construct(){
//ip 数据库文件不存在或者过期,则自动获取
if(!file_exists($this->dbfile)||($this->dbExpires&&((time()-filetime($this->dbfile))>$this->dbExpires))){
$this->update();
}

}
//忽略超时
private function ignore_timeout(){
@ignore_user_abort(true);//设置客户端断开连接时是否中断脚本的执行
@ini_set('max_execution_time',48*60*60);//为一个配置选项设置值
@set_time_limit(48*60*60);//设置脚本最大执行时间 这里设置了两天
@ini_set('memory_limit','4000M');//4G

}
//读取小端little-endian编码的4个字节转化为长整型数
private function getLong4(){
$result=unpack('Vlong',fread($this->fh,4));
return $result['long'];
}
//读取小断little-endian编码的3个字节转化为长整型数
private function getLong3(){
$result=unpack('Vlong',fread($this->fh,3).chr(0));
return $result['long'];
}
//查询位置信息
private function getPos($data=''){
$char=fread($this->fh,1);
while(ord($char)!=0){//ord()返回字符串的第一个字符的ascii码值
//地区信息以0结束
$data.=$char;
$char=fread($this->fh,1);

}
return $data;
}
//查询运营商
private function getISP(){
$byte=fread($this->fh,1);//标记字节
switch(ord($byte)){
case 0:$area='';break;//为0时结束,没有信息
case 1://被重定向
fseek($this->fh,$this->getLong3());//在文件指针中定位
$area=$this->getPos();break;
case 2://被重定向
fseek($this->fh,$this->getLong3());//在文件指针中定位
$area=$this->getPos();break;
default:$area=$this->getPos($byte);break;//没有被重定向

}
return $area;
}
//检查ip格式是否正确
public function checkIp($ip){
$arr=explode('.',$ip);//使用.来分割ip
if(count($arr)!=4)return false;
for($i=0;$i<4;$i++){
if($arr[$i]<'0'||$arr[0]>'255'){
return false;
}
}
return true;

}
//查询ip
public function query($ip){
if(!$this->checkIp($ip)){
return false;
}
$this->fh=fopen($this->dbfile,'rb');
$this->first=$this->getLong4();
$this->last=$this->getLong4();
$this->total=($this->last-$this->first)/7;//每条索引占7个字节
$ip=pack('N',intval(ip2long($ip)));//intval获取变量的整数值,ip2long将一个IPV4的字符串互联网协议转换成数字格式

//二分查找ip位置
$l=0;
$r=$this->total;
while($l<$r){
$m=floor(($l+$r)/2);
fseek($this->fh,$this->first+$m*7);
$beginip=strrev(fread($this->fh,4));//中间索引的开始ip地址,strrev进行反转字符串
fseek($this->fh,$this->getLong3());
$endip=strrev(fread($this->fh,4));//中间索引的结束ip地址

if($ip<$beginip){
//用户的ip小于中间索引的结束ip地址时,右边应该更新为左边-1
$r=$m-1;
}
else{
if($ip>$endip)
{
//用户ip大于中间索引的结束ip地址时,更新后的索引位置应为m+1
$l=$m+1;
}
else
{
//用户ip在中间索引的ip范围内
$findip=$this->first+$m*7;
break;
}
}

}
//查找ip地址段
fseek($this->fh,$findip);
$location['beginip']=long2ip($this->getLong4());//用户ip所在范围的开始地址
$offset=$this->getLong3();
fseek($this->fh,$offset);
$location['endip']=long2ip($this->getLong4());//用户ip所在范围的结束位置

//查找ip信息
$byte=fread($this->fh,1);//标志字节
switch(ord($byte)){
case 1://都被重定向
$countryOffset=$this->getLong3();//重定向地址
fseek($this->fh,$countryOffset);
$byte=fread($this->fh,1);//标志字节
switch(ord($byte)){
case 2://信息被二次重定向
fseek($this->fh,$this->getLong3());
$location['pos']=$this->getPos();
fseek($this->fh,$countryOffset+4);
$location['isp']=$this->getISP();
break;
default://信息没有被二次重定向
$location['pos']=$this->getPos($byte);
$location['isp']=$this->getISP();
break;
}
break;

case 2://信息被重定向
fseek($this->fh,$this->getLong3());
$location['pos']=$this->getPos();
fseek($this->fh,$offset+8);
$location['isp']=$this->getISP();
break;

default://信息没有被重定向
$location['pos']=$this->getPos($byte);
$location['isp']=$this->getISP();
break;

}

//信息转码处理
foreach($location as $k=>$v){
$location[$k]=iconv('gb2312','utf-8',$v);//字符串按要求的字符编码来转换,这里转化为utf-8编码
$location[$k] = preg_replace(array('/^.*CZ88\.NET.*$/isU', '/^.*纯真.*$/isU', '/^.*日IP数据/'), '', $location[$k]);//利用正则搜索替换
$location[$k]=htmlspecialchars($location[$k]);//吧预定义的字符"<"和">"转化为html实体

}
return $location;

}

//更新数据库
public function update(){
$this->ignore_timeout();
$copywrite=file_get_contents('http://update.cz88.net/ip/copywrite.rar');//将这个文件读作字符串
$qqwry=file_get_contents('http://update.cz88.net/ip/qqwry.rar');
$key=unpack('V6',$copywrite)[6];
for($i=0;$i<0x200;$i++){//512
$key*=0x805;//
$key++;
$key=$key&0xFF;
$qqwry[$i]=chr(ord($qqwry[$i])^$key);
}
$qqwry=gzuncompress($qqwry);//实现字符串压缩
file_put_contents($this->dbfile,$qqwry);

}

//析构函数
function _destruct(){
if($this->fh){
fclose($this->fh);
}
$this->fp=null;
}

}

?>

#在index.php中进行调用

<?php

header("Conten-type:text/html;charset=utf-8");
require_once('IPQuery.class.php');

$ip=new IPQuery();

function getIP(){
if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) {
$ip = getenv("HTTP_CLIENT_IP");
} else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) {
$ip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) {
$ip = getenv("REMOTE_ADDR");
} else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
$ip = "unknown";
}
return ($ip);
}
function GetOs() {
if (!empty($_SERVER['HTTP_USER_AGENT'])) {
$OS = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/win/i', $OS)) {
$OS = 'Windows';
} elseif (preg_match('/mac/i', $OS)) {
$OS = 'MAC';
} elseif (preg_match('/linux/i', $OS)) {
$OS = 'Linux';
} elseif (preg_match('/unix/i', $OS)) {
$OS = 'Unix';
} elseif (preg_match('/bsd/i', $OS)) {
$OS = 'BSD';
} else {
$OS = 'Other';
}
return $OS;
} else {
return "获取访客操作系统信息失败!";
}
}

function GetBrowser() {
if (!empty($_SERVER['HTTP_USER_AGENT'])) {
$br = $_SERVER['HTTP_USER_AGENT'];
if (preg_match('/MSIE/i', $br)) {
$br = 'MSIE';
} elseif (preg_match('/Firefox/i', $br)) {
$br = 'Firefox';
} elseif (preg_match('/Chrome/i', $br)) {
$br = 'Chrome';
} elseif (preg_match('/Safari/i', $br)) {
$br = 'Safari';
} elseif (preg_match('/Opera/i', $br)) {
$br = 'Opera';
} else {
$br = 'Other';
}
return $br;
} else {
return "获取浏览器信息失败!";
}
}

$checkip=getIP();
$fkos=GetOs();
$fkgetbrowser=GetBrowser();
$addr=$ip->query($checkip);
echo "<pre>
IP起始段:{$addr['beginip']}
IP结束段:{$addr['endip']}
实际地址:{$addr['pos']}
运营商:{$addr['isp']}
操作系统:{$fkos}
浏览器:{$fkgetbrowser}
</pre>
";

?>

 

#离线纯真ip数据库下载,文件名为qqwry.dat!!!

云盘下载

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像