程序中查询一个IP地址的归属地信息,方法有很多种。概括起来有两类:
-
调用某些网站提供的web api接口
好处是显而易见的,使用便捷,开发成本低,自己不需要维护IP地址信息库。坏处也很明显,受制于人,服务说停就停。
-
自己编程,查询本地的IP地址信息库
这种方式完全自主,使用起来没有任何限制。不过需要自己维护IP地址信息库,起码每年更新几次还是有必要的。国内最常用的IP地址信息库就是纯真IP地址信息库了。
下载网站1:http://www.cz88.net 下载网站2:http://www.crsky.com/soft/2611.html
需要注意的是,虽然php可以直接访问qqwry.dat文件进行查询,但是如果查询比较频繁的话,建议还是采用使用C编写成的qqwry.so这样的php扩展模块效率更高。在Linux下很容易进行安装。具体可以参照http://www.open-open.com/lib/view/open1334717267889.html
还有一种做法是使用数据库维护一个IP地址信息库。难点主要是如果拿到一份正确的数据库(去淘宝上买?哪里有官方的?)以及从哪里获取IP信息的更新。
对于小规模应用,最便捷的做法显然是调用新浪,淘宝等现成的接口。大不了把几个接口都写到程序里,一个接口失败了,就尝试调用另外一个接口,这样应该能大大增强程序的可靠性。
本想整理一下各种接口的调用,发现网上已经有人整理的很好了,直接引用了: http://www.lanrensc.com/Web-Lessons/PHP/329.shtml
<?php
//获取当前用户的ip
$ip = get_client_ip();
echo "您的IP地址: $ip <br/><br/>";
echo " 例子1:调用新浪接口获取客户端IP地址信息<br/>";
echo "============================<br/>";
$url = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=".$ip;
$result = file_get_contents($url);
//var_dump(json_decode($result));
$ip_info = json_decode($result);
echo "ret: " . $ip_info->ret . "<br />";
echo "start: " . $ip_info->start . "<br />";
echo "end: " . $ip_info->end . "<br />";
echo "country: " . $ip_info->country . "<br />";
echo "province: " . $ip_info->province . "<br />";
echo "city: " . $ip_info->city . "<br />";
echo "district: " . $ip_info->district . "<br />";
echo "isp: " . $ip_info->isp . "<br />";
echo "desc: " . $ip_info->desc . "<br />";
echo "============================<br/>";
echo "<br/>";
echo "例子2:调用淘宝接口获取客户端IP地址信息<br/>";
echo "============================<br/>";
$url = "http://ip.taobao.com/service/getIpInfo.php?ip=".$ip;
$result = file_get_contents($url);
//var_dump(json_decode($result));
$ip_info = json_decode($result);
if((string)$ip_info->code=='0'){
$info = $ip_info->data;
echo "country: " . $info->country . "<br />";
echo "country_id: " . $info->country_id ."<br />";
echo "area: " . $info->area . "<br />";
echo "area_id: " . $info->area_id . "<br />";
echo "region: " . $info->region . "<br />";
echo "region_id: " . $info->region_id . "<br />";
echo "city: " . $info->city . "<br />";
echo "city_id: " . $info->city_id . "<br />";
echo "county: " . $info->county . "<br />";
echo "county_id: " . $info->county_id . "<br />";
echo "isp: " . $info->isp . "<br />";
echo "isp_id: " . $info->isp_id . "<br />";
echo "ip: " . $info->ip . "<br />";
}
echo "============================<br/>";
echo "<br/>";
echo " 例子3:查询本地qqwry.dat文件<br/>";
echo "============================<br/>";
// 调用查询qqwry.dat的函数
$ip_info = query_qqwry($ip);
// 注意:qqwry文字编码位GB2312,这里转成UTF-8格式
$ip_info = iconv("GB2312","UTF-8",$ip_info) ;
echo "IP地址数据库(QQIP地址)V2013.08.25纯真版:" . $ip_info . "<br/>";
echo "============================<br/>";
//获取用户真实IP
function get_client_ip() {
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);
}
// 查询本地qqwry.dat文件
function query_qqwry($ip) {
$ip1num = 0;
$ip2num = 0;
$ipAddr1 ="";
$ipAddr2 ="";
// 修改为qqwry.dat的正确路径
$dat_path = '/www/libs/qqwry/qqwry.dat';
if(!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
return 'IP Address Error';
}
if(!$fd = @fopen($dat_path, 'rb')){
return 'IP date file not exists or access denied';
}
$ip = explode('.', $ip);
$ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
$DataBegin = fread($fd, 4);
$DataEnd = fread($fd, 4);
$ipbegin = implode('', unpack('L', $DataBegin));
if($ipbegin < 0) $ipbegin += pow(2, 32);
$ipend = implode('', unpack('L', $DataEnd));
if($ipend < 0) $ipend += pow(2, 32);
$ipAllNum = ($ipend - $ipbegin) / 7 + 1;
$BeginNum = 0;
$EndNum = $ipAllNum;
while($ip1num>$ipNum || $ip2num<$ipNum) {
$Middle= intval(($EndNum + $BeginNum) / 2);
fseek($fd, $ipbegin + 7 * $Middle);
$ipData1 = fread($fd, 4);
if(strlen($ipData1) < 4) {
fclose($fd);
return 'System Error';
}
$ip1num = implode('', unpack('L', $ipData1));
if($ip1num < 0) $ip1num += pow(2, 32);
if($ip1num > $ipNum) {
$EndNum = $Middle;
continue;
}
$DataSeek = fread($fd, 3);
if(strlen($DataSeek) < 3) {
fclose($fd);
return 'System Error';
}
$DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
fseek($fd, $DataSeek);
$ipData2 = fread($fd, 4);
if(strlen($ipData2) < 4) {
fclose($fd);
return 'System Error';
}
$ip2num = implode('', unpack('L', $ipData2));
if($ip2num < 0) $ip2num += pow(2, 32);
if($ip2num < $ipNum) {
if($Middle == $BeginNum) {
fclose($fd);
return 'Unknown';
}
$BeginNum = $Middle;
}
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(1)) {
$ipSeek = fread($fd, 3);
if(strlen($ipSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipSeek = implode('', unpack('L', $ipSeek.chr(0)));
fseek($fd, $ipSeek);
$ipFlag = fread($fd, 1);
}
if($ipFlag == chr(2)) {
$AddrSeek = fread($fd, 3);
if(strlen($AddrSeek) < 3) {
fclose($fd);
return 'System Error';
}
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0))
$ipAddr2 .= $char;
$AddrSeek = implode('', unpack('L', $AddrSeek.chr(0)));
fseek($fd, $AddrSeek);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
} else {
fseek($fd, -1, SEEK_CUR);
while(($char = fread($fd, 1)) != chr(0))
$ipAddr1 .= $char;
$ipFlag = fread($fd, 1);
if($ipFlag == chr(2)) {
$AddrSeek2 = fread($fd, 3);
if(strlen($AddrSeek2) < 3) {
fclose($fd);
return 'System Error';
}
$AddrSeek2 = implode('', unpack('L', $AddrSeek2.chr(0)));
fseek($fd, $AddrSeek2);
} else {
fseek($fd, -1, SEEK_CUR);
}
while(($char = fread($fd, 1)) != chr(0)){
$ipAddr2 .= $char;
}
}
fclose($fd);
if(preg_match('/http/i', $ipAddr2)) {
$ipAddr2 = '';
}
$ipaddr = "$ipAddr1 $ipAddr2";
$ipaddr = preg_replace('/CZ88.NET/is', '', $ipaddr);
$ipaddr = preg_replace('/^s*/is', '', $ipaddr);
$ipaddr = preg_replace('/s*$/is', '', $ipaddr);
if(preg_match('/http/i', $ipaddr) || $ipaddr == '') {
$ipaddr = 'Unknown';
}
return $ipaddr;
}
?>