使用PHP,根据访客的IP地址获取城市位置。方法有很多中,目前最简单的是通过腾讯的API接口:http://fw.qq.com/ipaddress ;可以获得形如 var IPData = new Array(“ip地址”,”",”所在省”,”所在市”);的数据,从而可以通过javascript在客户端调用,应用于各种场合。不过这个API只能支持javascript,例如网上的什么通过PHP的方法从腾讯API获取城市的做法,经本人验证,是无效的,原因很简单,腾讯的API不支持代理访问。
求人不如求己,我自己做了个IP获取城市API数据接口。代码同样是使用PHP来实现,透过纯真IP数据库的支持,可以精确地定位城市位置。支持多种查询方式形如:本机IP、自定义IP、自定义域名三种方式。
http://domain/ip 直接查询本机IP所在城市位置
http://domain/ip/?q=xxx.xxx.xxx.xxx 获取自定义IP的城市位置
http://domain/ip/?q=baidu.com 获取域名所在的城市位置
代码如下:
<?php
function
convertip(
$ip
) {
//IP数据文件路径
$dat_path
=
'QQWry.Dat'
;
//检查IP地址
if
(!filter_var(
$ip
, FILTER_VALIDATE_IP)) {
return
'IP Address Error'
;
}
//打开IP数据文件
if
(!
$fd
= @
fopen
(
$dat_path
,
'rb'
)){
return
'IP date file not exists or access denied'
;
}
//分解IP进行运算,得出整形数
$ipNum
=
ip2long
(
$ip
);
//获取IP数据索引开始和结束位置
$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
;
//使用二分查找法从索引记录中搜索匹配的IP记录 while($ip1num>$ipNum || $ip2num<$ipNum) {
$Middle
=
intval
((
$EndNum
+
$BeginNum
) / 2);
//偏移指针到索引位置读取4个字节
fseek
(
$fd
,
$ipbegin
+ 7 *
$Middle
);
$ipData1
=
fread
(
$fd
, 4);
if
(
strlen
(
$ipData1
) < 4) {
fclose(
$fd
);
return
'System Error'
;
}
//提取出来的数据转换成长整形,如果数据是负数则加上2的32次幂
$ip1num
= implode(
''
, unpack(
'L'
,
$ipData1
));
if
(
$ip1num
< 0)
$ip1num
+= pow(2, 32);
//提取的长整型数大于我们IP地址则修改结束位置进行下一次循环 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
;
}
header(
"Content-type: text/html; charset=utf-8"
);
$ip
=
$_SERVER
[
'HTTP_X_FORWARDED_FOR'
];
if
(isset(
$_GET
[
'q'
])){
$ip
=
$_GET
[
'q'
];
if
(filter_var(
"http://"
.
$ip
,FILTER_VALIDATE_URL,FILTER_FLAG_HOST_REQUIRED)){
$ip
=
gethostbyname
(
$ip
);
}
}
echo
"$ip,"
.mb_convert_encoding(convertip(
$ip
),
"utf-8"
,
"gb2312"
);
?>