网站评论者UA及IP转真实地址
in Skill with 4196 Views

网站评论者UA及IP转真实地址

in Skill with 4197 Views

其实这个功能在博主之前使用WORDPRESS时就用过了,不过苦于两者的调用函数还是有所区别,博主研究了半天,终于在博客上实现了此功能。

具体实现的效果可看下图。

要实现此效果共分两部分,我们一步一步来。

首先第一步先实现UA部分,在此再次感谢黑冰技术站的博主大大提供的教程

在主题模板的functions.php文件里添加以下代码。

/** 获取浏览器信息 */
function getBrowser($agent){ 

    $outputer = false;

    if (preg_match('/MSIE\s([^\s|;]+)/i', $agent, $regs)) {
        $outputer = 'IE浏览器';
    } else if (preg_match('/FireFox\/([^\s]+)/i', $agent, $regs)) {
      $str1 = explode('Firefox/', $regs[0]);
    $FireFox_vern = explode('.', $str1[1]);
        $outputer = '火狐浏览器 '. $FireFox_vern[0];
    } else if (preg_match('/Maxthon([\d]*)\/([^\s]+)/i', $agent, $regs)) {
      $str1 = explode('Maxthon/', $agent);
    $Maxthon_vern = explode('.', $str1[1]);
        $outputer = '傲游浏览器 '.$Maxthon_vern[0];
    } else if (preg_match('#SE 2([a-zA-Z0-9.]+)#i', $agent, $regs)) {
        $outputer = '搜狗浏览器';
    } else if (preg_match('#360([a-zA-Z0-9.]+)#i', $agent, $regs)) {
    $outputer = '360浏览器';
    } else if (preg_match('/Edge([\d]*)\/([^\s]+)/i', $agent, $regs)) {
        $str1 = explode('Edge/', $regs[0]);
    $Edge_vern = explode('.', $str1[1]);
        $outputer = 'Edge '.$Edge_vern[0];
    } else if (preg_match('/EdgiOS([\d]*)\/([^\s]+)/i', $agent, $regs)) {
        $str1 = explode('EdgiOS/', $regs[0]);
        $outputer = 'Edge';
    } else if (preg_match('/UC/i', $agent)) {
              $str1 = explode('rowser/',  $agent);
    $UCBrowser_vern = explode('.', $str1[1]);
        $outputer = 'UC浏览器 '.$UCBrowser_vern[0];
    }else if (preg_match('/OPR/i', $agent)) {
              $str1 = explode('OPR/',  $agent);
    $opr_vern = explode('.', $str1[1]);
        $outputer = '欧朋浏览器 '.$opr_vern[0];
    } else if (preg_match('/MicroMesseng/i', $agent, $regs)) {
        $outputer = '微信内嵌浏览器';
    }  else if (preg_match('/WeiBo/i', $agent, $regs)) {
        $outputer = '微博内嵌浏览器';
    }  else if (preg_match('/QQ/i', $agent, $regs)||preg_match('/QQBrowser\/([^\s]+)/i', $agent, $regs)) {
                  $str1 = explode('rowser/',  $agent);
    $QQ_vern = explode('.', $str1[1]);
        $outputer = 'QQ浏览器 '.$QQ_vern[0];
    } else if (preg_match('/MQBHD/i', $agent, $regs)) {
                  $str1 = explode('MQBHD/',  $agent);
    $QQ_vern = explode('.', $str1[1]);
        $outputer = 'QQ浏览器 '.$QQ_vern[0];
    } else if (preg_match('/BIDU/i', $agent, $regs)) {
        $outputer = '百度浏览器';
    } else if (preg_match('/LBBROWSER/i', $agent, $regs)) {
        $outputer = '猎豹浏览器';
    } else if (preg_match('/TheWorld/i', $agent, $regs)) {
        $outputer = '世界之窗浏览器';
    } else if (preg_match('/XiaoMi/i', $agent, $regs)) {
        $outputer = '小米浏览器';
    } else if (preg_match('/UBrowser/i', $agent, $regs)) {
              $str1 = explode('rowser/',  $agent);
    $UCBrowser_vern = explode('.', $str1[1]);
        $outputer = 'UC浏览器 '.$UCBrowser_vern[0];
    } else if (preg_match('/mailapp/i', $agent, $regs)) {
        $outputer = 'email内嵌浏览器';
    } else if (preg_match('/2345Explorer/i', $agent, $regs)) {
        $outputer = '2345浏览器';
    } else if (preg_match('/Sleipnir/i', $agent, $regs)) {
        $outputer = '神马浏览器';
    } else if (preg_match('/YaBrowser/i', $agent, $regs)) {
        $outputer = 'Yandex浏览器';
    }  else if (preg_match('/Opera[\s|\/]([^\s]+)/i', $agent, $regs)) {
        $outputer = 'Opera浏览器';
    } else if (preg_match('/MZBrowser/i', $agent, $regs)) {
        $outputer = '魅族浏览器';
    } else if (preg_match('/VivoBrowser/i', $agent, $regs)) {
        $outputer = 'vivo浏览器';
    } else if (preg_match('/Quark/i', $agent, $regs)) {
        $outputer = '夸克浏览器';
    } else if (preg_match('/mixia/i', $agent, $regs)) {
        $outputer = '米侠浏览器';
    }else if (preg_match('/fusion/i', $agent, $regs)) {
        $outputer = '客户端';
    } else if (preg_match('/CoolMarket/i', $agent, $regs)) {
        $outputer = '基安内置浏览器';
    } else if (preg_match('/Thunder/i', $agent, $regs)) {
        $outputer = '迅雷内置浏览器';
    } else if (preg_match('/Chrome([\d]*)\/([^\s]+)/i', $agent, $regs)) {
    $str1 = explode('Chrome/', $agent);
    $chrome_vern = explode('.', $str1[1]);
        $outputer = '<i class="fa fa-chrome"></i> Chrome '.$chrome_vern[0];
    } else if (preg_match('/safari\/([^\s]+)/i', $agent, $regs)) {
         $str1 = explode('Version/',  $agent);
    $safari_vern = explode('.', $str1[1]);
        $outputer = 'Safari '.$safari_vern[0];
    } else{
        return false;
    }
   return $outputer;
}

/** 获取操作系统信息 */
function getOs($agent){

    $os = false;
    
    if (preg_match('/win/i', $agent)) {
        if (preg_match('/nt 6.0/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows Vista';
        } else if (preg_match('/nt 6.1/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows 7';
        } else if (preg_match('/nt 6.2/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows 8';
        } else if(preg_match('/nt 6.3/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows 8.1';
        } else if(preg_match('/nt 5.1/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows XP';
        } else if (preg_match('/nt 10.0/i', $agent)) {
            $os = '<i class="fa fa-windows"></i> Windows 10';
        } else{
            $os = '<i class="fa fa-windows"></i> Windows';
        }
    } else if (preg_match('/android/i', $agent)) {
    if (preg_match('/android 9/i', $agent)) {
        $os = '<i class="fa fa-android"></i> Android P';
    }
    else if (preg_match('/android 8/i', $agent)) {
        $os = '<i class="fa fa-android"></i> Android O';
    }
    else if (preg_match('/android 7/i', $agent)) {
        $os = '<i class="fa fa-android"></i> Android N';
    }
    else if (preg_match('/android 6/i', $agent)) {
        $os = '<i class="fa fa-android"></i> Android M';
    }
    else if (preg_match('/android 5/i', $agent)) {
        $os = '<i class="fa fa-android"></i> Android L';
    }
    else{
        $os = '<i class="fa fa-android"></i> Android';
        }
    }
    else if (preg_match('/ubuntu/i', $agent)) {
        $os = '<i class="fa fa-linux"></i> Linux';
    } else if (preg_match('/linux/i', $agent)) {
        $os = '<i class="fa fa-linux"></i> Linux';
    } else if (preg_match('/iPhone/i', $agent)) {
        $os = '<i class="fa fa-apple"></i> iPhone';
    } else if (preg_match('/iPad/i', $agent)) {
        $os = '<i class="fa fa-apple"></i> iPad';
    } else if (preg_match('/mac/i', $agent)) {
        $os = '<i class="fa fa-OSX"></i> OSX';
    }else if (preg_match('/cros/i', $agent)) {
        $os = 'chrome os';
    }else {
    return false;
    }
   return $os;
}

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

<span class="agent"><?php echo getOs($comments->agent); ?></span>
<span class="agent"><?php echo getBrowser($comments->agent); ?></span>

至此,你的网站评论处就会出现浏览器及操作系统。注意,博主使用的是font awesome的图标,如您也想要和博主一样的效果,去font awesome官网下载图标包或直接引用其官网的BootstrapCDN即可,否则不会出现图标。

当然这只是最普通的显示效果,您也可以设置成只显示图标,鼠标放到图标上面时再显示文字等等效果。

接下来第二步,实现IP地址转换成真实地址。

其实网上的方法一共有两种,一种是利用淘宝、新浪、百度等的IP地址查询API进行查询并通过截取字段进行前台显示。第二种就是博主使用的方法,利用纯真IP数据库进行服务器本地查询。此方法的好处是速度快,坏处就是需要定期更新数据库,不过网上更新纯真数据库的教程很多,这里就不赘述了。

继续教程,将下方代码放入主题的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放在同一级目录,否则就需要修改$dat_path的数据库地址。

添加完成后,再次打开主题评论模板comments.php文件,在您想显示的位置加上如下代码。

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

此时,评论者的IP地址就转换成了真实地址,受数据库影响,其真实地址不一定准确哈。

同时,Typecho配置CDN后获取访客真实IP地址可能会受到影响,请在Typecho站点根目录里的config.inc.php添加下面这段代码即可。

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

至此,所有教程完毕。

如果本文对您有用的话,欢迎在下方留言评论哦~
发表评论
选择表情
  1. Kane
    A罩

    真实地址这个最好不要显示出来,这个有点那个。。。

    Chrome 78 北京市 联通
  2. ahxx
    B罩

    博主我用了你的,今天发现ie浏览器识别不出来

    浏览器 广东省深圳市 联通
  3. ahxx
    B罩

    学习了,谢谢博主分享

    火狐浏览器 66 广东省深圳市 联通
  4. 枂下
    B罩

    不错不错,跟我的原理一摸一样

    Chrome 72 广东省广州市 电信
    1. Jdeal
      主人
      @枂下

      就是更新数据有点麻烦,速度什么的确实快,用淘宝IP查询,打开会发现网站速度变慢了。

      Chrome 63 江苏省无锡市 电信
      1. 枂下
        B罩
        @Jdeal

        数据库基本不用更新的,就想起来去看看最新的数据库。网上有专门发这个数据库的地址

        Chrome 72 广东省广州市 电信
        1. Jdeal
          主人
          @枂下

          我是直接在纯真网站上下载了它的电脑客户端,可以自动更新下载数据库文件,刚刚点击你网站的订阅按钮,弹出来一个网页一直在空白页打转,是订阅成功了吗

          Chrome 63 江苏省无锡市 电信
          1. 枂下
            B罩
            @Jdeal

            嗯,查了下后台信息,订阅成功了。订阅用的是国外的mailchimp平台

            Chrome 72 广东省广州市 电信