qqzeng-ip.dat是一个特殊格式的dat文件,可以快速的查找IP对应的地理位置信息。据作者测试的结果来看,是100万ip查找速度0.5秒。

当然这和语言有非常大的关系,python的循环性能一直是为人所诟病的。目前python版本测试的结果是10万IP的查找速度是3.X秒左右,还算够用,毕竟真实情况下的30秒~5分钟内的日志不太可能出现一批数据中的不重复IP超过10万个。

作者提供了解析dat的java/c/php脚本,但没有提供python版本的。所以我就写了一个,以供需要用python语言读取ip的地理位置信息使用。

代码如下:

#coding:utf-8

import os

import math

import socket

import struct

import io

from io import SEEK_SET

path = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + "/qqzeng-ip-utf8.dat")

class IpSearch(object):

fp = None

firstStartIpOffset = None

lastStartIpOffset = None

preStartOffset = None

preEndOffset = None

ipCount = None

prefixCount = None

prefixList = dict()

def __init__(self):

self.fp = io.open(path,"rb")

buff = self.fp.read(16)

self.firstStartIpOffset = self.bytesToLong(buff[0],buff[1],buff[2],buff[3])

self.lastStartIpOffset = self.bytesToLong(buff[4],buff[5],buff[6],buff[7])

self.preStartOffset = self.bytesToLong(buff[8],buff[9],buff[10],buff[11])

self.preEndOffset = self.bytesToLong(buff[12],buff[13],buff[14],buff[15])

self.ipCount = (self.lastStartIpOffset - self.firstStartIpOffset) / 12 + 1

self.prefixCount = (self.preEndOffset - self.preStartOffset) / 9 + 1

self.fp.seek(self.preStartOffset,SEEK_SET)

preBuff = self.fp.read(self.prefixCount*9)

for k in range(0,self.prefixCount):

i = k*9

startIndex = self.bytesToLong(preBuff[1+i],preBuff[2+i],preBuff[3+i],preBuff[4+i])

endIndex = self.bytesToLong(preBuff[5+i],preBuff[6+i],preBuff[7+i],preBuff[8+i])

self.prefixList[ord(preBuff[i])] = {

"start_index":startIndex,

"end_index":endIndex

}

def __del__(self):

if self.fp != None:

self.fp.close()

def get(self,ip):

if ip == '':

return ""

high = 0

low = 0

startIp = 0

endIp = 0

localOffset = 0

localLength = 0

prefix = ip.split(".")[0]

prefix = int(prefix)

ipnum = self.ip2unit(ip)

if prefix in self.prefixList.keys():

index = self.prefixList[prefix]

low = index["start_index"]

high = index["end_index"]

else:

return ""

left = low if low == high else self.binarySearch(low,high,ipnum)

left,startIp,endIp,localOffset,localLength = self.getIndex(left,startIp,endIp,localOffset,localLength)

if startIp <= ipnum and endIp >= ipnum:

return self.getLocal(localOffset,localLength)

else:

return ""

def getLocal(self,localOffset,localLength):

self.fp.seek(localOffset,SEEK_SET)

return self.fp.read(localLength)

def getIndex(self,left,startIp,endIp,localOffset,localLength):

leftOffset = self.firstStartIpOffset + left*12

self.fp.seek(leftOffset,SEEK_SET)

buff = self.fp.read(12)

startIp = self.bytesToLong(buff[0],buff[1],buff[2],buff[3])

endIp = self.bytesToLong(buff[4],buff[5],buff[6],buff[7])

r3 = (ord(buff[8]) << 0 | ord(buff[9]) << 8 | ord(buff[10]) << 16)

if r3 < 0:

r3 += 4294967296

localOffset = r3

localLength = ord(buff[11])

return [left,startIp,endIp,localOffset,localLength]

def binarySearch(self,low,high,k):

m = 0

while low <= high:

mid = (low + high)/2

endIpNum = self.getEndIpNum(mid)

if endIpNum >= k:

m = mid

if mid == 0:

break

high = mid - 1

else:

low = mid + 1

return m

def getEndIpNum(self,left):

leftOffset = self.firstStartIpOffset + (left*12) + 4

self.fp.seek(leftOffset,SEEK_SET)

buf = self.fp.read(4)

return self.bytesToLong(buf[0],buf[1],buf[2],buf[3])

def ip2unit(self,ip):

lip = self.ip2long(ip)

if lip < 0:

lip += 4294967296

return lip

def ip2long(self,ip):

packedIP = socket.inet_aton(ip)

return struct.unpack("!L", packedIP)[0]

def bytesToLong(self,a,b,c,d):

iplong = (ord(a) << 0) | (ord(b) << 8) | (ord(c) << 16) | (ord(d) << 24)

if iplong < 0:

iplong += 4294967296

return iplong

if __name__ == '__main__':

ipSearch = IpSearch()

print ipSearch.get("210.51.200.123").decode("utf-8").encode("gbk")

import time

startTime = time.time()

for i in range(0,100000):

ipSearch.get("210.51.200.123")

endTime = time.time()

print "time waste:",endTime-startTime

测试结果如下:

与百度查出的IP信息进行对比:

还挺不错的,对吧。

python获取qq好友ip_qqzeng-ip.dat IP库读取python版相关推荐

  1. 教你用Python获取qq好友备注名称

    Python作为一种编程语言,超级多的库能够帮助我们完成很多繁琐的工作,今天小千就来教大家如何去利用Python获取qq好友的备注信息. 首先这个问题并不是很难,我们需要准备好一些工具,使用到requ ...

  2. python获取qq好友ip_使用Python模拟登录QQ邮箱获取QQ好友列表

    最近因开发项目的需要,有一个需求,就是很多SNS网站都有的通过 Email地址 导入好友列表,不过这次要导入的不是Email 列表,而是QQ的好友列表. 实现方式: 通过google一搜,实现的方式大 ...

  3. python 获取qq群成员信息_教你用python爬取自己加入的QQ群成员名单,它们竟然是这样的人...

    本次实验环境: 操作系统:Mac OS 开发语言:python 3.6 IDE:jupyter notebook(建议使用) 浏览器:Chrome(版本75.0.3770.100) 需要用到的库:se ...

  4. Python获取代理池和提取可用IP

    Python获取代理池和提取可用IP 前言 正文 请求代理池 筛选代理ip 保存可用的代理ip 把代理ip转发到本地(可选) 总结 前言 最近在学习Python爬虫的编写,发现很多网站设置了ip限制, ...

  5. python爬虫qq好友信息,GitHub - equationl/QQzone_crawler: QQ 空间动态爬虫,利用cookie登录获取所有可访问好友空间的动态保存到本地...

    关于 Edit by equationl 优先在 码云 上更新 该项目修改自 xjr7670 的 QQzone_crawler 原作者说明: QQ空间动态爬虫 修改了什么? 爬取完整的评论列表 爬取点 ...

  6. qq好友列表获取之动态爬虫清洗爬取好友列表数据 - 获取qq好友、群、群成员列表

    qq好友列表获取之动态爬虫清洗爬取qq好友列表数据 - 获取qq好友ip.群.群成员列表.我们的好友列表要从 qzone 获取,现在打开 qzone 的链接 https://h5.qzone.qq.c ...

  7. 用 Python 将 QQ 好友头像生成祝福语

    本文我们来看一下如何使用 Python 将 QQ 好友头像拼成"五一快乐"四个字.我们可以将整个实现过程分为两步:爬取 QQ 好友头像.利用好友头像生成文字. 爬取头像 爬取 QQ ...

  8. 今天咱们用 Python 将 QQ 好友头像生成祝福语

    本文我们来看一下如何使用 Python 将 QQ 好友头像拼成"五一快乐"四个字.我们可以将整个实现过程分为两步:爬取 QQ 好友头像.利用好友头像生成文字. 相关文件 小伙伴们可 ...

  9. 用Python将QQ好友头像生成祝福语!大家五一快乐!

    本文我们来看一下如何使用 Python 将 QQ 好友头像拼成"五一快乐"四个字.我们可以将整个实现过程分为两步:爬取 QQ 好友头像.利用好友头像生成文字. 爬取头像 爬取 QQ ...

最新文章

  1. php 引入其他文件中的变量
  2. BW标准数据源初始化设置
  3. 独家 | 如何从头开始为MNIST手写数字分类建立卷积神经网络(附代码)
  4. iptables总结
  5. GD32F130命名方式
  6. validator API文档
  7. postgresql中自定义函数脚本的备份及恢复
  8. [导入]正则表达式学习心得体会(2)
  9. java做法_Java方法
  10. HTML5 代码要怎样凭“魅力”吸引搜索引擎的注意?
  11. 流浪猫的故事看质量人员需求
  12. python最新版安装图集_[python] plist图集拆分小图
  13. java访问数据库视图_java 访问数据库视图
  14. Android包体优化总结
  15. 大数据的四个典型特征
  16. AndroidX适配教程
  17. 贡献度分析--帕累托图
  18. 使用JAVA将m3u8转换为mp4格式
  19. POI DataValidation 删除数据有效性验证
  20. HTML5 Video播放本地文件

热门文章

  1. pod 的亲和性,反亲和性 实验
  2. CNCF TOC 委员张磊:不断演进的云原生给我们带来了什么?
  3. 【超详细】一文学会链表解题(建议收藏!)
  4. 《尼山萨满》项目美术亲述游戏创作过程
  5. 《Invisible Inc.》游戏分析:如何在回合制中塑造紧张刺激的体验?
  6. ORACLE TEXT LEXER PREFERENCE(三)
  7. python 面向对象之:反射,双下方法
  8. SVN - 简单使用手册
  9. python_深浅拷贝
  10. GateOne Web SSH 环境搭建