Skip to content

Commit b9d8857

Browse files
committed
update
1 parent ccea8cf commit b9d8857

File tree

8 files changed

+228
-1
lines changed

8 files changed

+228
-1
lines changed

Diff for: .gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ __pycache__/
55

66
# C extensions
77
*.so
8-
8+
.idea
99
# Distribution / packaging
1010
.Python
1111
build/

Diff for: example.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import ipdb
2+
3+
db = ipdb.Reader("C:/WORK/tiantexin/framework/library/ip/mydata6.ipdb")
4+
print(db.find("2001:250:200::"))
5+
print(db.find_map("2001:250:200::"))
6+
7+
info = db.find_info("2a06:e881:3800::")
8+
print(info.country_name, info.region_name, info.city_name, info.owner_domain, info.isp_domain, info.latitude, info.longitude, info.timezone, info.utc_offset)

Diff for: ipdb/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
:copyright: ©2018 by IPIP.net
4+
"""
5+
6+
from .database import Reader

Diff for: ipdb/database.py

+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
:copyright: ©2018 by IPIP.net
4+
"""
5+
6+
import ipaddress
7+
import json
8+
from .meta import MetaData
9+
from .info import IPInfo
10+
from .util import bytes2long
11+
12+
13+
class Reader:
14+
15+
meta = {}
16+
data = b""
17+
18+
file = False
19+
file_size = 0
20+
21+
v4offset = 0
22+
v6offsetCache = {}
23+
24+
def __init__(self, name):
25+
self.file = open(name, "rb")
26+
self.data = self.file.read()
27+
self.file_size = len(self.data)
28+
29+
meta_length = bytes2long(self.data[0], self.data[1], self.data[2], self.data[3])
30+
meta = json.loads(self.data[4:meta_length+4])
31+
32+
self.meta = MetaData(**meta)
33+
self.data = self.data[4+meta_length:]
34+
35+
def _find_node(self, ip):
36+
37+
if ip.version == 6:
38+
bit_count = 128
39+
else:
40+
bit_count = 32
41+
42+
i = 0
43+
node = 0
44+
key = ip.packed[0:2]
45+
if bit_count == 32:
46+
if self.v4offset == 0:
47+
i = 0
48+
while i < 96:
49+
if i >= 80:
50+
node = self.read_node(node, 1)
51+
else:
52+
node = self.read_node(node, 0)
53+
i += 1
54+
self.v4offset = node
55+
else:
56+
node = self.v4offset
57+
else:
58+
val = self.v6offsetCache.get(key, -1)
59+
if val > -1:
60+
i = 16
61+
node = val
62+
63+
while i < bit_count:
64+
if node > self.meta.node_count:
65+
break
66+
node = self.read_node(node, (1 & (ip.packed[i >> 3] >> 7 - (i % 8))))
67+
i += 1
68+
if i == 16:
69+
self.v6offsetCache[key] = node
70+
71+
return node
72+
73+
def read_node(self, node, idx):
74+
off = idx * 4 + node * 8
75+
return bytes2long(self.data[off], self.data[off + 1], self.data[off + 2], self.data[off + 3])
76+
77+
def _resolve(self, node):
78+
resolved = node - self.meta.node_count + self.meta.node_count * 8
79+
size = bytes2long(0, 0, self.data[resolved], self.data[resolved + 1])
80+
return self.data[resolved+2:resolved+2 + size]
81+
82+
def find(self, addr, language = "CN"):
83+
node = self._find_node(ipaddress.ip_address(addr))
84+
if node is None:
85+
return None
86+
87+
bytes = self._resolve(node)
88+
if bytes is None:
89+
return None
90+
91+
tmp = bytes.decode("utf-8").split("\t")
92+
93+
off = self.meta.languages.get(language)
94+
if off is None:
95+
return None
96+
97+
return tmp[off:off+len(self.meta.fields)]
98+
99+
def find_map(self, addr, language = 'CN'):
100+
loc = self.find(addr, language)
101+
if loc is None:
102+
return None
103+
m = {}
104+
for idx, value in enumerate(self.meta.fields):
105+
m[value] = loc[idx]
106+
return m
107+
108+
def find_info(self, addr, language = 'CN'):
109+
m = self.find_map(addr, language)
110+
if m is None:
111+
return None
112+
return IPInfo(**m)

Diff for: ipdb/info.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
:copyright: ©2018 by IPIP.net
4+
"""
5+
6+
7+
class IPInfo(object):
8+
9+
country_name = ""
10+
region_name = ""
11+
city_name = ""
12+
owner_domain = ""
13+
isp_domain = ""
14+
latitude = ""
15+
longitude = ""
16+
timezone = ""
17+
utc_offset = ""
18+
china_admin_code = ""
19+
idd_code = ""
20+
country_code = ""
21+
continent_code = ""
22+
idc = ""
23+
base_station = ""
24+
country_code3 = ""
25+
european_union = ""
26+
currency_code = ""
27+
currency_name = ""
28+
anycast = ""
29+
30+
def __init__(self, **kwargs):
31+
self._map = kwargs
32+
for key in self._map:
33+
self.__setattr__(key, self._map[key])
34+
35+
def __getattr__(self, item):
36+
return self._map.get(item, "")

Diff for: ipdb/meta.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
:copyright: ©2018 by IPIP.net
4+
"""
5+
6+
7+
class MetaData(object):
8+
def __init__(self, **kwargs):
9+
self.fields = kwargs['fields']
10+
self.node_count = kwargs['node_count']
11+
self.total_size = kwargs['total_size']
12+
self.build = kwargs['build']
13+
self.languages = kwargs['languages']
14+
self.ip_version = kwargs['ip_version']

Diff for: ipdb/util.py

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
:copyright: ©2018 by IPIP.net
4+
"""
5+
6+
7+
import sys
8+
9+
10+
def bytes2long(a, b, c, d):
11+
return convert(a) << 24 | convert(b) << 16 | convert(c) << 8 | convert(d)
12+
13+
14+
def convert(v):
15+
if sys.version_info.major >= 3:
16+
return v
17+
else:
18+
return ord(v)

Diff for: setup.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# coding=utf-8
2+
3+
from setuptools import setup
4+
5+
setup(
6+
name='ipip-ipdb',
7+
version="0.2.0",
8+
description=(
9+
'IPIP.net 官方支持维护的 IP 数据库 ipdb 格式解析代码库'
10+
),
11+
author='IPIP.net',
12+
author_email='[email protected]',
13+
maintainer='frk',
14+
maintainer_email='[email protected]',
15+
license='Apache License Version 2.0',
16+
packages=['ipdb'],
17+
platforms=["all"],
18+
url='https://github.com/ipipdotnet/ipdb-python',
19+
classifiers=[
20+
'Development Status :: 4 - Beta',
21+
'Operating System :: OS Independent',
22+
'Intended Audience :: Developers',
23+
'Programming Language :: Python',
24+
'Programming Language :: Python :: Implementation',
25+
'Programming Language :: Python :: 2',
26+
'Programming Language :: Python :: 2.7',
27+
'Programming Language :: Python :: 3',
28+
'Programming Language :: Python :: 3.4',
29+
'Programming Language :: Python :: 3.5',
30+
'Programming Language :: Python :: 3.6',
31+
'Topic :: Software Development :: Libraries'
32+
],
33+
)

0 commit comments

Comments
 (0)