`

淘宝IP地址库

阅读更多
网上流传最广的免费IP库,是纯真的IP库:http://www.cz88.net/,且该库一直有维护,但缺点是不太准确。
淘宝的IP地址库比较准确,且提供了IP查询的接口:http://ip.taobao.com/。但它没有提供全量下载,且一秒内调用不能超过10次。

于是萌生了一个想法:
以纯真IP库作为IP分段的依据,以此去调用淘宝的接口,从而获得比较准确的IP库。


以纯真IP库的几行记录为例:
a.235995136*14.17.0.0*235997951*14.17.10.255*广东省*深圳市*广东省深圳市*电信
b.3546091247*211.93.14.239*3546091519*211.93.15.255*青海省*西宁市*青海省西宁市*联通


处理方式如下:
1.对于记录a,14.17.0.0和14.17.10.255,分两次调用淘宝的接口,获得结果均为:
14.17.0.0-14.17.10.255 广东省广州市
这种情况最为简单,直接用淘宝的结果替换纯真的结果即可。

2.对于记录b,211.93.14.239和211.93.15.255,分两次调用淘宝的接口,获得结果为:
211.93.14.239 青海省海南藏族自治州
211.93.15.255 青海省西宁市
出现了前后不一致的情况。
这时候怎么办呢?

把211.93.14.239-211.93.15.255这个IP段进行粗略的分段,按IP的前三段相同的,分为一个小段:
211.93.14.239-211.93.14.255 青海省海南藏族自治州
211.93.15.0-211.93.15.255 青海省西宁市
在每一个小段里,前后一致,纯真的一个IP段变成了两个IP段。
但这样做是基于一个前提:那就是认为211.93.15.0-211.93.15.255这样的(x.y.z.0-x.y.z.255,前三部分相同)所有IP是落在同一个城市。
这个前提不一定成立的。因此以此得到的数据,只是相对准确。

那对于x.y.z.0和x.y.z.255,如果落在不同城市呢?
这时候没有更好的办法了,只能遍历x.y.z.0-x.y.z.255之间的所有IP,得到结果后再把城市相同的进行合并。
在我的测试过程中,有455个这样的IP段是前后不一致的。

这样的处理很繁琐,我花费了几天才处理完毕,现在把结果分享出来,供有需要的人下载:http://pan.baidu.com/s/1eQg3pvW, 提取密码为nhhd。此外,为方便使用,我还在IP表中记录了IP对应的城市的经纬度:






要声明的是,本人不对数据的正确性作任何保证

同时,提供几个用到的函数(代码待优化),供参考:
public class IpUtil {

    private static final int MAX = 255;
    
    /**
     * 把IpRange拆成更小的IpRange,使得每个小的IpRange的前三个网段是相同的
     * 例如把1.1.1.20-1.1.3.30拆成:
     * 1.1.1.20-1.1.1.255
     * 1.1.2.0-1.1.2.255
     * 1.1.3.0-1.1.3.30
     * @param range
     * @return
     */
    public static  List<IpRange> split(IpRange range) {
        List<IpRange> list = new ArrayList<IpRange>();
        long p0, p1, p2;
        long min = toLongWithFirstThreeParts(range.getStart());
        long max = toLongWithFirstThreeParts(range.getEnd());
        for (p0 = range.getStart().getP0(); p0 <= range.getEnd().getP0(); p0++) {
            for (p1 = 0; p1 <= MAX; p1++) {
                for (p2 = 0; p2 <= MAX; p2++) {
                    if (firstThreePartsToLong(p0, p1, p2)< min) {
                        continue;
                    }
                    if (firstThreePartsToLong(p0, p1, p2) > max) {
                        break;
                    }
                    IpBean newStart = new IpBean(p0, p1, p2, 0);
                    if (newStart.toLong() < range.getStart().toLong()) {
                        newStart = range.getStart();
                    }
                    IpBean newEnd = new IpBean(p0, p1, p2, 255);
                    if (newEnd.toLong() > range.getEnd().toLong()) {
                        newEnd = range.getEnd();
                    }
                    IpRange ipRange = new IpRange(newStart, newEnd);
                    list.add(ipRange);
                }
            }
        }
        return list;
    }
    
    /**
     * 只计算前三段
     * @return
     */
    public static  long toLongWithFirstThreeParts(IpBean bean) {
        long p0 = bean.getP0();
        long p1 = bean.getP1();
        long p2 = bean.getP2();
        return firstThreePartsToLong(p0, p1, p2);
    }
    
    public  static long firstThreePartsToLong(long p0, long p1, long p2) {
        return (p0 << 24) + (p1 << 16) + (p2 << 8);
    }
    
    /**
     * 取得startIp-endIp这个IP段内所有的单个IP
     * @param startIp
     * @param endIp
     * @return
     */
    public static  List<IpBean> findIpList(String startIp, String endIp) {
        List<IpBean> list = new ArrayList<IpBean>();
        
        IpBean startBean = toBean(startIp);
        IpBean endBean = toBean(endIp);
        long start = startBean.toLong();
        long end = endBean.toLong();
        long p0, p1, p2, p3;
        for (p0 = startBean.getP0(); p0 <= endBean.getP0(); p0++ ) {
            for (p1 = 0; p1 <= MAX; p1++) {
                for (p2 = 0; p2 <= MAX; p2++) {
                    for (p3 = 0; p3 <= MAX; p3++) {
                        IpBean newIp = new IpBean();
                        newIp.setP0(p0);
                        newIp.setP1(p1);
                        newIp.setP2(p2);
                        newIp.setP3(p3);
                        long newLongVal = newIp.toLong();
                        if (start <= newLongVal && newLongVal <= end) {
                            list.add(newIp);
                        }
                    }
                }
            }
        }
        return list;
    }
    
    

    public  static IpBean toBean(String ipStr) {
        long[] ip = new long[4];
        // 先找到IP地址字符串中.的位置
        int position1 = ipStr.indexOf(".");
        int position2 = ipStr.indexOf(".", position1 + 1);
        int position3 = ipStr.indexOf(".", position2 + 1);
        // 将每个.之间的字符串转换成整型
        ip[0] = Long.parseLong(ipStr.substring(0, position1));
        ip[1] = Long.parseLong(ipStr.substring(position1 + 1, position2));
        ip[2] = Long.parseLong(ipStr.substring(position2 + 1, position3));
        ip[3] = Long.parseLong(ipStr.substring(position3 + 1));
        
        IpBean bean = new IpBean();
        bean.setP0(ip[0]);
        bean.setP1(ip[1]);
        bean.setP2(ip[2]);
        bean.setP3(ip[3]);
        return bean;
    }

}


    /**
     * 合并连续的、在同一城市的IP
     */
    public void merge() {
        IpExample example = new IpExample();
        example.createCriteria().andStateEqualTo(IpConst.State.OK);
        example.setOrderByClause("ipstartdigital asc");
        List<Ip> list = mapper.selectByExample2(example);
        logger.info("size={}", list.size());
        Ip startIp = null;
        Ip endIp = null;
        int count = 0;
        for (Ip ip : list) {
            if (startIp == null) {
                startIp = ip;
                endIp = ip;
            } else {
                if (isMatched(endIp, ip) && isContinuous(endIp, ip) ) {
                    endIp = ip;
                    continue;
                } else {
                    count++;
                    insert(startIp, endIp);
                    startIp = ip;
                    endIp = ip;
                }
            }
        }
        if (startIp != null && endIp != null) {
            count++;
            insert(startIp, endIp);
        }
        logger.info("count={}", count);
    }
    
    
    private boolean isContinuous(Ip endIp, Ip ip) {
        return endIp.getIpenddigital().equals(ip.getIpstartdigital() - 1);
    }


    private void insert(Ip startIp, Ip endIp) {
        Ip ip = new Ip();
        Helper.copyFromNotNull(ip, startIp);
        ip.setIpend(endIp.getIpend());
        ip.setIpenddigital(endIp.getIpenddigital());
        ip.setId(null);
        logger.info("last ipstart={}, ipstartdigital={}, ipend={}, ipenddigital={}, province={}, city={}", ip.getIpstart(), ip.getIpstartdigital(), ip.getIpend(), ip.getIpenddigital(), ip.getProvince(), ip.getCity());
        mapper.insert(ip);
    }

    private boolean isMatched(Ip x, Ip y) {
        boolean result = false;
        
        //国家+省+市是否相等
        if (x != null && y != null) {
            result =  StringUtils.equals(x.getCountry(), y.getCountry())
                   && StringUtils.equals(x.getProvince(), y.getProvince())
                   && StringUtils.equals(x.getCity(), y.getCity());
        }
        return result;
    }
	
	


  • 大小: 80.9 KB
3
1
分享到:
评论

相关推荐

    vs2005下通过淘宝IP地址库获取IP的地区信息

    淘宝IP地址库,jsoncpp, http

    淘宝IP地址库,提供API

    淘宝IP地址库,提供API

    淘宝IP地址库采集器c#代码

     在百度上找啊找,找到淘宝Ip地址库,官方介绍的相当诱人,准确率高,数据质量有保障,提供国家、省、市、县、运营商全方位信息,信息维度广,格式规范,但是限制每秒10次的访问(这个比较无语)。  淘宝IP地址库,...

    使用淘宝ip地址库查ip的示例

    使用淘宝ip地址库的api查询ip地址信息。 TaobaoIPHelper.cs 代码如下:using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace LixinCommon{ ///  /// 淘宝IP地址库...

    免费的ip数据库淘宝IP地址库简介和PHP调用实例

    淘宝ip地址库提供免费的ip信息查询,可查询ip所在国家、区域、省份、城市及运营商等信息。不需要认证不需要注册,唯一的小缺陷就是限制美妙查询频率不能高于10次。

    IP地址库2018024(SQL Server)

    IP地址值库(基于纯真数据库和淘宝地址库进行的重置)。精确到市级(国家,省,市),包含ISP信息(记录数 &gt; 480000)

    IP地址查询 v3.0 php版.zip

    并且会随着淘宝IP地址库实时更新。所以您获得的数据将会是最新的。 2.此3.0核心函数代码加密 其它2.0 1.0 版本完全开源 3.define('SINA_SAE', '0'); //是否启用新浪SAE平台1为使用0为不使用 4.define('REWRITE', ...

    IP地址库20181029(SQL Server)

    IP地址值库(基于纯真数据库和淘宝地址库进行的重置)。精确到市级(国家,省,市),包含ISP信息(记录数 &gt; 480000)

    IP地址查询php版 3.0.zip

    并且会随着淘宝IP地址库实时更新。所以您获得的数据将会是最新的。 2.此3.0核心函数代码加密 其它2.0 1.0 版本完全开源 3.define('SINA_SAE', '0'); //是否启用新浪SAE平台1为使用0为不使用 4.define('REWRITE', ...

    IP地址库20190225(SQL Server)

    IP地址值库(基于纯真数据库和淘宝地址库进行的重制)。精确到市级(国家,省,市),包含ISP信息(原纯真记录数 &gt; 480000,合并去重后近30w) 新版的地址20200325 ...

    根据IP地址获取ip所在区域.rar

    资源中有测试示例, 根据IP地址,调取淘宝IP地址库接口,获取IP所属的国家、运营商以及区域代码和运营商的代码。。。。

    Python2.7基于淘宝接口获取IP地址所在地理位置的方法【测试可用】

    主要介绍了Python2.7基于淘宝接口获取IP地址所在地理位置的方法,涉及Python调用淘宝IP库接口进行IP查询的简单操作技巧,需要的朋友可以参考下

    IP地址库20180710(SQL Server)

    IP地址值库(基于纯真数据库和淘宝地址库进行的重置)。精确到市级(国家,省,市),包含ISP信息(记录数 &gt; 480000)

    IP地址库-20180205(SQL)

    IP地址库,SQL 语句版本( 根据 纯真IP地址库 和 淘宝地址库 转换而来)。 可以放心使用

    IP地址库20191104(SQL Server)

    IP地址库(基于纯真数据库和淘宝地址库进行的重制)。精确到市级(国家,省,市),包含ISP信息(原纯真记录数 &gt; 500000,合并处理后 近30w)

    java获取IP地址工具类

    利用淘宝IP地址库实现的利用IP获取用户所在地工具类

    IP地址查询 v3.0 php版

    并且会随着淘宝IP地址库实时更新。所以您获得的数据将会是最新的。 2.此3.0核心函数代码加密 其它2.0 1.0 版本完全开源 3.define('SINA_SAE', '0'); //是否启用新浪SAE平台1为使用0为不使用 4.define('REWRITE', ...

    IP地址库20210512

    IP地址库(基于纯真数据库和淘宝地址库进行的重制)。精确到市级(国家,省,市),包含ISP信息(原纯真记录数 &gt; 500000,合并处理后 近30w)

Global site tag (gtag.js) - Google Analytics