zoukankan      html  css  js  c++  java
  • php根据ip查询所在地区(非常有用,赶集网就用到)

    dat文件,关于ip对应地区的信息文件

    qqwry.dat文件

    网上自己下载

    class类文件,解析qqwry.data文件的

    IpLocation.php文件

    1. <?php  
    2. class IpLocation {  
    3.     /** 
    4.     * @var resource 指针 
    5.     */  
    6.     private $fp;  
    7.   
    8.     /** 
    9.     * 第一条IP记录的偏移地址 
    10.     * @var int 
    11.     */  
    12.     private $firstip;  
    13.   
    14.     /** 
    15.     * 最后一条IP记录的偏移地址 
    16.     * @var int 
    17.     */  
    18.     private $lastip;  
    19.   
    20.     /** 
    21.     * IP记录的总条数(不包含版本信息记录) 
    22.     * @var int 
    23.     */  
    24.     private $totalip;  
    25.   
    26.     /** 
    27.     * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息 
    28.     * @param string $filename 
    29.     * @return IpLocation 
    30.     */  
    31.     public function __construct($filename = "qqwry.dat") {  
    32.         $this->fp = 0;  
    33.         if (($this->fp = @fopen($filename'rb')) !== false) {  
    34.             $this->firstip = $this->getlong();  
    35.             $this->lastip = $this->getlong();  
    36.             $this->totalip = ($this->lastip - $this->firstip) / 7;  
    37.         }  
    38.     }  
    39.   
    40.     /** 
    41.     * 返回读取的长整型数 
    42.     * @access private 
    43.     * @return int 
    44.     */  
    45.     public function getlong() {  
    46.         //将读取的little-endian编码的4个字节转化为长整型数  
    47.         $result = unpack('Vlong'fread($this->fp, 4));  
    48.         return $result['long'];  
    49.     }  
    50.   
    51.     /** 
    52.     * 返回读取的3个字节的长整型数 
    53.     * 
    54.     * @access private 
    55.     * @return int 
    56.     */  
    57.     public function getlong3() {  
    58.         //将读取的little-endian编码的3个字节转化为长整型数  
    59.         $result = unpack('Vlong'fread($this->fp, 3).chr(0));  
    60.         return $result['long'];  
    61.     }  
    62.   
    63.     /** 
    64.     * 返回压缩后可进行比较的IP地址 
    65.     * 
    66.     * @access private 
    67.     * @param string $ip 
    68.     * @return string 
    69.     */  
    70.     public function packip($ip) {  
    71.         // 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,  
    72.         // 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串  
    73.         return pack('N'intval(ip2long($ip)));  
    74.     }  
    75.   
    76.     /** 
    77.     * 返回读取的字符串 
    78.     * 
    79.     * @access private 
    80.     * @param string $data 
    81.     * @return string 
    82.     */  
    83.     public function getstring($data = "") {  
    84.         $char = fread($this->fp, 1);  
    85.         while (ord($char) > 0) { // 字符串按照C格式保存,以\0结束  
    86.             $data .= $char// 将读取的字符连接到给定字符串之后  
    87.             $char = fread($this->fp, 1);  
    88.         }  
    89.         return mb_convert_encoding($data'utf-8''gb2312');  
    90.     }  
    91.   
    92.     /** 
    93.     * 返回地区信息 
    94.     * 
    95.     * @access private 
    96.     * @return string 
    97.     */  
    98.     public function getarea() {  
    99.         $byte = fread($this->fp, 1); // 标志字节  
    100.         switch (ord($byte)) {  
    101.             case 0: // 没有区域信息  
    102.                 $area = "";  
    103.             break;  
    104.             case 1:  
    105.             case 2: // 标志字节为1或2,表示区域信息被重定向  
    106.                 fseek($this->fp, $this->getlong3());  
    107.                 $area = $this->getstring();  
    108.             break;  
    109.             default// 否则,表示区域信息没有被重定向  
    110.                 $area = $this->getstring($byte);  
    111.             break;  
    112.         }  
    113.         return $area;  
    114.     }  
    115.   
    116.     /** 
    117.     * 根据所给 IP 地址或域名返回所在地区信息 
    118.     * @access public 
    119.     * @param string $ip 
    120.     * @return array 
    121.     */  
    122.     function getlocation($ip) {  
    123.         if (!$this->fp) return null; // 如果数据文件没有被正确打开,则直接返回空  
    124.         $location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址  
    125.         $ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址  
    126.         // 不合法的IP地址会被转化为255.255.255.255  
    127.         // 对分搜索  
    128.         $l = 0; // 搜索的下边界  
    129.         $u = $this->totalip; // 搜索的上边界  
    130.         $findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息)  
    131.         while ($l <= $u) { // 当上边界小于下边界时,查找失败  
    132.             $i = floor(($l + $u) / 2); // 计算近似中间记录  
    133.             fseek($this->fp, $this->firstip + $i * 7);  
    134.             $beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址  
    135.             // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式  
    136.             // 以便用于比较,后面相同。  
    137.             if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时  
    138.                 $u = $i - 1; // 将搜索的上边界修改为中间记录减一  
    139.             }else{  
    140.                 fseek($this->fp, $this->getlong3());  
    141.                 $endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址  
    142.                 if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时  
    143.                     $l = $i + 1; // 将搜索的下边界修改为中间记录加一  
    144.                 }else// 用户的IP在中间记录的IP范围内时  
    145.                     $findip = $this->firstip + $i * 7;  
    146.                     break// 则表示找到结果,退出循环  
    147.                 }  
    148.             }  
    149.         }  
    150.   
    151.         //获取查找到的IP地理位置信息  
    152.         fseek($this->fp, $findip);  
    153.         $location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址  
    154.         $offset = $this->getlong3();  
    155.         fseek($this->fp, $offset);  
    156.         $location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址  
    157.         $byte = fread($this->fp, 1); // 标志字节  
    158.   
    159.         switch (ord($byte)) {  
    160.             case 1: // 标志字节为1,表示国家和区域信息都被同时重定向  
    161.                 $countryOffset = $this->getlong3(); // 重定向地址  
    162.                 fseek($this->fp, $countryOffset);  
    163.                 $byte = fread($this->fp, 1); // 标志字节  
    164.                 switch (ord($byte)) {  
    165.                     case 2: // 标志字节为2,表示国家信息又被重定向  
    166.                         fseek($this->fp, $this->getlong3());  
    167.                         $location['country'] = $this->getstring();  
    168.                         fseek($this->fp, $countryOffset + 4);  
    169.                         $location['area'] = $this->getarea();  
    170.                         break;  
    171.                     default// 否则,表示国家信息没有被重定向  
    172.                         $location['country'] = $this->getstring($byte);  
    173.                         $location['area'] = $this->getarea();  
    174.                         break;  
    175.                 }  
    176.                 break;  
    177.             case 2: // 标志字节为2,表示国家信息被重定向  
    178.                 fseek($this->fp, $this->getlong3());  
    179.                 $location['country'] = $this->getstring();  
    180.                 fseek($this->fp, $offset + 8);  
    181.                 $location['area'] = $this->getarea();  
    182.                 break;  
    183.             default// 否则,表示国家信息没有被重定向  
    184.                 $location['country'] = $this->getstring($byte);  
    185.                 $location['area'] = $this->getarea();  
    186.                 break;  
    187.         }  
    188.         if ($location['country'] == " CZ88.NET") { // CZ88.NET表示没有有效信息  
    189.             $location['country'] = "未知";  
    190.         }  
    191.         if ($location['area'] == " CZ88.NET") {  
    192.             $location['area'] = "";  
    193.         }  
    194.         return $location;  
    195.     }  
    196.   
    197.       
    198.     /** 
    199.     * 析构函数,用于在页面执行结束后自动关闭打开的文件。 
    200.     * 
    201.     */  
    202.     function __desctruct() {  
    203.         if ($this->fp) {  
    204.             fclose($this->fp);  
    205.         }  
    206.         $this->fp = 0;  
    207.     }  
    208. }  
    209. ?>   

    这个也可以网上下载,也可以copy这里的,这里的也是很全的。

    执行文件,我这里叫ip_location.php文件

      1. <?php   
      2. function getIpPlace(){  
      3.     require_once("IpLocation.php")//加载类文件IpLocation.php  
      4.     $ipfile = "qqwry.dat";      //获取ip对应地区的信息文件  
      5.     $iplocation = new IpLocation($ipfile);  //new IpLocation($ipfile) $ipfile ip对应地区信息文件  
      6.     $ipresult = $iplocation->getlocation("ip地址"); //根据ip地址获得地区 getlocation("ip地区")  
      7.     return $ipresult;  
      8. }  
      9. print_r($getIpPlace()); //调用方法  
      10. ?> 
    http://blog.csdn.net/motian06/article/details/7919675
  • 相关阅读:
    2015-05-27 用正则把oracle时间转化到mysql时间
    linux版idea14界面美观和windows,mac基本一致
    ubuntu 下自定义快捷键,,用着舒服
    ubuntu 方便好用的截图软件
    Integer 包装器类 大小比较
    win7、ubuntu双系统,遇到分区不可用问题,和卸载ubuntu后win7开不了机
    巧妙小思想
    读取16进制文件和校验图片格式的问题。 文件名后缀
    旧电脑变废为宝!
    Win10打开Autodesk软件时提示“管理员已阻止你运行此应用”
  • 原文地址:https://www.cnblogs.com/xinlei/p/2948196.html
Copyright © 2011-2022 走看看