评论者添加IP地址归属地信息

首页 代码865 字
评论者添加IP地址归属地信息
首页代码865 字

  最近,百度、微博、抖音、知乎、小红书都上线了评论IP属地功能,国内显示到省份/地区,国外显示到国家,且用户无法关闭该功能。



  我这几天有时间折腾,决定跟上这个风,加上这个功能,我的博客是Typecho搭建的,目前测试两种方式都可以实现:一个是调用百度、太平洋、淘宝这些网站的api,问题是影响网站加载速度;第二个是利用本地数据库,这个就快了很多。
所以我用的第二种利用纯真IP数据库。

具体效果如下



具体操作如下

第一种方法

这里使用太平洋网络IP地址查询web接口
参数有三个
第一个是ip,这个从评论表就能拿到
第二个是level,这个是用来设置输出精度的,=1/=2/=3分别代表只输出省名称/输出省市名称/输出省市区名称
第三个就是domId,用来指定结点ID

然后就开始了
首先找到现在使用的主题的评论展示的代码,这个根据主题不同位置也不一样,我的这个在主题文件夹comments.php文件中
然后再需要的地方加上一个的标签,这个标签id需要是该条评论的id,前缀可以随便加一个以便区分
最后再标签后面加上js脚本,脚本的url参数中需要注意:level根据需要自定义,domId和上面标签的id一样,ip则是该条评论的ip。

<span class="t-g">来自<span id="ip-<?php $comments->theId();?>"></span></span>
<script src="https://whois.pconline.com.cn/jsDom.jsp?level=1&domId=ip-<?php $comments->theId(); ?>&ip=<?php echo $comments->ip; ?>"></script>

博客主题的head中加上no-referrer的标签

<meta name="referrer" content="no-referrer"/>

效果如图

请输入图片描述


第二种方法

将下面代码放入主题的functions.php文件中,可插入在最尾部。
代码

/** 获取评论者地址 */
function convertip($ip){  
  $ip1num = 0; 
  $ip2num = 0; 
  $ipAddr1 =""; 
  $ipAddr2 =""; 
  $dat_path = './qqwry.dat';         
  if(!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {  
    return 'IP 数据库路径不对';  
  }   
  if(!$fd = @fopen($dat_path, 'rb')){  
    return 'IP 数据库路径不正确';  
  }   
  $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 = '可能来自火星';  
  }
  $ipaddr = iconv('gbk', 'utf-8//IGNORE', $ipaddr); 
  return $ipaddr;  
}


下载QQWry.Dat放在网站根目录,注意是网站根目录!

下载

  

打开主题评论模板comments.php文件,在您想显示的位置加上如下代码:

<?php echo convertip($comments->ip); ?> 

Typecho配置CDN后获取访客真实IP地址可能会受到影响,请在Typecho站点根目录里的config.inc.php添加下面这段代码即可。有的虚拟主机会自带CDN,所以哪怕没有配置CDN,只要不能正常显示,也可以尝试插入以下代码。

//绕过 CDN 代理IP获取客户真实IP地址
if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
$list = explode(',',$_SERVER['HTTP_X_FORWARDED_FOR']);
$_SERVER['REMOTE_ADDR'] = $list[0];
}

效果如图

请输入图片描述

作者:云帆沧海

链接:https://yf-ch.com/archives/1951.html

版权:除特别声明,均采用 BY-NC-SA 4.0 许可协议,转载请表明出处。


云帆沧海
一个持续更新的个人博客,记录生活、工作、爱好的点点滴滴。
赞赏
OωO
开启隐私评论,您的评论仅作者和评论双方可见
评论 ( 31 )
  1. 此条为私密评论,仅评论双方可见
    2022年10月31日 · 山东省 回复
    1. 云帆沧海 博主大人
      @Qicloud

      嗯嗯

      2022年10月31日 · 河北省 回复
  2. 如果 是IPV6的地址呢?

    2022年10月31日 · 湖南省 回复
    1. 云帆沧海 博主大人
      @chenmo

      暂不支持

      2022年10月31日 · 河北省 回复
  3. 时间

    2022年10月31日 · 辽宁省 回复
    1. 云帆沧海 博主大人
      @风记星辰

      刚把操作方法整理出来

      2022年10月31日 · 河北省 回复
  4. 试试看我的坐标

    2022年08月17日 · 湖南省 回复
    1. @Guangran

      闪现

      2022年08月17日 · 江西省 回复
  5. 晚风

    老哥可以解答一下php代码怎么解析到省吗,我在网上看到的都是全部解析了,那段代码我看了很久不知道怎么修改,只让他解析到省份

    2022年08月11日 · 广东省 回复
    1. 云帆沧海 博主大人
      @晚风

      只显示地区,不显示后面的网络请把$ipaddr = "$ipAddr1 $ipAddr2";改为$ipaddr = "$ipAddr1";即可。至于如何只显示省份或者国家,可以使用 strpos()来匹配文字并截断返回就可以了

      2022年08月11日 · 河北省 回复
      1. 晚风
        @云帆沧海

        感谢老哥提供的思路,我也不判断了,直接截断3个字符去了, $ipaddr = substr($ipaddr,0,9);

        2022年08月11日 · 广东省 回复
  6. 话说这个博客主题是老哥自己写的吗 真的好看

    2022年08月09日 · 山东省 回复
    1. 云帆沧海 博主大人
      @xmmmmmovo

      不是,别人的简单修改了下

      2022年08月09日 · 河北省 回复
  7. 测试测试~

    2022年08月09日 · 山东省 回复
  8. 河北 前来报道!

    2022年07月23日 · 河北省 回复
    1. 云帆沧海 博主大人
      @Net

      欢迎

      2022年07月23日 · 河北省 回复
  9. 跟你的风,我也搞了一个

    2022年07月17日 · 江苏省 回复
    1. 云帆沧海 博主大人
      @HELLOYOSI

      挺好

      2022年07月17日 · 河北省 回复
  10. 这个得支持下!

    2022年07月06日 · 北京市 回复