diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a90dda7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +MANIFEST +dist diff --git a/IP/17monipdb.dat b/IP/17monipdb.dat new file mode 100644 index 0000000..a5d21b2 Binary files /dev/null and b/IP/17monipdb.dat differ diff --git a/IP/__init__.py b/IP/__init__.py new file mode 100644 index 0000000..548b1c2 --- /dev/null +++ b/IP/__init__.py @@ -0,0 +1,3 @@ +__all__ = ["find"] + +from .ip import find diff --git a/IP/ip.py b/IP/ip.py new file mode 100644 index 0000000..2b11d7a --- /dev/null +++ b/IP/ip.py @@ -0,0 +1,68 @@ +import sys + +PY2 = sys.version_info.major == 2 + +import functools +import os +import socket +import struct + +_unpack_V = lambda b: struct.unpack("L", b) +_unpack_C = lambda b: struct.unpack("B", b) + +with open(os.path.join(os.path.dirname(__file__), "17monipdb.dat"), "rb") as f: + dat = f.read() + offset, = _unpack_N(dat[:4]) + index = dat[4:offset] + + +def memoize(func): + """Memoize for functions based on memory + """ + cache = func.cache = {} + + @functools.wraps(func) + def wrapper(*args, **kwargs): + key = "{0}{1}".format(args, kwargs) + if key not in cache: + cache[key] = func(*args, **kwargs) + return cache[key] + return wrapper + + +@memoize +def _find_ip(ip): + nip = socket.inet_aton(ip) + + tmp_offset = int(ip.split(".")[0]) * 4 + start, = _unpack_V(index[tmp_offset:tmp_offset + 4]) + + index_offset = index_length = 0 + max_comp_len = offset - 1028 + start = start * 8 + 1024 + while start < max_comp_len: + if index[start:start + 4] >= nip: + index_offset, = _unpack_V( + index[start + 4:start + 7] + chr(0).encode("utf-8")) + if PY2: + index_length, = _unpack_C(index[start + 7]) + else: + index_length = index[start + 7] + break + start += 8 + + if index_offset == 0: + return + + res_offset = offset + index_offset - 1024 + return dat[res_offset:res_offset + index_length].decode("utf-8") + + +def find(ip): + try: + ip = socket.gethostbyname(ip) + except socket.gaierror: + return + + return _find_ip(ip) diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..9561fb1 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..416b6f1 --- /dev/null +++ b/README.rst @@ -0,0 +1,24 @@ +17MonIP Python Lib +================== + +IP search based on 17mon.cn, the best IP database for china. + +Source: http://tool.17mon.cn + +Install +------- + +.. code:: bash + + $ pip install 17monip + +Usage +----- + +.. code:: python + + >>> import IP + >>> IP.find("www.baidu.com") + '中国\t浙江' + >>> IP.find("127.0.0.1") + '本机地址\t本机地址' diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c56528d --- /dev/null +++ b/setup.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from distutils.core import setup + +setup( + name="17MonIP", + version="0.1.0", + description="IP search based on 17mon.cn, the best IP database for China.", + author="Lx Yu", + author_email="github@lxyu.net", + packages=["IP", ], + package_data={'IP': ['17monipdb.dat'], }, + entry_points={"console_scripts": ["ip = ip.cmd:ip", ]}, + url="http://lxyu.github.io/17monip/", + license="MIT", + long_description=open("README.rst").read(), +)