优化ip2region查询

This commit is contained in:
Jing Ling
2020-08-23 16:30:20 +08:00
parent d4d6b93d54
commit 463c3d9173
2 changed files with 36 additions and 11 deletions
+33 -7
View File
@@ -10,6 +10,8 @@ import socket
import struct import struct
import sys import sys
from config import settings
class IpRegInfo(object): class IpRegInfo(object):
__INDEX_BLOCK_LENGTH = 12 __INDEX_BLOCK_LENGTH = 12
@@ -39,7 +41,8 @@ class IpRegInfo(object):
self.__dbBinStr = self.__f.read() # read all the contents in file self.__dbBinStr = self.__f.read() # read all the contents in file
self.__indexSPtr = self.get_long(self.__dbBinStr, 0) self.__indexSPtr = self.get_long(self.__dbBinStr, 0)
self.__indexLPtr = self.get_long(self.__dbBinStr, 4) self.__indexLPtr = self.get_long(self.__dbBinStr, 4)
self.__indexCount = int((self.__indexLPtr - self.__indexSPtr) / self.__INDEX_BLOCK_LENGTH) + 1 self.__indexCount = int((self.__indexLPtr - self.__indexSPtr) /
self.__INDEX_BLOCK_LENGTH) + 1
l, h, data_ptr = (0, self.__indexCount, 0) l, h, data_ptr = (0, self.__indexCount, 0)
while l <= h: while l <= h:
@@ -67,14 +70,16 @@ class IpRegInfo(object):
" binary search method " binary search method
" param: ip " param: ip
""" """
if not ip.isdigit(): ip = self.ip2long(ip) if not ip.isdigit():
ip = self.ip2long(ip)
if self.__indexCount == 0: if self.__indexCount == 0:
self.__f.seek(0) self.__f.seek(0)
super_block = self.__f.read(8) super_block = self.__f.read(8)
self.__indexSPtr = self.get_long(super_block, 0) self.__indexSPtr = self.get_long(super_block, 0)
self.__indexLPtr = self.get_long(super_block, 4) self.__indexLPtr = self.get_long(super_block, 4)
self.__indexCount = int((self.__indexLPtr - self.__indexSPtr) / self.__INDEX_BLOCK_LENGTH) + 1 self.__indexCount = int((self.__indexLPtr - self.__indexSPtr) /
self.__INDEX_BLOCK_LENGTH) + 1
l, h, data_ptr = (0, self.__indexCount, 0) l, h, data_ptr = (0, self.__indexCount, 0)
while l <= h: while l <= h:
@@ -208,10 +213,9 @@ class IpRegInfo(object):
self.__f.seek(data_ptr) self.__f.seek(data_ptr)
data = self.__f.read(data_len) data = self.__f.read(data_len)
return { info = {"city_id": self.get_long(data, 0),
"city_id": self.get_long(data, 0), "region": data[4:].decode('utf-8')}
"region": data[4:] return info
}
@staticmethod @staticmethod
def ip2long(ip): def ip2long(ip):
@@ -244,3 +248,25 @@ class IpRegInfo(object):
self.__dbBinStr = None self.__dbBinStr = None
self.__headerPtr = None self.__headerPtr = None
self.__headerSip = None self.__headerSip = None
class IpRegData(IpRegInfo):
def __init__(self):
path = settings.data_storage_dir.joinpath('ip2region.db')
IpRegInfo.__init__(self, path)
def query(self, ip, algorithm='memory'):
algorithms = ['memory', 'binary', 'btree']
if algorithm not in algorithms:
raise Exception(f"Only three query algorithms are supported: {algorithms}")
if algorithm == 'memory':
result = self.memory_search(ip)
elif algorithm == 'binary':
result = self.binary_search(ip)
else:
result = self.btree_search(ip)
addr_list = result.get('region').split('|')
isp = addr_list[-1]
addr = ''.join(filter(lambda x: x != '0', addr_list[:-1]))
info = {'addr': addr, 'isp': isp}
return info
+3 -4
View File
@@ -6,13 +6,12 @@ from config import settings
from common import utils from common import utils
from common.ipasn import IPAsnInfo from common.ipasn import IPAsnInfo
from common.ipgeo import IpGeoInfo from common.ipgeo import IpGeoInfo
from common.ipreg import IpRegInfo from common.ipreg import IpRegData
ip_asn = IPAsnInfo() ip_asn = IPAsnInfo()
ip_geo = IpGeoInfo() ip_geo = IpGeoInfo()
db_path = settings.data_storage_dir.joinpath('ip2region.db') ip_reg = IpRegData()
ip_reg = IpRegInfo(db_path)
def filter_subdomain(data): def filter_subdomain(data):
@@ -107,7 +106,7 @@ def gen_infos(data, qname, info, infos):
f'{ip_geo.get_region(ip)} ' \ f'{ip_geo.get_region(ip)} ' \
f'{ip_geo.get_city(ip)}' f'{ip_geo.get_city(ip)}'
locs.append(loc) locs.append(loc)
reg = ip_reg.memory_search(ip).get('region').decode('utf-8') reg = ip_reg.query(ip).get('addr')
regs.append(reg) regs.append(reg)
info['resolve'] = 1 info['resolve'] = 1
info['reason'] = 'OK' info['reason'] = 'OK'