核心代碼:
#!/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字節(jié)) +----------+ | 記錄區(qū) | (不定長) +----------+ | 索引區(qū) | (大小由文件頭決定) +----------+ 文件頭:4字節(jié)開始索引偏移值+4字節(jié)結(jié)尾索引偏移值 記錄區(qū): 每條IP記錄格式 ==> IP地址[國家信息][地區(qū)信息] 對于國家記錄,可以有三種表示方式: 字符串形式(IP記錄第5字節(jié)不等于0x01和0x02的情況), 重定向模式1(第5字節(jié)為0x01),則接下來3字節(jié)為國家信息存儲(chǔ)地的偏移值 重定向模式(第5字節(jié)為0x02), 對于地區(qū)記錄,可以有兩種表示方式: 字符串形式和重定向 最后一條規(guī)則:重定向模式1的國家記錄后不能跟地區(qū)記錄 索引區(qū): 每條索引記錄格式 ==> 4字節(jié)起始IP地址 + 3字節(jié)指向IP記錄的偏移值 索引區(qū)的IP和它指向的記錄區(qū)一條記錄中的IP構(gòu)成一個(gè)IP范圍。查詢信息是這個(gè) 范圍內(nèi)IP的信息 ''' import sys import socket from struct import pack, unpack class IPInfo(object): '''QQWry.Dat數(shù)據(jù)庫查詢功能集合 ''' def __init__(self, dbname): ''' 初始化類,讀取數(shù)據(jù)庫內(nèi)容為一個(gè)字符串, 通過開始8字節(jié)確定數(shù)據(jù)庫的索引信息''' self.dbname = dbname # f = file(dbname, 'r') # Demon注:在Windows下用'r'會(huì)有問題,會(huì)把\r\n轉(zhuǎn)換成\n # 詳見http://demon.tw/programming/python-open-mode.html # 還有Python文檔中不提倡用file函數(shù)來打開文件,推薦用open f = open(dbname, 'rb') self.img = f.read() f.close() # QQWry.Dat文件的開始8字節(jié)是索引信息,前4字節(jié)是開始索引的偏移值, # 后4字節(jié)是結(jié)束索引的偏移值。 # (self.firstIndex, self.lastIndex) = unpack('II', self.img[:8]) # Demon注:unpack默認(rèn)使用的endian是和機(jī)器有關(guān)的 # Intel x86和AMD64(x86-64)是little-endian # Motorola 68000和PowerPC G5是big-endian # 而純真數(shù)據(jù)庫全部采用了little-endian字節(jié)序 # 所以在某些big-endian的機(jī)器上原代碼會(huì)出錯(cuò) (self.firstIndex, self.lastIndex) = unpack('
用Python腳本查詢純真IP庫QQWry.dat(Demon修改版)
由于要用 Python 讀取一個(gè)和純真IP數(shù)據(jù)庫 QQWry.dat 格式差不多的 IPv6 數(shù)據(jù)庫,所以在網(wǎng)上搜索了一下,在 LinuxTOY 看到了一個(gè) Python 腳本,發(fā)現(xiàn)有一些小小的問題,于是修改了一下。
#!/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字節(jié)) +----------+ | 記錄區(qū) | (不定長) +----------+ | 索引區(qū) | (大小由文件頭決定) +----------+ 文件頭:4字節(jié)開始索引偏移值+4字節(jié)結(jié)尾索引偏移值 記錄區(qū): 每條IP記錄格式 ==> IP地址[國家信息][地區(qū)信息] 對于國家記錄,可以有三種表示方式: 字符串形式(IP記錄第5字節(jié)不等于0x01和0x02的情況), 重定向模式1(第5字節(jié)為0x01),則接下來3字節(jié)為國家信息存儲(chǔ)地的偏移值 重定向模式(第5字節(jié)為0x02), 對于地區(qū)記錄,可以有兩種表示方式: 字符串形式和重定向 最后一條規(guī)則:重定向模式1的國家記錄后不能跟地區(qū)記錄 索引區(qū): 每條索引記錄格式 ==> 4字節(jié)起始IP地址 + 3字節(jié)指向IP記錄的偏移值 索引區(qū)的IP和它指向的記錄區(qū)一條記錄中的IP構(gòu)成一個(gè)IP范圍。查詢信息是這個(gè) 范圍內(nèi)IP的信息 ''' import sys import socket from struct import pack, unpack class IPInfo(object): '''QQWry.Dat數(shù)據(jù)庫查詢功能集合 ''' def __init__(self, dbname): ''' 初始化類,讀取數(shù)據(jù)庫內(nèi)容為一個(gè)字符串, 通過開始8字節(jié)確定數(shù)據(jù)庫的索引信息''' self.dbname = dbname # f = file(dbname, 'r') # Demon注:在Windows下用'r'會(huì)有問題,會(huì)把\r\n轉(zhuǎn)換成\n # 詳見http://demon.tw/programming/python-open-mode.html # 還有Python文檔中不提倡用file函數(shù)來打開文件,推薦用open f = open(dbname, 'rb') self.img = f.read() f.close() # QQWry.Dat文件的開始8字節(jié)是索引信息,前4字節(jié)是開始索引的偏移值, # 后4字節(jié)是結(jié)束索引的偏移值。 # (self.firstIndex, self.lastIndex) = unpack('II', self.img[:8]) # Demon注:unpack默認(rèn)使用的endian是和機(jī)器有關(guān)的 # Intel x86和AMD64(x86-64)是little-endian # Motorola 68000和PowerPC G5是big-endian # 而純真數(shù)據(jù)庫全部采用了little-endian字節(jié)序 # 所以在某些big-endian的機(jī)器上原代碼會(huì)出錯(cuò) (self.firstIndex, self.lastIndex) = unpack('
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
