程序查询IP地址归属地的方法

程序中查询一个IP地址的归属地信息,方法有很多种。概括起来有两类:

  1. 调用某些网站提供的web api接口

    好处是显而易见的,使用便捷,开发成本低,自己不需要维护IP地址信息库。坏处也很明显,受制于人,服务说停就停。

  2. 自己编程,查询本地的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;
}
?>
Share Comments
comments powered by Disqus