IPIP.net 地址库解析

本文介绍了作者使用Python解析IPIP.net的ipdb地址库,包括库的格式分析、解析过程和代码实现。通过3天时间,作者完成了支持IPv4和IPv6的解析代码,能在几分钟内处理约550万条数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在做ip地址库解析,使用的是IPIP.net 的离线数据库ipdb

IPIP.net 地址库格式分析(现在网址已经无法访问)
以上作者对地址库格式进行了分析,文章后面说是有解析成txt的代码,未找到,只能自己动手写
作者设置了密码,密码为:metowolf

本人花了3天完成:
第一天:搭建python,熟悉python
第二天:熟悉ipdb地址库格式
第三天:编码

该版本同时支持ipv4、ipv6,一般几分钟可以解析出550万左右的数据,换成c、c++、go语言可能更快。

整体文件格式是:4个字节(保存meta的长度) + meta + 8 * node_count(ip地址区) + 20个空字节(空的,意义可能跟算法有关) + 地理位置区

ip地址区里面是8个字节一个node,其中node的前4个字节表示二进制0,后4个字节表示二进制1,值表示下一个node的偏移量。

当node > node_count的意思就是 node * 8 > node_count * 8,那么该node的值就跑到地理位置区去了,而node - node_count表示地理位置区起点隔ip地址区最后的间隔,至于加上node_count * 8就很好理解了,就是地理位置区的起始位置。

代码如下:

import json
import sys
import socket
import gc

def bytes2long(a, b, c, d):
    return convert(a) << 24 | convert(b) << 16 | convert(c) << 8 | convert(d)

def convert(v):
    if v == "" or v == 0:
        return 0
    if sys.version_info.major >= 3:
        return v
    else:
        return ord(v)

def int_to_ip(v):
    if v > 4294967295: #b'11111111111111111111111111111111'
        return socket.inet_ntop(socket.AF_INET6, v.to_bytes(length=16,byteorder='big',signed=False))
    return socket.inet_ntoa(v.to_bytes(length=4,byteorder='big',signed=False))

class DatabaseError(Exception):
    pass

class NoSupportLanguageError(Exception):
    pass

class NoSupportIPv6Error(Exception):
    pass

class NoSupportIPv4Error(Exception):
    pass

class IPNotFound(Exception):
    pass

class NodeData(object):
    def __init__(self, node, idx, next):
        self.node = node
        self.idx = idx
        self.next = next

class IPData(object):
    def __init__(self, start, end):
        self.start = start
        self.end = end

class MetaData(object):
    def __init__(self, **kwargs):
        self.fields = kwargs['fields']
        self.node_count = kwargs['node_count']
        self.total_size = kwargs['total_size']
        self.build = kwargs['build']
        self.languages = kwargs['languages']
        self.ip_version = kwargs['ip_version']

class Reader:
    _meta = {
   }
    data = b""
   
    #ipv4偏移量、最大长度
    _v4offset = 0
    _v4maxlength = 32

    #ipv6偏移量、最大长度
    _v6offset = 0
    _v6maxlength = 128

    node_dict = dict
ip地址资源 /** * */ package common.tools.ip.ipSeeker; import common.tools.ip.Utils; import common.webBase.base.util.Log4jUtil; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteOrder; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /* * LumaQQ - Java QQ Client * * Copyright (C) 2004 luma * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * 用来读取QQwry.dat文件,以根据ip获得好友位置,QQwry.dat的格式是 一. 文件头,共8字节 1. 第一个起始IP的绝对偏移, 4字节 2. * 最后一个起始IP的绝对偏移, 4字节 二. "结束地址/国家/区域"记录区 四字节ip地址后跟的每一条记录分成两个部分 1. 国家记录 2. 地区记录 * 但是地区记录是不一定有的。而且国家记录和地区记录都有两种形式 1. 以0结束的字符串 2. 4个字节,一个字节可能为0x1或0x2 a. * 为0x1时,表示在绝对偏移后还跟着一个区域的记录,注意是绝对偏移之后,而不是这四个字节之后 b. 为0x2时,表示在绝对偏移后没有区域记录 * 不管为0x1还是0x2,后三个字节都是实际国家名的文件内绝对偏移 * 如果是地区记录,0x1和0x2的含义不明,但是如果出现这两个字节,也肯定是跟着3个字节偏移,如果不是 则为0结尾字符串 三. * "起始地址/结束地址偏移"记录区 1. 每条记录7字节,按照起始地址从小到大排列 a. 起始IP地址,4字节 b. 结束ip地址的绝对偏移,3字节 * * 注意,这个文件里的ip地址和所有的偏移量均采用little-endian格式,而java是采用 big-endian格式的,要注意转换 */ public class IPSeeker { /** * 用来封装ip相关信息,目前只有两个字段,ip所在的国家和地区 */ private class IPLocation { public String country; pu
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值