python3通过纯真IP数据库查询IP归属地信息
在网上看到的别人写的python2的代码,修改成了python3。
把纯真IP数据库文件qqwry.dat放到czip.py同一目录下。
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# filename: czip.py import socket
import struct class CzIp:
def __init__(self, db_file='qqwry.dat'):
self.f_db = open(db_file, "rb")
bs = self.f_db.read(8)
(self.first_index, self.last_index) = struct.unpack('II', bs)
self.index_count = int((self.last_index - self.first_index) / 7 + 1)
self.cur_start_ip = None
self.cur_end_ip_offset = None
self.cur_end_ip = None
# print(self.get_version(), " 纪录总数: %d 条 "%(self.index_count)) def get_version(self):
'''
获取版本信息,最后一条IP记录 255.255.255.0-255.255.255.255 是版本信息
:return: str
'''
s = self.get_addr_by_ip(0xffffff00)
return s def _get_area_addr(self, offset=0):
if offset:
self.f_db.seek(offset)
bs = self.f_db.read(1)
(byte,) = struct.unpack('B', bs)
if byte == 0x01 or byte == 0x02:
p = self.getLong3()
if p:
return self.get_offset_string(p)
else:
return ""
else:
self.f_db.seek(-1, 1)
return self.get_offset_string(offset) def _get_addr(self, offset):
'''
获取offset处记录区地址信息(包含国家和地区)
如果是中国ip,则是 "xx省xx市 xxxxx地区" 这样的形式
(比如:"福建省 电信", "澳大利亚 墨尔本Goldenit有限公司")
:param offset:
:return:str
'''
self.f_db.seek(offset + 4)
bs = self.f_db.read(1)
(byte,) = struct.unpack('B', bs)
if byte == 0x01: # 重定向模式1
country_offset = self.getLong3()
self.f_db.seek(country_offset)
bs = self.f_db.read(1)
(b,) = struct.unpack('B', bs)
if b == 0x02:
country_addr = self.get_offset_string(self.getLong3())
self.f_db.seek(country_offset + 4)
else:
country_addr = self.get_offset_string(country_offset)
area_addr = self._get_area_addr()
elif byte == 0x02: # 重定向模式2
country_addr = self.get_offset_string(self.getLong3())
area_addr = self._get_area_addr(offset + 8)
else: # 字符串模式
country_addr = self.get_offset_string(offset + 4)
area_addr = self._get_area_addr()
return country_addr + " " + area_addr def dump(self, first, last):
'''
打印数据库中索引为first到索引为last(不包含last)的记录
:param first:
:param last:
:return:
'''
if last > self.index_count:
last = self.index_count
for index in range(first, last):
offset = self.first_index + index * 7
self.f_db.seek(offset)
buf = self.f_db.read(7)
(ip, of1, of2) = struct.unpack("IHB", buf)
address = self._get_addr(of1 + (of2 << 16))
print("%d %s %s" % (index, self.ip2str(ip), address)) def _set_ip_range(self, index):
offset = self.first_index + index * 7
self.f_db.seek(offset)
buf = self.f_db.read(7)
(self.cur_start_ip, of1, of2) = struct.unpack("IHB", buf)
self.cur_end_ip_offset = of1 + (of2 << 16)
self.f_db.seek(self.cur_end_ip_offset)
buf = self.f_db.read(4)
(self.cur_end_ip,) = struct.unpack("I", buf) def get_addr_by_ip(self, ip):
'''
通过ip查找其地址
:param ip: (int or str)
:return: str
'''
if type(ip) == str:
ip = self.str2ip(ip)
L = 0
R = self.index_count - 1
while L < R - 1:
M = int((L + R) / 2)
self._set_ip_range(M)
if ip == self.cur_start_ip:
L = M
break
if ip > self.cur_start_ip:
L = M
else:
R = M
self._set_ip_range(L)
# version information, 255.255.255.X, urgy but useful
if ip & 0xffffff00 == 0xffffff00:
self._set_ip_range(R)
if self.cur_start_ip <= ip <= self.cur_end_ip:
address = self._get_addr(self.cur_end_ip_offset)
else:
address = "未找到该IP的地址"
return address def get_ip_range(self, ip):
'''
返回ip所在记录的IP段
:param ip: ip(str or int)
:return: str
'''
if type(ip) == str:
ip = self.str2ip(ip)
self.get_addr_by_ip(ip)
range = self.ip2str(self.cur_start_ip) + ' - ' \
+ self.ip2str(self.cur_end_ip)
return range def get_offset_string(self, offset=0):
'''
获取文件偏移处的字符串(以'\0'结尾)
:param offset: 偏移
:return: str
'''
if offset:
self.f_db.seek(offset)
bs = b''
ch = self.f_db.read(1)
(byte,) = struct.unpack('B', ch)
while byte != 0:
bs += ch
ch = self.f_db.read(1)
(byte,) = struct.unpack('B', ch)
return bs.decode('gbk') def ip2str(self, ip):
'''
整数IP转化为IP字符串
:param ip:
:return:
'''
return str(ip >> 24) + '.' + str((ip >> 16) & 0xff) + '.' + str((ip >> 8) & 0xff) + '.' + str(ip & 0xff) def str2ip(self, s):
'''
IP字符串转换为整数IP
:param s:
:return:
'''
(ip,) = struct.unpack('I', socket.inet_aton(s))
return ((ip >> 24) & 0xff) | ((ip & 0xff) << 24) | ((ip >> 8) & 0xff00) | ((ip & 0xff00) << 8) def getLong3(self, offset=0):
'''
3字节的数值
:param offset:
:return:
'''
if offset:
self.f_db.seek(offset)
bs = self.f_db.read(3)
(a, b) = struct.unpack('HB', bs)
return (b << 16) + a if __name__ == '__main__':
cz = CzIp()
print(cz.get_version())
ip = '14.215.177.39'
print(cz.get_ip_range(ip))
print(cz.get_addr_by_ip(ip))
运行结果:

python3通过纯真IP数据库查询IP归属地信息的更多相关文章
- 【VB.NET】利用纯真IP数据库查询IP地址及信息
几年前从某个博客抄来的,已经忘记原地址了,如果需要C#版的,可以在博客园搜到吧.我因为自己用,所以转换为了VBNET代码,而且也放置了很久,今天无意间翻出来,就分享给大家吧. 首先,先下载 纯真数据库 ...
- 易语言 - 模块 - 子程序 - 纯真IP数据库查询
.版本 .支持库 spec .程序集 程序集1 .子程序 _启动子程序, 整数型, , 请在本子程序中放置易模块初始化代码 _临时子程序 () ' 在初始化代码执行完毕后调用测试代码 返回 () ' ...
- 优化读取纯真IP数据库QQWry.dat获取地区信息
改自HeDaode 2007-12-28的代码 将之改为从硬盘读取后文件后,将MemoryStream放到内存中,提高后续查询速度 ///<summary> /// 提供从纯真IP数据库搜 ...
- 调用webservice查询手机号码归属地信息
Web Services是由企业发布的完成其特定商务需求的在线应用服务,其他公司或应用软件能够通过Internet来访问并使用这项在线服务.在这里我们使用soap协议往webservice发送信息,然 ...
- python 利用淘宝IP库 查询IP归属地
#coding:utf-8 from django.test import TestCase import json import urllib ip = "114.114.114.114& ...
- 【VB.NET】通过 IPIP.NET 数据库来查询IP地址
上一次介绍了利用纯真数据库查询IP地址详细信息的方法.然而纯真数据库是由网友反馈所提供的,很多数据描述并不准确,所以我上网找了一些其他的IP数据库,最后就找到了 ipip.net 这个网站所提供的IP ...
- C# 调用IP库(QQWry.Dat)查询IP位置及自动升级IP库方法【转】
前言 C# 用IP地址(123.125.114.144)查询位置(北京市百度公司)的东西,非常好用也非常方便,可手动升级刷新IP库,一次编码永久收益,可支持winform.asp.net等程序. 本文 ...
- 分享几个免费IP地址查询API接口
几个免费IP地址查询API接口 1.IP地址查询接口:http://apis.juhe.cn/ip/ip2addr要先去https://www.juhe.cn/docs/api/...申请APPKEY ...
- 齐全的IP地址查询接口及调用方法(转)
设计蜂巢IP地址查询接口:http://www.hujuntao.com/api/ip/ip.php 腾讯IP地址查询接口:http://fw.qq.com/ipaddress 新浪IP地址查询接口: ...
随机推荐
- BS网站架构演变
BS网站架构演变 网站架构的整个演变过程主要是围绕大数据和高并发这两个问题展开的,解决的方案主要分为使用缓存和使用多资源两种类型.多资源主要指多存储(包括多内存).多CPU和多网络,对于多资源来说又可 ...
- CSS 小结笔记之定位
定位也是Css中一个非常强大的属性.定位主要是用来移动盒子,将其移动到我们想要的位置. 定位分为两部分 1.边偏移 left | right |top |bottom:偏移大小:(边偏移一般制定上就不 ...
- 2.CSS使用基础(1)
目录 一.css颜色的四种表示法 二.使用css 4种方式 三.css注释: 四.CSS Id 和 Class选择器 五.多重样式优先级顺序 六.CSS Backgrounds(背景) 七.CSS T ...
- ASP.NET MVC 5搭建自己的视图基架 (CodeTemplate)
我们知道,在MVC项目中添加视图时,在添加面板有模板可以选择,这里会有人疑问,这个模板位于哪里?我可以搭建自己的基架吗? 首先回答第二个问题,答案是当然可以 我这里使用的是Visual Studio ...
- UIView使用UIMotionEffect效果
UIView使用UIMotionEffect效果 这个效果在模拟器上看不了,所以无法截图. UIView+MotionEffect.h + UIView+MotionEffect.m // // ...
- 使用CADisplayLink写秒表
使用CADisplayLink写秒表 效果: 源码: StopWatch.h 与 StopWatch.m // // StopWatch.h // ShowTime // // Created by ...
- IP地址分类及CIDR划分方法
IP地址的分类和表示有三种形式,1.分类的IP地址.2.子网划分.3.无分类编址CIDR 1.分类的IP地址 IP地址:: = {<网络号>,<主机号>} 不同的网络号和主机号 ...
- 全部读取------------ 一次性全部读取的.read() VS 一行一行的for迭代
全部读取 f = open("喜洋洋",mode= "r",encoding= "utf-8") 方法一: 一次性全部读取f = o ...
- exits, in, left join性能比较
exits in left join性能比较 ,笔者使用的是MYSQL数据库,这三个关键字方法在其他的关系数据库里也是大同小异,如果各种有兴趣,自行比较. 我这里有一个249_account 表,总 ...
- 3613: [Heoi2014]南园满地堆轻絮
3613: [Heoi2014]南园满地堆轻絮 Time Limit: 50 Sec Memory Limit: 256 MB Submit: 827 Solved: 534 [Submit][Sta ...