在网上看到的别人写的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归属地信息的更多相关文章

  1. 【VB.NET】利用纯真IP数据库查询IP地址及信息

    几年前从某个博客抄来的,已经忘记原地址了,如果需要C#版的,可以在博客园搜到吧.我因为自己用,所以转换为了VBNET代码,而且也放置了很久,今天无意间翻出来,就分享给大家吧. 首先,先下载 纯真数据库 ...

  2. 易语言 - 模块 - 子程序 - 纯真IP数据库查询

    .版本 .支持库 spec .程序集 程序集1 .子程序 _启动子程序, 整数型, , 请在本子程序中放置易模块初始化代码 _临时子程序 () ' 在初始化代码执行完毕后调用测试代码 返回 () ' ...

  3. 优化读取纯真IP数据库QQWry.dat获取地区信息

    改自HeDaode 2007-12-28的代码 将之改为从硬盘读取后文件后,将MemoryStream放到内存中,提高后续查询速度 ///<summary> /// 提供从纯真IP数据库搜 ...

  4. 调用webservice查询手机号码归属地信息

    Web Services是由企业发布的完成其特定商务需求的在线应用服务,其他公司或应用软件能够通过Internet来访问并使用这项在线服务.在这里我们使用soap协议往webservice发送信息,然 ...

  5. python 利用淘宝IP库 查询IP归属地

    #coding:utf-8 from django.test import TestCase import json import urllib ip = "114.114.114.114& ...

  6. 【VB.NET】通过 IPIP.NET 数据库来查询IP地址

    上一次介绍了利用纯真数据库查询IP地址详细信息的方法.然而纯真数据库是由网友反馈所提供的,很多数据描述并不准确,所以我上网找了一些其他的IP数据库,最后就找到了 ipip.net 这个网站所提供的IP ...

  7. C# 调用IP库(QQWry.Dat)查询IP位置及自动升级IP库方法【转】

    前言 C# 用IP地址(123.125.114.144)查询位置(北京市百度公司)的东西,非常好用也非常方便,可手动升级刷新IP库,一次编码永久收益,可支持winform.asp.net等程序. 本文 ...

  8. 分享几个免费IP地址查询API接口

    几个免费IP地址查询API接口 1.IP地址查询接口:http://apis.juhe.cn/ip/ip2addr要先去https://www.juhe.cn/docs/api/...申请APPKEY ...

  9. 齐全的IP地址查询接口及调用方法(转)

    设计蜂巢IP地址查询接口:http://www.hujuntao.com/api/ip/ip.php 腾讯IP地址查询接口:http://fw.qq.com/ipaddress 新浪IP地址查询接口: ...

随机推荐

  1. linux 用户配置文件及其相关目录

    用户配置文件及其相关目录: /etc/passwd 用户信息文件/etc/shadow 影子文件/etc/group 组信息文件/etc/gshadow 组密码文件邮箱目录模板目录 /etc/pass ...

  2. idea springboot应用启动

    在idea里启动springboot应用最好使用 spring-boot:run 如果通过运行main方法启动应用,会找不到页面

  3. LeetCode题解之Rotate Array

    1.题目描述 2.代码 void rotate(vector<int>& nums, int k) { ) return ; && (k / nums.size() ...

  4. c# 编译期常量const和运行时常量readonly

    注意:const编译期常量是编译的时候就确定的,可以查看IL代码,是写死的.如果另一个程序集引用后,该程序集没有进行编译,则值不会改变. 看效果: 项目中有2个程序集: 其中:常量在这个程序集中定义并 ...

  5. machine learning model(algorithm model) .vs. statistical model

    https://www.analyticsvidhya.com/blog/2015/07/difference-machine-learning-statistical-modeling/ http: ...

  6. Jquery 保留N位小数,且千位以上用","号隔开

    s:数据Value n:保留小数位数 function jinEFmoney(s, n) { if (s == '' || s == null) return '0.00'; n = n > 0 ...

  7. 阿里云ECS服务器环境搭建 ubuntu 16.04 图形界面的安装

    https://blog.csdn.net/zwq912318834/article/details/80528374

  8. Error creating bean with name xxxx,xxxx must be provided

    原因: 继承父类的bean注入是set,get方法 问题: 自己的controller不能创建,因为需要的bean没有创建 解决方法: bean 注入,通过构造函数调用父类的set方法

  9. 铁乐学python_day02-作业

    1.判断下列逻辑语句的True,False. 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 解题思路 ...

  10. (matlab)plot画图的颜色线型(转)

    http://wenku.baidu.com/link?url=SVVMVH8QlDIu2hVKDtoBYs6l0CnQvFnFHJJ9yexmYVKQqhz47qIr7aK7LOf8nN0qNdy8 ...