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

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。