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地址查询接口: ...
随机推荐
- Fragment 源码解析add()和replace()方法
1.有问题的代码: MainActivity public class MainActivity extends AppCompatActivity implements View.OnClickLi ...
- import依赖范围的使用
<!-- <parent> <groupId>org.springframework.boot</groupId> <artifactId>spr ...
- leveldb源码分析--插入删除流程
由于网络上对leveldb的分析文章都比较丰富,一些基础概念和模型都介绍得比较多,所以本人就不再对这些概念以专门的篇幅进行介绍,本文主要以代码流程注释的方式. 首先我们从db的插入和删除开始以对整个体 ...
- nginx 的socket 选项处理--TCP_DEFER_ACCEPT
在nginx listen配置项的说明中有一个选项: deferred -- indicates to use that postponed accept(2) on Linux with. the ...
- MySQL中如何实现select top n
用惯了access mssql server的朋友,可能在用mysql查询前N条记录时,习惯的使用select top n 形式的语句,在这里说明一下,mysql没有此语法,mysql用limit来实 ...
- Oracle EBS 请求
SELECT t.responsibility_id, t.responsibility_key, t.responsibility_name, t.description, t.menu_id, f ...
- golang 防知乎 中文验证码 源码
原创,转载请注明出处! 最开始用图形来模仿文字进行各种角度的倒立和排列,后来切换为文字后,有很多问题.总结如下: 1.程序在画图形和画文字方面不一样,图形的是从原点开始(0,0),而文字则从文字的基线 ...
- QT5.8连接Mysql提示QMYSQL driver not loaded
我们都知道在QT5.8系列里已经带了Mysql的dll文件 驱动的名字为“qsqlmysql.dll”和“qsqlmysqld.dll” 但是按照网上的各种教程和博客基本都是错的,只有个别人是对的. ...
- Linux 的计划任务
Linux操作系统定时任务系统 Cron 入门 cron是一个linux下的定时执行工具,可以在无需人工干预的情况下运行作业.由于Cron 是Linux的内置服务,但它不自动起来,可以用以下的方法启动 ...
- JVM虚拟机20:内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)
1.内存区域划分 根据我们之前介绍的垃圾收集算法,限定商用虚拟机基本都采用分代收集算法进行垃圾回收.根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法.大批对象死去.少量 ...