首页 > 其他分享 >纯真IP库查询方法(2024-6-19更新qqwry.dat后无法查询,修改代码)

纯真IP库查询方法(2024-6-19更新qqwry.dat后无法查询,修改代码)

时间:2024-06-24 11:53:36浏览次数:3  
标签:ip index begin 19 IP self 2024 offset data

2024-6-19更新qqwry.dat后使用pthon38那篇文章里的代码无法查询,使用pythom2的代码,修改之后python3可用,将文件放到工程里查询,不用Lib库里的。

修改后的qqwry.py如下,python3可用。

coding=utf-8

for Python 2.7

为https://pypi.python.org/pypi/qqwry-py3的Python 2版

版本:2017-10-25

用法

============

from qqwry import QQwry

q = QQwry()

q.load_file('qqwry.dat')

result = q.lookup('8.8.8.8')

解释q.load_file(filename, loadindex=False)函数

--------------

加载qqwry.dat文件。成功返回True,失败返回False。

参数filename可以是qqwry.dat的文件名(str类型),也可以是bytes类型的文件内容。

当参数loadindex=False时(默认参数):

程序行为:把整个文件读入内存,从中搜索

加载速度:很快,0.004 秒

进程内存:较少,16.9 MB

查询速度:较慢,5.3 万次/秒

使用建议:适合桌面程序、大中小型网站

当参数loadindex=True时:

程序行为:把整个文件读入内存。额外加载索引,把索引读入更快的数据结构

加载速度:★★★非常慢,因为要额外加载索引,0.78 秒★★★

进程内存:较多,22.0 MB

查询速度:较快,18.0 万次/秒

使用建议:仅适合高负载服务器

(以上是在i3 3.6GHz, Win10, Python 3.6.2 64bit,qqwry.dat 8.86MB时的数据)

解释q.lookup('8.8.8.8')函数

--------------

找到则返回一个含有两个字符串的元组,如:('国家', '省份')

没有找到结果,则返回一个None

解释q.clear()函数

--------------

清空已加载的qqwry.dat

再次调用load_file时不必执行q.clear()

解释q.is_loaded()函数

--------------

q对象是否已加载数据,返回True或False

解释q.get_lastone()函数

--------------

返回最后一条数据,最后一条通常为数据的版本号

没有数据则返回一个None

import array
import bisect
import struct
import socket

all = ('QQwry',)

def int3(data, offset):
return data[offset] + (data[offset+1]<< 8) +
(data[offset+2] << 16)

def int4(data, offset):
return data[offset] + (data[offset+1] << 8) +
(data[offset+2] << 16) + (data[offset+3] << 24)

class QQwry:
def init(self):
self.clear()

def clear(self):
    self.idx1 = None
    self.idx2 = None
    self.idxo = None
    
    self.data = None
    self.index_begin = -1
    self.index_end = -1
    self.index_count = -1
    
    self.__fun = None
    
def load_file(self, filename, loadindex=False):
    self.clear()
    
    
    # read file
    try:
        with open(filename, 'rb') as f:
            self.data = buffer = f.read()
    except Exception as e:
        print(u'open file failed:', e)
        self.clear()
        return False
    
    if self.data == None:
        print(u'%s load failed' % filename)
        self.clear()
        return False
    
                
    if len(buffer) < 8:
        print(u'%s load failed, file only %d bytes' % 
              (filename, len(buffer))
              )
        self.clear()
        return False            
    
    # index range
    index_begin = int4(buffer, 0)
    index_end = int4(buffer, 4)
    if index_begin > index_end or \
       (index_end - index_begin) % 7 != 0 or \
       index_end + 7 > len(buffer):
        print(u'%s index error' % filename)
        self.clear()
        return False
    
    self.index_begin = index_begin
    self.index_end = index_end
    self.index_count = (index_end - index_begin) // 7 + 1
    
    if not loadindex:
        print(u'%s %s bytes, %d segments. without index.' %
              (filename, format(len(buffer),','), self.index_count)
             )
        self.__fun = self.__raw_search
        return True

    # load index
    self.idx1 = array.array('L')
    self.idx2 = array.array('L')
    self.idxo = array.array('L')
    
    try:
        for i in range(self.index_count):
            ip_begin = int4(buffer, index_begin + i*7)
            offset = int3(buffer, index_begin + i*7 + 4)
            
            # load ip_end
            ip_end = int4(buffer, offset)
            
            self.idx1.append(ip_begin)
            self.idx2.append(ip_end)
            self.idxo.append(offset+4)
    except:
        print(u'%s load index error' % filename)
        self.clear()
        return False

    print(u'%s %s bytes, %d segments. with index.' % 
          (filename, format(len(buffer),','), len(self.idx1))
           )
    self.__fun = self.__index_search
    return True
    
def __get_addr(self, offset):
    # mode 0x01, full jump
    mode = self.data[offset]
    if mode == 1:
        offset = int3(self.data, offset+1)
        mode = self.data[offset]
    
    # country
    if mode == 2:
        off1 = int3(self.data, offset+1)
        c = self.data[off1:self.data.index(b'\x00', off1)]
        offset += 4
    else:
        c = self.data[offset:self.data.index(b'\x00', offset)]
        offset += len(c) + 1

    # province
    if self.data[offset] == 2:
        offset = int3(self.data, offset+1)
    p = self.data[offset:self.data.index(b'\x00', offset)]
    
    return c.decode('gb18030', errors='replace'), \
           p.decode('gb18030', errors='replace')
        
def lookup(self, ip_str):
    try:
        ip = struct.unpack(">I", socket.inet_aton(ip_str))[0]
        return self.__fun(ip)
    except:
        return None
    
def __raw_search(self, ip):
    l = 0
    r = self.index_count
    
    while r - l > 1:
        m = (l + r) // 2
        offset = self.index_begin + m * 7
        new_ip = int4(self.data, offset)

        if ip < new_ip:
            r = m
        else:
            l = m
    
    offset = self.index_begin + 7 * l
    ip_begin = int4(self.data, offset)
    
    offset = int3(self.data, offset+4)
    ip_end = int4(self.data, offset)
    
    if ip_begin <= ip <= ip_end:
        return self.__get_addr(offset+4)
    else:
        return None

def __index_search(self, ip):
    posi = bisect.bisect_right(self.idx1, ip) - 1
    
    if posi >= 0 and self.idx1[posi] <= ip <= self.idx2[posi]:
        return self.__get_addr(self.idxo[posi])
    else:
        return None
    
def is_loaded(self):
    return self.__fun != None
    
def get_lastone(self):
    try:
        offset = int3(self.data, self.index_end+4)
        return self.__get_addr(offset+4)
    except:
        return None

if name == 'main':
import sys
if len(sys.argv) > 1:
fn = u'qqwry.dat'
q = QQwry()
q.load_file(fn)

    for ipstr in sys.argv[1:]:
        s = q.lookup(ipstr)
        if s is not None:
            print('%s\n%s, %s' % (ipstr, s[0], s[1]))
        else:
            print('%s\nNone')
else:
    print(u'请以查询ip作为参数运行')

标签:ip,index,begin,19,IP,self,2024,offset,data
From: https://www.cnblogs.com/luhongwei168/p/18264749

相关文章

  • XAMPP Windows PHP-CGI 代码执行漏洞(CVE-2024-4577) | Goby漏洞预警
    漏洞描述:PHP是一种在服务器端执行的脚本语言,在PHP的8.3.8版本之前存在命令执行漏洞,由于Windows的“Best-FitMapping”特性,在处理查询字符串时,非ASCII字符可能被错误地映射为破折号(-),导致命令行参数解析错误,当php_cgi运行在Windows平台上,且代码页为繁体中文、简......
  • 2024年商业管理与金融创新国际会议(BMFI 2024)
    2024年商业管理与金融创新国际会议(BMFI2024)2024InternationalConferenceonBusinessManagementandFinancialInnovation【重要信息】大会地点:上海大会官网:http://www.icbmfi.com投稿邮箱:[email protected]【注意:将稿件Word+PDF上传至邮箱,邮件正文请备注“BMFI......
  • 华为在 2024 年 6 月 21 日的华为开发者大会上,华为终端 BG 软件部总裁龚体正式官宣了
    华为在2024年6月21日的华为开发者大会上,华为终端BG软件部总裁龚体正式官宣了华为自研仓颉编程语言,并发布了HarmonyOSNEXT仓颉语言开发者预览版。仓颉编程语言文件后缀名为.cj,以下是第一个入门代码输出:你好,仓颉。仓颉编程语言的名字来自“仓颉造字”。仓......
  • 常上来看看-20240624
    【今天又是什么日子】今天是2024年6月24日,一个普通的周一或者也可以有另外的说法,今天是老婆去深圳后的第一个工作日今天有一些地方开始出高考成绩了【上次来是什么时候】上次来刚好是高考的时候,真是巧了【为啥突然记得来了】因为有些计划要变了【之前想干啥,还记得吗】之......
  • Klipper RP2040 display ssd1306 0.96 屏幕配置
    接线屏幕接线parampinGNDGNDVCCVCCSCLSDA编码器接线parampinGNDGNDEN1VCCEN2CLklipper配置#显示屏及旋钮[display]lcd_type:ssd1306#i2c_bus:i2c0dencoder_pins:^gpio24,^gpio23encoder_steps_per_detent:2c......
  • AI大模型企业应用实战(19)-RAG应用框架和解析器
    1开源解析和拆分文档第三方工具去对文件解析拆分,将文件内容给提取出来,并将我们的文档内容去拆分成一个小的chunk。常见的PDFwordmarkdown,JSON、HTML。都可以有很好的一些模块去把这些文件去进行一个东西去提取。1.1优势支持丰富的文档类型每种文档多样化选择与开源框......
  • [图解]企业应用架构模式2024新译本讲解17-活动记录1
    100:00:01,070-->00:00:04,180下一个我们要说的就是200:00:04,190-->00:00:06,740活动记录模式了300:00:07,640-->00:00:11,210同样是数据源架构模式400:00:12,300-->00:00:18,480里面的一个,活动记录500:00:18,490-->00:00:21,710我们看这里,定义,active......
  • 华为HCIP Datacom H12-821 卷11
    1.多选题OSPF包括哪些报文类型?A、LinkStateDDB、HelloC、LinkStateRequestD、DatabaseDescription正确答案: B,C,D解析:在OSPF协议中,报文类型分为:hello、DD、LSR、LSU、LSAck。所以正确答案是“Hello”、“DatabaseDescription”、“LinkStateRequest”......
  • 【2024-06-12】自我烦恼
    20:00现在我们做中国人要顶勇敢,什么都不怕,什么都顶有决心才好。                                                 ——林徽因昨天一整天,心思都不在工作,打开手机,插着充......
  • 【2024-06-13】端午叙事
    20:00让我们天亮就起,按时吃早餐,心平气和而又心中坦然,任人来人往,任钟鸣孩子闹一下定决心好好地过一天。我们为什么要被击垮甚至自甘堕落呢?                                           ......