• 把纯真IP数据库中的记录导入Mysql数据库的PHP脚本


            最近在带一个BI项目,其中要展示用户注册、登陆、充值的地区分布。技术的原始数据中保存的是IP地址,然后通过php查询脚本从qqwry.dat文件中查出某个ip对应的地区。

            技术的代码更适合处理一条一条的记录。而我们做数据分析,更希望是把整个qqwry.dat文件中的记录解析出来放到数据库中,这样使用起来会比较方便,特别是批处理的时候。

            本文是在技术给的IP查询脚本的基础上写的遍历程序。关于qqwry.dat文件的结构,可以参考这几篇文章:

    1.《关于QQWry.dat格式》,原文链接:http://blog.csdn.net/cnss/article/details/77628

    2.《纯真IP数据库格式详解》,原文链接:http://lumaqq.linuxsir.org/article/qqwry_format_detail.html

            这两个文档都非常重要,个人感觉,把结构弄清楚了,就比较好处理了。废话不多说,上代码:

    <?php
    
    function read_qqip($qq_datafile)
    
    {
    
        if(!$fd = @fopen($qq_datafile, 'rb')){
    
        return 'Invalid IP data file';
    
      }
    
        
    
      //获取文件的前8个字节
    
      if(!($DataBegin = fread($fd, 4)) || !($DataEnd = fread($fd, 4)) ) return;
    
      //$ipbegin指向第一个起始IP的位置(索引区)
    
      @$ipbegin = implode('', unpack('L', $DataBegin)); 
    
      if($ipbegin < 0) $ipbegin += pow(2, 32);
    
      //$ipend指向最后一个起始IP的位置(索引区)
    
      @$ipend = implode('', unpack('L', $DataEnd));
    
      if($ipend < 0) $ipend += pow(2, 32);
    
      //索引区每条记录的长度为7个字节,$ipAllNum表示的是IP段的个数
    
      $ipAllNum = ($ipend - $ipbegin) / 7 + 1;  
    
      
    
      //在起始IP区进行索引
    
      $result = array(array());
    
      for($i = 0; $i < $ipAllNum; $i++)
    
      {
    
        fseek($fd, $ipbegin + 7 * $i);
    
        $ip_start = fread($fd, 4);  //读取IP段的起始IP的二进制串
    
        
    
        if(strlen($ip_start) < 4){
    
              fclose($fd);
    
              return 'System Error';
    
        }
    
        $ip_start = implode('', unpack('L', $ip_start));
    
        if($ip_start < 0) $ip_start += pow(2, 32);  
    
        $result[$i]['IP_START'] = $ip_start;   //获取IP段的起始IP值
    
        
    
        $DataSeek = fread($fd, 3);  //寻找结束IP
    
        if(strlen($DataSeek) < 3) {
    
          fclose($fd);
    
          return 'System Error';
    
        }
    
        $DataSeek = implode('', unpack('L', $DataSeek.chr(0)));
    
        fseek($fd, $DataSeek);
    
        $ip_end = fread($fd, 4);   //结束IP二进制码
    
        if(strlen($ip_end) < 4) {
    
          fclose($fd);
    
          return 'System Error';
    
        }
    
        $ip_end = implode('', unpack('L', $ip_end)); //结束IP值
    
        if($ip_end < 0) $ip_end += pow(2, 32);    
    
        $result[$i]['IP_END'] = $ip_end;  //读取结束IP值  
    
        
    
        $ipAddr1 = '';
    
        $ipAddr2 = '';
    
            //下面开始读取国家和地区信息
    
            $ipFlag = fread($fd, 1);  //指向国家串前的一个字节
    
          if($ipFlag == chr(1)) {  //为0x01表明国家、地区与前面的IP信息重复
    
            $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)) { //为0x02,表明国家串与前面的国家或地区重复
    
            $AddrSeek = fread($fd, 3);  //国家串的偏移量
    
            if(strlen($AddrSeek) < 3) {
    
              fclose($fd);
    
              return 'System Error';
    
            }
    
            $ipFlag = fread($fd, 1); //读取地区串前的第一个字节
    
            if($ipFlag == chr(2)) {  //出现0x02说明地区串与前面的国家或地区串重复
    
              $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;  //地区串
    
          }
    
          if(preg_match('/http/i', $ipAddr2)) {
    
            $ipAddr2 = '';
    
          }
    
          
    
          $ipaddr = "$ipAddr1";
    
          $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 = mb_convert_encoding($ipaddr, "utf-8", "gb2312"); 
    
        $ipAddr2 = mb_convert_encoding($ipAddr2, "utf-8", "gb2312");
    
          $result[$i]['BIG_AREA'] = $ipaddr;
    
        $result[$i]['SMALL_AREA'] = $ipAddr2;
    
        //echo $result[$i]['BIG_AREA'].'---'.$result[$i]['SMALL_AREA'].'<br>';
    
        
    
      }
    
      return $result;
    
    }
    
    ?>
    
      

            需要说明的是,上面的代码并非100%原创,而是在技术给的代码的基础上修改出来的,在此感谢相关人员。

            获取$result之后,只需要把$result写入相应的数据表即可。导入之后的结果如下:

            image

  • 相关阅读:
    团队项目-需求分析报告
    团队项目-选题报告
    第一次结对编程作业
    第一次个人编程作业
    第一次博客作业
    如何上传大文件到github上
    第07组 Alpha冲刺(3/4)
    第07组 Alpha冲刺(2/4)
    第07组 Alpha冲刺(2/4)
    第07组 Alpha冲刺(1/4)
  • 原文地址:https://www.cnblogs.com/huake/p/3495231.html
Copyright © 2020-2023  润新知