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地址查询接口: ...
随机推荐
- LeetCode题解之Number of 1 Bits
1.题目描述 2.问题分析 使用C++ 标准库的 bitset 类,将整数转换为 二进制,然后将二进制表示转换为字符串,统计字符串中 1 的个数即可. 3.代码 int hammingWeight(u ...
- 1.CSS基础简介
一.基础简介 1.简介 CSS(Cascading Style Sheet)可译为“层叠样式表”或“级联样式表”,它定义如何显示 HTML 元素,用于控制Web页面的外观.通过使用CSS实现页面的内容 ...
- GoldenGate搭建与运维
GolenGate介绍 GoldenGate软件是一种基于日志的结构化数据复制软件,它通过解析源数据库在线日志或归档日志获得数据的增删改变化,再将这些变化应用到目标数据库,实现源数据库与目标数据库实时 ...
- Oracle EBS 清理归档
oraprod 登陆数据库服务器 执行 rman target / 如图: 执行: delete noprompt force archivelog all completed before ‘sys ...
- 标准的Flask启动文件
最近有一些同学问了我一些项目结构的问题 所以今天给大家专门讲解 解耦后的项目 目录我会分为两种方式:一种是普通解耦 一种是多mvc解耦 首先 我没先建立我们程序的文件夹并且在这个文件夹内写一个和这个文 ...
- Linux 系统的目录结构_【all】
Linux系统的目录结构 /:最大根目录,存放系统程序 /etc: 加载配置文件好服务启动命令,系统配置文件 /etc/exports /etc/hosts /bin:binaries 存放命令 /s ...
- Centos7 教程收集ing
CentOS7 常用命令集合 https://blog.csdn.net/o0darknessyy0o/article/details/52072054#t1 1.centOS7下实践查询版本/CPU ...
- php函数substr_replace中文乱码的替代解决方法
$str = "中华人民共和国"; $len = mb_strlen($str,'utf-8'); if($len>=6){ $str1 = mb_substr($str,0 ...
- 【2】python3字符串的比较(辨析is与==的区别)
PYTHON3基本数据类型(二.字符串) Python3字符串 ①字符串比较 1.比较字符串是否相同: ==:使用==来比较两个字符串内的value值是否相同 is:比较两个字符串的id值. 2.字符 ...
- DevExpress02、RibbonControl
RibbonControl 常用操作 1.如何代码显示选中的页 ribbonControl1.SelectedPage = ribbonPage2; 2.如何绑定ApplicationMenus和Po ...