最近在做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