经过两天下班时间的弯弯绕绕,终于实现了在评论区展示用户归属地的功能,在此记录分享一下。
修改主题functions
首先在主题functions.php文件中添加以下代码。
/** * 根据百度IP查询接口获取IP所在地 */
function getCity($ip) {
//百度api的接口
$url = "https://opendata.baidu.com/api.php?query=".$ip."&co=&resource_id=6006&format=json&oe=utf8";
$ip=json_decode(file_get_contents($url),true);
$out = "<div class='comment-useragent'>";
if($ip['status']=='0'){
$out .= "<i class='fa fa-globe'; style='color:blue';></i>" ." ".$ip['data'][0]['location'];
/* 如果想使用自定义图标库,可以把上面的“$out .=”后面的内容替换成以下代码,在按自定义图标部分的内容进行操作
$out .= $GLOBALS['UA_ICON']['City2'] ." ".$ip['data'][0]['location'];
*/
}else{
return false;
}
$out .= "</div>";
return apply_filters("argon_comment_ua_icon", $out);
}
在functions.php中定位到以下代码位置
echo parse_ua_and_icon($comment -> comment_agent);
在这段代码后面添加如下内容,以调用上面定义的功能块。
<?php
echo getCity(get_comment_author_ip());
?>
自定义图标
找到useragent-parser.php文件,在最后添加以下代码,用于在归属地前添加图标。
$GLOBALS['UA_ICON']['City2'] = '<svg >……</svg>';
上述代码里的”<svg >……</svg>“,替换成自己下载的svg代码,格式可参照useragent-parser.php文件的原有内容。
解析
下面的代码是百度的IP归属地在线查询API返回的JSON结果(已将真实IP隐去)。
{
"status": "0",
"t": "",
"set_cache_time": "",
"data": [
{
"ExtendedLocation": "",
"OriginQuery": "123.123.123.123",
"appinfo": "",
"disp_type": 0,
"fetchkey": "123.123.123.123",
"location": "福建省福州市 电信",
"origip": "123.123.123.123",
"origipquery": "123.123.123.123",
"resourceid": "6006",
"role_id": 0,
"shareImage": 1,
"showLikeShare": 1,
"showlamp": "1",
"titlecont": "IP地址查询",
"tplt": "ip"
}
]
}
返回结果中,status=0表示请求成功,但是不表示有数据返回,data集合不为空才表示查询成功。
根据以上,可知代码作用如下:
设置API接口参数;format:设置返回结果的格式,支持json,xml,json。
$url = "https://opendata.baidu.com/api.php?query=".$ip."&co=&resource_id=6006&format=json&oe=utf8";
判断请求是否成功,若请求不成功,则不显示归属地。
if($ip['status']=='0')
{
……
}else{
return false;
}
$out .= "<i class='fa fa-globe'; style='color:blue';></i>" ." ".$ip['data'][0]['location'];
返回的JSON结果中”data”里的地理位置,需要根据不同API返回的JSON结果修改“$ip”之后的部分。
离线IP归属地接口
在网络上搜寻的时候也看到了一个使用纯真IP数据库作为离线IP归属地接口的方法:WordPress获取真实IP,以及将IP转换成归属地,来自 Gimhoy’s Blog,搬运在此进行一个记录!
调用QQ IP数据库
纯真IP数据库也就是QQ IP数据库纯真版,收集了包括中国电信、中国网通、长城宽带、网通宽带、聚友宽带等 ISP 的 IP 地址数据。
使用方法:百度下载QQ IP数据库纯真版,将其中的QQWry.Dat放入主题目录下。然后在当前主题下的functions.php中加入以下代码
//IP转地址
function convertip($ip) {
$dat_path = TEMPLATEPATH.'/QQWry.Dat';
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';
}
$ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr);
if( $ipaddr != ' ' )
return $ipaddr;
else
$ipaddr = '地址未知!火星来客?';
return $ipaddr;
}
使用的时候调用这个函数即可。
调用IP归属地函数
将IP转换成归属地在WordPress中的应用:在评论列表/后台评论列表/评论通知邮件中显示评论者IP所在地
在主题目录下的functions.php中,找到评论列表,大概搜get_comment_author_link()即可,在合适的位置加上下面的代码:
<?php if ( is_user_logged_in() ) echo convertip(get_comment_author_ip()); //回复者所在地及网络 ?>
这里用到了《WordPress获取真实IP,以及将IP转换成归属地》中创建的convertip函数,如果用的是其他的IP地址转换函数,修改一下代码中的函数名称即可。如果没有转换IP的函数,请先加入,方法见上文。
淘宝API接口
以下是网上找的淘宝IP归属地API接口代码,以及相关说明
/* 淘宝API,不对个人开放
$url="https://ip.taobao.com/outGetIpInfo?ip=".$ip;
$ip=json_decode(file_get_contents($url));
if((string)$ip->code=='4'){
return "个人qps超出";
}
$data = (array)$ip->data;
return $data;
*/
1. 请求接口(GET,POST):
/outGetIpInfo?ip=[ip地址字串]&accessKey=[访问密匙]
2. 响应信息:
(json格式的)国家 、省(自治区或直辖市)、市(县)、运营商
3. 返回数据格式:
{“code”:0,”data”:{“ip”:”210.75.225.254″,”country”:”\u4e2d\u56fd”,”area”:”\u534e\u5317″,
淘宝IP地址库接口说明
“region”:”\u5317\u4eac\u5e02″,”city”:”\u5317\u4eac\u5e02″,”county”:””,”isp”:”\u7535\u4fe1″,
“country_id”:”86″,”area_id”:”100000″,”region_id”:”110000″,”city_id”:”110000″,
“county_id”:”-1″,”isp_id”:”100017″}}
其中code的值的含义为,0:成功,1:服务器异常,2:请求参数异常,3:服务器繁忙,4:个人qps超出。
由于自己不太懂PHP语法,以及没有认真研究Argon主题的逻辑结构,在添加的时候也经过了一些失败。但是,最重要的是,一开始没注意到使用的IP归属地在线查询API (ip.taobao.com)是无效的、是已不对个人开放的!导致我一直以为是我插入的方式不对,(;´༎ຶД༎ຶ`) 。
厉害