文档章节

纯真IP地址库合并

心驰
 心驰
发布于 2017/09/06 17:19
字数 689
阅读 3
收藏 0
点赞 0
评论 0
<?php
/**
 * @author( author = 'xbruce' )
 * @datetime( datetime = '2017年7月2日 下午3:29:44' )
 * @comment( comment='ip地址工具' )
 */
class IpUtils
{
    private static $_instance = null;

    private $_nredis = null;
    
    private $arrIpsTmp = array();
    
    const REDIS_SS_IPS = 'l_ss_ips';
    
    const GREP_IP = "/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}/";
    
    private function __construct( $redis = null )
    {
        if( $redis )
        {
            $this->_nredis = $redis;
        }

        assert( $redis, 'redis实例不能为空!' );
    }

    static public function getInstance( $redis = null )
    {
        assert( $redis, 'redis实例不能为空!' );
        
        if( !$redis )
        {
            echo 'redis实例不能为空!', PHP_EOL;
            return null;
        }
        
        if( is_null( self::$_instance ) )
        {
            self::$_instance = new IpUtils( $redis );
        }
        
        return self::$_instance;
    }
  
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '读文件到内存中以方便写查询缓存' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strFileName
     * @return boolean
     */
    public function initIpLibFromFile( string $strFileName = null )
    {
        set_time_limit( 0 );
        ini_set( 'memory_limit', '1024M' );
        
        if( !file_exists( $strFileName ))
        {
            return false;
        }
        
//         $this->removeSetKeys();
        
        $fIp = fopen( $strFileName, 'r' );
        
        if( !$fIp )
        {
            return false;
        }
                
        echo '正在进行缓存请稍后...' . PHP_EOL;
        $ip = array();
        
        $iIndex = 0;
        while( ($line = trim( fgets( $fIp ))) != '' )
        {
            $line = mb_convert_encoding( $line, 'UTF8', 'GBK' );
            
            preg_match_all( "/[^\s]+/", $line, $arrMatches );
            
            if( count( $arrMatches[0] ) < 3 )
            {
                return false;
            }
            
            $arrIpInfo = $arrMatches[0];
            $ip['ip_begin'] = $this->ip2longCust( $arrIpInfo[0] );
            $ip['ip_end'] = $this->ip2longCust( $arrIpInfo[1] );
            
            $ip['info'] = '';
            $key = $arrIpInfo[2];
            $iInfoCnt = count( $arrIpInfo );
            for( $i = 2; $i < $iInfoCnt; ++$i )
            {
                $ip['info'] .= ' ' . $arrIpInfo[$i];
            }
            
            $strKey = md5( $key );
            
            $this->arrIpsTmp[ $strKey ][$ip['ip_begin']] = $ip;

            unset($ip);
        }
        
        fclose( $fIp );
        
        echo '写缓存结束!' . PHP_EOL;
        
        return true;
    }
    
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '' )
     * @method( method = '' )
     * @op( op = '' )
     */
    public function combineAdjacentIp()
    {
        ini_set( 'memory_limit', '1024M' );
        
        $arrDupIps = array();
        $arrKeys = $this->arrIpsTmp;
        
        $iIndex = 0;
        
        foreach( $arrKeys as $v )
        {     
            $arrIps = $v;
            foreach( $arrIps as $ip )
            {
                $arrDupIps[ $ip['ip_begin'] ] = $ip;
            }
            
            unset( $arrIps );
                        
            if( uksort( $arrDupIps, function( $left, $right ){
                if( $left < $right )
                {
                    return -1;
                }
                else if( $left == $right )
                {
                    return 0;
                }
                else 
                {
                    return 1;
                }
            }))
            {
                $iCnt = 0;
                
                $arrTemp = array();
                foreach( $arrDupIps as $key => $val )
                {
                    $arrTemp[$iCnt++] = $val;
                }
                unset( $arrDupIps );
                
                $iTargetIndex = 0;
                
                $curIp = $arrTemp[0];
                
                if( $iCnt > 1 )
                {
                    for( $i = 0; $i < $iCnt; ++$i )
                    {
                        if( $i + 1 < $iCnt && ( $curIp['ip_end'] + 1 == $arrTemp[ $i + 1 ]['ip_begin'] ))
                        {
                            $curIp['ip_end'] = $arrTemp[ $i + 1 ]['ip_end'];
                        }
                        else 
                        {
                            ++$iIndex;
                            $this->_nredis->zAdd( self::REDIS_SS_IPS, $curIp['ip_begin'], json_encode( $curIp ));
                            
                            if( $i + 1 < $iCnt )
                            {
                                $curIp = $arrTemp[$i+1];
                            }
                        }
                        
                    }
                }
                else if( 1 == $iCnt )
                {
                    $this->_nredis->zAdd( self::REDIS_SS_IPS, $curIp['ip_begin'], json_encode( $curIp ));
                    ++$iIndex;                    
                }

                unset( $arrTargets );
                unset( $arrTemp );
                
                echo '已处理到第', $iIndex, '个', PHP_EOL;
            }
            else
            {
                echo '排序失败,请检查错误原因!', PHP_EOL;
                exit();
            }
            
        }
        
        echo PHP_EOL, '成功精简IP地址库!', PHP_EOL;
    }
    
    
    /**
     * 
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '取IP地址相关信息' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strIp
     */
    public function getIpLocation( string $strIp = null )
    {
        if( empty( $strIp ) || ( $strIp = trim( $strIp )) == '' )
        {
            return false;
        }

        $lIp = $this->ip2longCust( $strIp );

        $r = $this->_nredis->zRevRangeByScore( self::REDIS_SS_IPS, $lIp, -1, array( 'limit' => array( 0, 1 )));
        
        if( count( $r ) >= 1 )
        {
            $objIp = json_decode( $r[0] );
            if( $objIp->ip_begin <= $lIp && $lIp <= $objIp->ip_end )
            {
                return $objIp;
            }
            
            return false;
        }
        
        return false;
    }
    
    
    public function test()
    {
        return $this->getIpLocation( '8.8.8.8');
    }
    
    /**
     * @author( author='xbruce' )
     * @date( date = '2017年7月2日' )
     * @comment( comment = '解决因ip2long bug而引起的bug' )
     * @method( method = '' )
     * @op( op = '' )
     * @param string $strIp
     */
    private function ip2longCust( string $strIp )
    {
        if( preg_match( self::GREP_IP, $strIp ) && is_string( $strIp ) )
        {
            $arrIps = explode( '.', $strIp );
            $strIpTmp = '';
            foreach( $arrIps as $k => $v )
            {
                $strIpTmp .= intval( $v ) . '.';
            }
    
            $strIpTmp = rtrim( $strIpTmp, '\.' );
    
            return ip2long( $strIpTmp );
    
        }
    
        return false;
    }
    
}

// $redis = new Redis();

$redis = new Redis();
$redis->connect( '127.0.0.1', 6379 );
$redis->auth( 'pass' );//redis requirepass
// $redis->select( 0 );

$iu = IpUtils::getInstance( $redis );
// var_dump( $iu->initIpLibFromFile( '/git/phcms/czip.txt' ) );//初始化文件到临时文件
// $iu->combineAdjacentIp();//合并同一地的相邻IP

$t = microtime( true );
for( $i = 0; $i < 100000; ++$i )
{
    $objRes = $iu->test();
}

echo microtime( true ) - $t;
//在我的配置很低小本子上可以达到15190QPS以上

本文转载自:https://my.oschina.net/u/1584951/blog/1114029

共有 人打赏支持
心驰
粉丝 0
博文 20
码字总数 910
作品 0
海淀
程序员
Java解析归属地,以前用纯真库,现在需要兼容ipv6

之前项目用纯真的ip库,然后写的Java代码查询纯真库中相应ip的归属地,现在项目需要支持ipv6的ip地址,所以归属地查询就是问题,首先 纯真的ipv6版本的数据库去哪里下载? 其次 查询该ipv6的...

bluysky
2013/08/15
317
0
根据ip查找ISP运营商和归属地的几种方法

一般来说都是根据网上流传的各种IP库来解析获取对应的ISP和归属地的, 除非有实力的公司自己从运营商获取数据,然后做数据分析得到。 下面介绍前者,如何利用网上的IP库获取这类信息: 1、利...

大数据之路
2012/07/16
0
0
国内常用ip地址库

腾讯腾讯IP分享计划IP分享 新浪http://int.dpool.sina.com.cn/iplookup/iplookup.php?ip=8.8.8.8&format=js 百度Web服务Geocoding API-百度地图 淘宝淘宝IP地址库 geoip MaxMind - IP地理定位...

沉淀岁月
2016/07/19
117
0
高效查询纯真IP库 --lib-qqwry

lib-qqwry是一个高效查询纯真 IP 库(qqwry.dat)的模块。它是用 NodeJS 解析纯真 IP 库(QQwry.dat) ,支持 IP 段查询。为更好的字符转化效率,未使用iconv模块,直接使用gbk编码表文件。经过不...

含浪
2015/05/22
759
0
Thinkphp的Ip地址定位

获取IP地址 如果你仅仅需要获取用户访问的IP地址,那么直接使用系统内置的getclientip函数即可,该函数是ThinkPHP标准模式内置方法,可以直接使用,比PHP内置的系统变量$SERVER['HTTPCLIENT...

freedonn
2014/02/14
0
0
关于ip识别的问题和ip存储的问题

在登录网站的时间,一些可以直接通过识别ip来显示相应位置的信息。 ip信息在数据库里面是怎么存储的,我看纯真ip库有四十多万的ip地址信息。如果放在一个表里面去匹配的话时间应该会很长,但...

mrmusic
2015/09/25
193
5
二分法在IP地址查询中的应用(来自深空老大)

前段时间做数据分析,需要大量的IP地址查询(每秒钟近万次检索),首先考虑到使用数据库。数据库大概存储几十万条IP记录,记录集如下: 这样做查询需要用到如下SQL: 这样的检索显然用不到索...

岭南六少
2011/07/21
0
0
PHP的IP地址查询库--QQWry

QQWry 是一个php扩展,实现语言为c。这个扩展的作用,就是根据ip来获取纯真数据库(QQWry.Dat)的地址信息。经过和discuz,CoolCode两个纯php版本的对比测试,这个c实现的扩展比纯php的实现效率...

匿名
2009/01/18
9K
2
Python读取纯真IP数据库

一、获取最新版IP地址数据库qqwry.dat 纯真IP地址数据库下载地址:http://update.cz88.net/soft/setup.zip 在windows机器上下载解压,点击setup.exe安装,在安装目录下的qqwry.dat即是最新版...

张斌_青岛
2014/12/12
0
0
IP 到地名映射库--ip2region

ip2region - 准确率99.9%的ip地址定位库,0.0x毫秒级查询,数据库文件大小只有1.5M,提供了java,php,c,python,nodejs,golang查询绑定和Binary,B树,内存三种查询算法,妈妈再也不用担心我的i...

狮子的魂
2015/11/02
11K
14

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring boot中日期的json格式化

Model 在model层中,类的日期属性上面添加如下注解: @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss") 参考 Jackson Date格式化教程...

亚林瓜子
5分钟前
0
0
Eclipse:Failed to load the JNI shared library

1.问题背景: 由于我之前使用jdk1.9学习,当使用Luke的时候发现jdk版本过高,需要向下配置jdk,就向朋友拷了一个安装包。重新配置路径后,便开始报错。 2.问题描述: Failed to load the JNI...

tinder_boy
8分钟前
0
0
少儿学习编程课程是否真的适合七八岁的低龄儿童[图]

少儿学习编程课程是否真的适合七八岁的低龄儿童[图]: 天下熙熙皆为利来,天下攘攘皆为利往。 这几年来,乐高教育机构在国内如同雨后春笋般出现,当然关闭/转手的也很多。从教师角度来看,部...

原创小博客
13分钟前
0
0
ES12-词项查询

1.词项查询介绍 全文查询将在执行之前分析查询字符串,但词项级别查询将按照存储在倒排索引中的词项进行精确操作。这些查询通常用于数字,日期和枚举等结构化数据,而不是全文本字段。 或者,...

贾峰uk
21分钟前
0
0
http状态码与ajax的状态值

ajax状态值 1.1 200 & OK:状态请求成功

litCabbage
24分钟前
0
0
iOS动画效果合集、飞吧企鹅游戏、换肤方案、画板、文字效果等源码

iOS精选源码 动画知识运用及常见动画效果收集 3D卡片拖拽卡片叠加卡片 iFIERO - FLYING PENGUIN 飞吧企鹅SpriteKit游戏(源码) Swift封装的空数据提醒界面EmptyView 沙盒文件浏览与分享调试控...

sunnyaigd
27分钟前
0
0
AngularJS配置.run()块中设置路由事件的监听器以及过滤未经授权的请求

AngularJS中的run方法初始化全局数据,只对全局作用域起作用,如$rootScope.多个控制器之间可以共享数据,如下代码所示: <script type="text/javascript"> var m1 = angular....

孟飞阳
28分钟前
0
0
Java语言学习(十):输入/输出

Java中,I/O操作代表着输入、输出,Java所有的I/O机制都是基于数据流进行输入输出。java.io类包提供了很多的输入输出处理功能方法,大家可以参考下JDK文档中关于I/O的一些处理方法:JDK在线中...

海岸线的曙光
37分钟前
1
0
基于阿里出得ng-Alain搭建后台管理系统

首先跟大家介绍一下ng_Alain(阿里团队出品) ng-alain技术栈基于 Typescript、Angular、g2、@delon 和 ng-zorro-antd,提前了解和学习这些知识会非常有帮助。 ng-alain 脚手架是基于 Angular ...

方宏春
41分钟前
1
0
Spring框架IOC和AOP的实现原理

一、IoC(Inversion of Control) (1). IoC(Inversion of Control)是指容器控制程序对象之间的关系,而不是传统实现中,由程序代码直接操控。控制权由应用代码中转到了外部容器,控制权的转...

HaierBrother
44分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部