ip库查询
2010-06-09 09:51
[python]
现在网上流传的ip库,稍微处理了一下,一共 373691条记录,压缩后是 3.5M
记录格式如
63.211.200.72 63.211.200.79 美国 加利福尼亚州山景市谷歌公司IP范围,然后是名称。名称为utf8编码。使用掩码表示可能更专业一些。
64.41.221.192 64.41.221.207 美国 加利福尼亚州山景市谷歌公司
64.68.64.64 64.68.64.127 美国 加利福尼亚州山景市谷歌公司
64.68.80.0 64.68.95.255 美国 加利福尼亚州山景市谷歌公司
64.233.160.0 64.233.191.255 美国 加利福尼亚州山景市谷歌公司
66.102.0.0 66.102.15.255 美国 加利福尼亚州山景市谷歌公司
66.249.64.0 66.249.95.255 美国 加利福尼亚州山景市谷歌公司
72.14.192.0 72.14.255.255 美国 加利福尼亚州山景市谷歌公司
74.125.0.0 74.125.255.255 美国 加利福尼亚州山景市谷歌公司
194.221.68.0 194.221.68.255 英国 谷歌(北爱尔兰)有限公司
195.249.20.0 195.249.20.255 丹麦 谷歌公司
写了个简单Python程序,使用二分法检索这个IP库。实际使用时启动为daemon,不用每次都加载30万条记录
import socket, struct, string
# import datetime
class SubNetwork:
def __init__(self, p, m, n):
self.portion = p
self.end = m
self.name = n
def __str__(self):
return '%d %s %s %s' % (self.portion,
socket.inet_ntoa(struct.pack('>I', self.portion)),
socket.inet_ntoa(struct.pack('>I', self.end)),
self.name)
class IpLibrary:
def __init__(self):
self.list = []
def Find(self, ips):
ip = struct.unpack('>I', socket.inet_pton(socket.AF_INET, ips))[0]
low = 0
high = len(self.list)
while (low <= high):
m = (low+high)/2
if m >= len(self.list):
return None #self.list[-1]
mv = self.list[m]
if ip > mv.portion and ip < mv.end:
# print '%d got (%d < %d < %d)' % (m, mv.portion, ip, mv.end)
return mv
else:
if ip > mv.end:
low = m + 1
else:
high = m -1
# print '%d (%d %d)' % (m, ip, mv.end)
return mv
def Split(self, line, sep):
arr = string.split(line, sep)
ret = []
for i in arr:
if i and i != '\n':
ret.append(i)
return ret
def Load(self, filename):
c = 0
f = open(filename, 'r')
for i in f:
c = c + 1
arr = self.Split(i, ' ')
if len(arr) < 3:
continue
# >I mean big-endian unsigned int
p = struct.unpack('>I', socket.inet_pton(socket.AF_INET, arr[0]))
m = struct.unpack('>I', socket.inet_pton(socket.AF_INET, arr[1]))
name = string.join(arr[2:])
sn = SubNetwork(p[0], m[0], string.replace(name, '\n', ''))
self.list.append(sn)
# if c > 200:
# break
def Load(filename):
global _lib
_lib.Load(filename)
def Query(ips):
global _lib
# t = datetime.datetime.now()
r = _lib.Find(ips)
return r
# print 'query %s, result: %s, used: %s' % (
# ips, r, str(datetime.datetime.now() - t))
if __name__ == "__main__":
_lib.Load('ipsu.txt')
Query('1.155.3.3')
Query('0.0.3.3')
Query('255.255.3.3')
Query('0.0.0.0')
Query('218.0.4.137')
Query('218.0.5.0')
需要注意的是,代码中的 >
struct.unpack('>I', ...)
>I 的意思是 big-endian unsigned int
实际使用时,基本都在30毫秒左右返回结果