核心代碼:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from bisect import bisect
_LIST1, _LIST2 = [], []
_INIT = False
ip2int = lambda ip_str: reduce(lambda a, b: (a << 8) + b, [int(i) for i in ip_str.split('.')])
def _init():
global _LIST, _INIT
if not _INIT:
for l in open('ipdata.txt', 'rb'):
ip1, ip2 = l.split()[:2]
addr = ' '.join(l.split()[2:])
ip1, ip2 = ip2int(ip1), ip2int(ip2)
_LIST1.append(ip1)
_LIST2.append((ip1, ip2, addr))
_INIT = True
def ip_from(ip):
_init()
i = ip2int(ip)
idx = bisect(_LIST1, i)
assert(idx > 0)
if len(_LIST1) <= idx:
return u'unknown ip address %s' % ip
else:
frm, to ,addr = _LIST2[idx - 1]
if frm <= i <= to:
return addr
else:
return u'unknown ip address %s' % ip
if __name__ == '__main__':
print ip_from('115.238.54.106')
print ip_from('220.181.29.160')
print ip_from('115.238.54.107')
print ip_from('8.8.8.8')
代碼打包下載 http://xiazai.jb51.net/201105/yuanma/ipaddress.7z
接下來為大家分享更完美的代碼:
#!/usr/bin/env python
# coding: utf-8
'''用Python腳本查詢純真IP庫
QQWry.Dat的格式如下:
+----------+
| 文件頭 | (8字節)
+----------+
| 記錄區 | (不定長)
+----------+
| 索引區 | (大小由文件頭決定)
+----------+
文件頭:4字節開始索引偏移值+4字節結尾索引偏移值
記錄區: 每條IP記錄格式 ==> IP地址[國家信息][地區信息]
對于國家記錄,可以有三種表示方式:
字符串形式(IP記錄第5字節不等于0x01和0x02的情況),
重定向模式1(第5字節為0x01),則接下來3字節為國家信息存儲地的偏移值
重定向模式(第5字節為0x02),
對于地區記錄,可以有兩種表示方式: 字符串形式和重定向
最后一條規則:重定向模式1的國家記錄后不能跟地區記錄
索引區: 每條索引記錄格式 ==> 4字節起始IP地址 + 3字節指向IP記錄的偏移值
索引區的IP和它指向的記錄區一條記錄中的IP構成一個IP范圍。查詢信息是這個
范圍內IP的信息
'''
import sys
import socket
from struct import pack, unpack
class IPInfo(object):
'''QQWry.Dat數據庫查詢功能集合
'''
def __init__(self, dbname):
''' 初始化類,讀取數據庫內容為一個字符串,
通過開始8字節確定數據庫的索引信息'''
self.dbname = dbname
# f = file(dbname, 'r')
# Demon注:在Windows下用'r'會有問題,會把\r\n轉換成\n
# 詳見http://demon.tw/programming/python-open-mode.html
# 還有Python文檔中不提倡用file函數來打開文件,推薦用open
f = open(dbname, 'rb')
self.img = f.read()
f.close()
# QQWry.Dat文件的開始8字節是索引信息,前4字節是開始索引的偏移值,
# 后4字節是結束索引的偏移值。
# (self.firstIndex, self.lastIndex) = unpack('II', self.img[:8])
# Demon注:unpack默認使用的endian是和機器有關的
# Intel x86和AMD64(x86-64)是little-endian
# Motorola 68000和PowerPC G5是big-endian
# 而純真數據庫全部采用了little-endian字節序
# 所以在某些big-endian的機器上原代碼會出錯
(self.firstIndex, self.lastIndex) = unpack('
用Python腳本查詢純真IP庫QQWry.dat(Demon修改版)
由于要用 Python 讀取一個和純真IP數據庫 QQWry.dat 格式差不多的 IPv6 數據庫,所以在網上搜索了一下,在 LinuxTOY 看到了一個 Python 腳本,發現有一些小小的問題,于是修改了一下。
#!/usr/bin/env python
# coding: utf-8
# from: http://linuxtoy.org/files/pyip.py
# Blog: http://linuxtoy.org/archives/python-ip.html
# Modified by Demon
# Blog: http://demon.tw/programming/python-qqwry-dat.html
'''用Python腳本查詢純真IP庫
QQWry.Dat的格式如下:
+----------+
| 文件頭 | (8字節)
+----------+
| 記錄區 | (不定長)
+----------+
| 索引區 | (大小由文件頭決定)
+----------+
文件頭:4字節開始索引偏移值+4字節結尾索引偏移值
記錄區: 每條IP記錄格式 ==> IP地址[國家信息][地區信息]
對于國家記錄,可以有三種表示方式:
字符串形式(IP記錄第5字節不等于0x01和0x02的情況),
重定向模式1(第5字節為0x01),則接下來3字節為國家信息存儲地的偏移值
重定向模式(第5字節為0x02),
對于地區記錄,可以有兩種表示方式: 字符串形式和重定向
最后一條規則:重定向模式1的國家記錄后不能跟地區記錄
索引區: 每條索引記錄格式 ==> 4字節起始IP地址 + 3字節指向IP記錄的偏移值
索引區的IP和它指向的記錄區一條記錄中的IP構成一個IP范圍。查詢信息是這個
范圍內IP的信息
'''
import sys
import socket
from struct import pack, unpack
class IPInfo(object):
'''QQWry.Dat數據庫查詢功能集合
'''
def __init__(self, dbname):
''' 初始化類,讀取數據庫內容為一個字符串,
通過開始8字節確定數據庫的索引信息'''
self.dbname = dbname
# f = file(dbname, 'r')
# Demon注:在Windows下用'r'會有問題,會把\r\n轉換成\n
# 詳見http://demon.tw/programming/python-open-mode.html
# 還有Python文檔中不提倡用file函數來打開文件,推薦用open
f = open(dbname, 'rb')
self.img = f.read()
f.close()
# QQWry.Dat文件的開始8字節是索引信息,前4字節是開始索引的偏移值,
# 后4字節是結束索引的偏移值。
# (self.firstIndex, self.lastIndex) = unpack('II', self.img[:8])
# Demon注:unpack默認使用的endian是和機器有關的
# Intel x86和AMD64(x86-64)是little-endian
# Motorola 68000和PowerPC G5是big-endian
# 而純真數據庫全部采用了little-endian字節序
# 所以在某些big-endian的機器上原代碼會出錯
(self.firstIndex, self.lastIndex) = unpack('
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

