专栏首页python3python3通过纯真IP数据库查询IP

python3通过纯真IP数据库查询IP

在网上看到的别人写的python2的代码,修改成了python3。

把纯真IP数据库文件qqwry.dat放到czip.py同一目录下。

  1 #! /usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 # filename: czip.py
  4 
  5 
  6 import socket
  7 import struct
  8 
  9 
 10 class CzIp:
 11     def __init__(self, db_file='qqwry.dat'):
 12         self.f_db = open(db_file, "rb")
 13         bs = self.f_db.read(8)
 14         (self.first_index, self.last_index) = struct.unpack('II', bs)
 15         self.index_count = int((self.last_index - self.first_index) / 7 + 1)
 16         self.cur_start_ip = None
 17         self.cur_end_ip_offset = None
 18         self.cur_end_ip = None
 19         # print(self.get_version(), " 纪录总数: %d 条 "%(self.index_count))
 20 
 21     def get_version(self):
 22         '''
 23         获取版本信息,最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
 24         :return: str
 25         '''
 26         s = self.get_addr_by_ip(0xffffff00)
 27         return s
 28 
 29     def _get_area_addr(self, offset=0):
 30         if offset:
 31             self.f_db.seek(offset)
 32         bs = self.f_db.read(1)
 33         (byte,) = struct.unpack('B', bs)
 34         if byte == 0x01 or byte == 0x02:
 35             p = self.getLong3()
 36             if p:
 37                 return self.get_offset_string(p)
 38             else:
 39                 return ""
 40         else:
 41             self.f_db.seek(-1, 1)
 42             return self.get_offset_string(offset)
 43 
 44     def _get_addr(self, offset):
 45         '''
 46         获取offset处记录区地址信息(包含国家和地区)
 47         如果是中国ip,则是 "xx省xx市 xxxxx地区" 这样的形式
 48         (比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
 49         :param offset:
 50         :return:str
 51         '''
 52         self.f_db.seek(offset + 4)
 53         bs = self.f_db.read(1)
 54         (byte,) = struct.unpack('B', bs)
 55         if byte == 0x01:    # 重定向模式1
 56             country_offset = self.getLong3()
 57             self.f_db.seek(country_offset)
 58             bs = self.f_db.read(1)
 59             (b,) = struct.unpack('B', bs)
 60             if b == 0x02:   
 61                 country_addr = self.get_offset_string(self.getLong3())
 62                 self.f_db.seek(country_offset + 4)
 63             else:   
 64                 country_addr = self.get_offset_string(country_offset)
 65             area_addr = self._get_area_addr()
 66         elif byte == 0x02:  # 重定向模式2
 67             country_addr = self.get_offset_string(self.getLong3())
 68             area_addr = self._get_area_addr(offset + 8)
 69         else:   # 字符串模式
 70             country_addr = self.get_offset_string(offset + 4)
 71             area_addr = self._get_area_addr()
 72         return country_addr + " " + area_addr
 73 
 74     def dump(self, first, last):
 75         '''
 76         打印数据库中索引为first到索引为last(不包含last)的记录
 77         :param first:
 78         :param last:
 79         :return:
 80         '''
 81         if last > self.index_count:
 82             last = self.index_count
 83         for index in range(first, last):
 84             offset = self.first_index + index * 7
 85             self.f_db.seek(offset)
 86             buf = self.f_db.read(7)
 87             (ip, of1, of2) = struct.unpack("IHB", buf)
 88             address = self._get_addr(of1 + (of2 << 16))
 89             print("%d %s %s" % (index, self.ip2str(ip), address))
 90 
 91     def _set_ip_range(self, index):
 92         offset = self.first_index + index * 7
 93         self.f_db.seek(offset)
 94         buf = self.f_db.read(7)
 95         (self.cur_start_ip, of1, of2) = struct.unpack("IHB", buf)
 96         self.cur_end_ip_offset = of1 + (of2 << 16)
 97         self.f_db.seek(self.cur_end_ip_offset)
 98         buf = self.f_db.read(4)
 99         (self.cur_end_ip,) = struct.unpack("I", buf)
100 
101     def get_addr_by_ip(self, ip):
102         '''
103         通过ip查找其地址
104         :param ip: (int or str)
105         :return: str
106         '''
107         if type(ip) == str:
108             ip = self.str2ip(ip)
109         L = 0
110         R = self.index_count - 1
111         while L < R - 1:
112             M = int((L + R) / 2)
113             self._set_ip_range(M)
114             if ip == self.cur_start_ip:
115                 L = M
116                 break
117             if ip > self.cur_start_ip:
118                 L = M
119             else:
120                 R = M
121         self._set_ip_range(L)
122         # version information, 255.255.255.X, urgy but useful
123         if ip & 0xffffff00 == 0xffffff00:
124             self._set_ip_range(R)
125         if self.cur_start_ip <= ip <= self.cur_end_ip:
126             address = self._get_addr(self.cur_end_ip_offset)
127         else:
128             address = "未找到该IP的地址"
129         return address
130 
131     def get_ip_range(self, ip):
132         '''
133         返回ip所在记录的IP段
134         :param ip: ip(str or int)
135         :return: str
136         '''
137         if type(ip) == str:
138             ip = self.str2ip(ip)
139         self.get_addr_by_ip(ip)
140         range = self.ip2str(self.cur_start_ip) + ' - ' \
141                 + self.ip2str(self.cur_end_ip)
142         return range
143 
144     def get_offset_string(self, offset=0):
145         '''
146         获取文件偏移处的字符串(以'\0'结尾)
147         :param offset: 偏移
148         :return: str
149         '''
150         if offset:
151             self.f_db.seek(offset)
152         bs = b''
153         ch = self.f_db.read(1)
154         (byte,) = struct.unpack('B', ch)
155         while byte != 0:
156             bs += ch
157             ch = self.f_db.read(1)
158             (byte,) = struct.unpack('B', ch)
159         return bs.decode('gbk')
160 
161     def ip2str(self, ip):
162         '''
163         整数IP转化为IP字符串
164         :param ip:
165         :return:
166         '''
167         return str(ip >> 24) + '.' + str((ip >> 16) & 0xff) + '.' + str((ip >> 8) & 0xff) + '.' + str(ip & 0xff)
168 
169     def str2ip(self, s):
170         '''
171         IP字符串转换为整数IP
172         :param s:
173         :return:
174         '''
175         (ip,) = struct.unpack('I', socket.inet_aton(s))
176         return ((ip >> 24) & 0xff) | ((ip & 0xff) << 24) | ((ip >> 8) & 0xff00) | ((ip & 0xff00) << 8)
177 
178     def getLong3(self, offset=0):
179         '''
180         3字节的数值
181         :param offset:
182         :return:
183         '''
184         if offset:
185             self.f_db.seek(offset)
186         bs = self.f_db.read(3)
187         (a, b) = struct.unpack('HB', bs)
188         return (b << 16) + a
189 
190 
191 
192 if __name__ == '__main__':
193     cz = CzIp()
194     print(cz.get_version())
195     ip = '14.215.177.39'
196     print(cz.get_ip_range(ip))
197     print(cz.get_addr_by_ip(ip))

运行结果:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python实现的简单点对点(p2p)聊

    点对点聊天首先是基于多线程的网络编程,其次就是将每一个连接都保存为一个具有独一属性的对象并添加到连接列表中,对于每一个连接对象发送过来的信息必须要包含主要的三项...

    py3study
  • python面向对象

    类中把某些属性和方法隐藏起来(或者说定义成私有的),只在类的内部使用、外部无法访问

    py3study
  • Python实现布隆过滤器

    转载自:http://blog.csdn.net/demon24/article/details/8537665

    py3study
  • python爬虫学习之用Python抢火车票的简单小程序

    Python现在非常火,语法简单而且功能强大,很多同学都想学Python!所以小的给各位看官们准备了高价值Python学习视频教程及相关电子版书籍,欢迎前来领取...

    python学习教程
  • Weex 事件传递的那些事儿

    在前两篇文章里面分别谈了Weex如何在Native端初始化的和Weex是如何高效的渲染Native的原生UI的。Native这边还缺一块,那就是Native产生...

    一缕殇流化隐半边冰霜
  • 强化学习(十一) Prioritized Replay DQN

        在强化学习(十)Double DQN (DDQN)中,我们讲到了DDQN使用两个Q网络,用当前Q网络计算最大Q值对应的动作,用目标Q网络计算这个最大动作...

    刘建平Pinard
  • R条件语句

    但如果你有一长串 if 语句,那么就要考虑重写了。重写的一种方法是使用 switch() 函数, 它先对第一个参数求值,然后按照名称或位置在后面的参数列表中匹...

    生信编程日常
  • R语言写2048游戏

           2048 是一款益智游戏,只需要用方向键让两两相同的数字碰撞就会诞生一个翻倍的数字,初始数字由 2 或者 4 构成,直到游戏界面全部被填满,游戏结...

    用户1680321
  • Android 应用安装过程分析

    在之前的文章中,我们对PakageManagerService启动流程分析 做了简单的介绍,并对PMS系统的启动流程做了详细的解析。上面只是说到了Android...

    xiangzhihong
  • COCO 数据集目标检测等相关评测指标

    [3] - APAPAP (所有 10 个 IoU 阈值和全部 80 个类别的平均值) 作为最终 COCO竞赛胜者的标准. 在考虑目标检测器再 COCO 上的性...

    AIHGF

扫码关注云+社区

领取腾讯云代金券