一, 服务器环境介绍:
服务器硬件: 4 核 4g 内存
服务器系统: centos6.9 x86_64 位最小化安装
二, 环境安装
参考地址: https://github.com/lionsoul2014/ip2region
直接下载包到服务器上的 / root 目录下
wget https://github.com/lionsoul2014/ip2region/archive/master.zip
unzip 解压
unzip master.zip
到此准备工作基本完成
以下都是 github.com 官网上的说明, 我这边复制在自己的博文里了
99.9% 准确率, 定时更新:
数据聚合了一些知名 ip 到地名查询提供商的数据, 这些是他们官方的的准确率, 经测试着实比纯真啥的准确多了.
每次聚合一下数据需要 1-2 天, 会不定时更新.
标准化的数据格式:
每条 ip 数据段都固定了格式: 城市 Id | 国家 | 区域 | 省份 | 城市 | ISP
只有中国的数据精确到了城市, 其他国家只能定位到国家, 后前的选项全部是 0, 已经包含了全部你能查到的大大小小的国家. (请忽略前面的城市 Id, 个人项目需求)
体积小:
生成的数据库文件 ip2region.db 只有 1.5M(1.2 版本前是 3.5M)
多查询客户端的支持, 0.0x 毫秒级别的查询
已经集成的客户端有: java, C#, php, c, python,nodejs,php 扩展 (支持 linux, php5, php7 版本已支持),golang.
提供了两种查询算法, 响应时间如下:
客户端 / binary 算法 / b-tree 算法 / Memory 算法:
c#/0.x 毫秒 / 0.x 毫秒 / 0.x 毫秒
java/0.x 毫秒 / 0.x 毫秒 / 0.1x 毫秒 (使用 RandomAccessFile)
php/0.x 毫秒 / 0.1x 毫秒 / 0.1x 毫秒
c/0.0x 毫秒 / 0.0x 毫秒 / 0.00x 毫秒 (b-tree 算法基本稳定在 0.02x 毫秒级别)
python/0.x 毫秒 / 0.1x 毫秒 / 未知
任何客户端 b-tree 都比 binary 算法快, 当然 Memory 算法固然是最快的!
maven 仓库地址:
- <dependency>
- <groupId>org.lionsoul</groupId>
- <artifactId>ip2region</artifactId>
- <version>1.4</version>
- </dependency>
nuget 安装命令
Install-Package IP2Region
5. 测试程序:
- c#:
- cd IP2Region_ConsoleTest
- dotnet run
- example result:
请输入 IP 地址:
- 36.149.160.55
- java:
- cd binding/java
- ant all
- java -jar ip2region-{version}.jar ./data/ip2region.db
- php:
- php binding/php/testSearcher.php ./data/ip2region.db
- c:
- cd binding/c/
gcc -g -O2 testSearcher.c ip2region.c
- ./a.out ../../data/ip2region.db
- python:
- python binding/python/testSearcher.py ./data/ip2region.db
均会看到如下界面:
initializing B-tree ...
- +----------------------------------+
- | ip2region test script |
- | Author: chenxin619315@gmail.com |
- | Type 'quit' to exit program |
- +----------------------------------+
- p2region>> 101.105.35.57
2163 | 中国 | 华南 | 广东省 | 深圳市 | 鹏博士 in 0.02295 millseconds
输入 ip 地址开始测试, 第一次会稍微有点慢, 在运行命令后面接入 binary,memory 来尝试其他算法, 建议使用 b-tree 算法, 速度和并发需求的可以使用 memory 算法.
具体集成请参考不同客户端的测试源码.
6. 如何生成 ip2region.db 文件
从 ip2region 1.2.2 版本开始里面提交了一个 dbMaker-{version}.jar 的可以执行 jar 文件, 用它来完成这个工作:
1, 确保你安装好了 java 环境 (不玩 Java 的童鞋就自己谷歌找找拉, 临时用一用, 几分钟的事情)
2, cd 到 ip2region 的根目录, 然后运行如下命令:
java -jar dbMaker-{version}.jar -src 文本数据文件 -region 地域 csv 文件 [-dst 生成的 ip2region.db 文件的目录]
- # 文本数据文件: db 文件的原始文本数据文件路径, 自带的 ip2region.db 文件就是 / data/ip.merge.txt 生成而来的, 你可以换成自己的或者更改 / data/ip.merge.txt 重新生成
- # 地域 csv 文件: 该文件目的是方便配置 ip2region 进行数据关系的存储, 得到的数据包含一个 city_id, 这个直接使用 / data/origin/global_region.csv 文件即可
- #ip2region.db 文件的目录: 是可选参数, 没有指定的话会在当前目录生成一份./data/ip2region.db 文件
3, 获取生成的 ip2region.db 文件覆盖原来的 ip2region.db 文件即可
4, 默认的 ip2region.db 文件生成命令:
cd ip2region 项目根目录
- java -jar dbMaker-1.2.2.jar -src ./data/ip.merge.txt -region ./data/global_region.csv
- # 会看到一大片的输出
三, 演示
以下是我采用的 php 和 Python 语言进行的实际测试演示:
php 演示测试:
- [root@git-server ~]# cd /root/ip2region-master
- [root@git-server ip2region-master]# ls
binding CHANGES.md data dbMaker-1.2.2.jar LICENSE.md README.md
- [root@git-server ip2region-master]# cd binding/
- [root@git-server binding]# ls
- c c# c_mmap golang java nodejs php php_extension python python3
- [root@git-server binding]# cd php
- [root@git-server php]# ls
Ip2Region.class.php testSeacher.php
[root@git-server php]# php testSeacher.php /opt/ip2region-master/data/ip2region.db
initializing B-tree ...
- +----------------------------------+
- | ip2region test script |
- | Author: chenxin619315@gmail.com |
- | Type 'quit' to exit program |
- +----------------------------------+
- ip2region>> 211.144.7.32
0 | 中国 | 0 | 北京 | 北京 | 联通 in 2.38013 millseconds
ip2region>> 124.207.48.234
0 | 中国 | 0 | 北京 | 北京 | 鹏博士 in 0.12134 millseconds
ip2region>>
Python 演示:
[root@git-server python3]# python3 testSearcher.py /opt/ip2region-master/data/ip2region.db
initializing b-tree...
- +----------------------------------+
- | ip2region test program |
- | Author: chenxin619315@gmail.com. |
- | Type 'quit' or 'exit' to exit program |
- +----------------------------------+
- ip2region>> 66.249.82.86
0 | 台湾 | 0 | 台湾 | 0|0 in 1.554199 millseconds
ip2region>> 101.108.251.187
0 | 泰国 | 0 | 曼谷 | 曼谷 | TOT in 0.149414 millseconds
ip2region>>
四, 实际应用:
采用 python 脚本, 来查询一个存有 1017 万个不同 IP 的文本文件中的 ip 归属地
以下结合原作者的 testSearcher.py Python 脚本, 来获取这存有 1017 万个不同 IP 的归属地址. 此 Python 脚本简单修改如下:
- [root@git-server python3]# cat /root/ip2region-master/binding/python3/searcher.py
- #-*- coding:utf-8 -*-
"""" ip2region python seacher client module"
- "Autho: koma<komazhang@foxmail.com>" Date : 2015-11-06
- """
- import struct, sys, os, time
- from ip2Region import Ip2Region
- def testSearch():
- """" ip2region test function"""
- llen = len(sys.argv)
- if llen <3:
- print ("Usage: python testSearcher.py [ip2region db file] [alrogrithm]")
- print ("Algorithm: binary or b-tree")
- return 0
- dbFile = sys.argv[1]
- method = 1
- algorithm = "b-tree"
- search_file = sys.argv[2]
- if (not os.path.isfile(dbFile)) or (not os.path.exists(dbFile)):
- print ("[Error]: Specified db file is not exists.")
- return 0
- if (not os.path.isfile(search_file)) or (not os.path.exists(search_file)):
- print("查询文件不存在")
- return 0
- if llen> 3:
- algorithm = sys.argv[3]
- if algorithm == "binary":
- method = 2
- elif algorithm == "memory":
- method = 3
- searcher = Ip2Region(dbFile);
- with open(search_file,"rt") as f:
- for line in f:
- line = line.strip()
- #print(line)
- if line == "":
- print("[Error]: Invalid ip address.")
- continue
- if line == "quit" or line == "exit":
- print("[Info]: Thanks for your use, Bye.")
- break
- if not searcher.isip(line):
- print("[Error]: Invalid ip address.")
- continue
- #sTime = time.time() * 1000
- if method == 1:
- data = searcher.btreeSearch(line)
- elif method == 2:
- data = searcher.binarySearch(line)
- else:
- data = searcher.memorySearch(line)
- #eTime = time.time() * 1000
- if isinstance(data, dict):
- #print("%s in %f millseconds" % (data["city_id"], data["region"].decode('utf-8'), eTime - sTime))
- #print( "%s" % (data["region"].decode('utf-8')))
- print("%s|%s" % (line, data["region"].decode('utf-8')))
- else:
- print("[Error]:", data)
- searcher.close()
- if __name__ == "__main__":
- testSearch()
测试如下:
- [root@git-server python3]# cd /root/ip2region-master
- [root@git-server ip2region-master]# time python3 ./binding/python3/searcher.py ./data/ip2region.db /root/unip_guishu>/opt/ipdizhi.txt
- real 15m54.394s
- user 14m47.138s
- sys 0m56.876s
- [root@git-server ip2region-master]# tail -10 /opt/ipdizhi.txt
99.97.22.46 | 美国 | 0|0|0 | 美国电话电报
99.97.26.40 | 美国 | 0|0|0 | 美国电话电报
99.97.29.64 | 美国 | 0|0|0 | 美国电话电报
99.97.30.121 | 美国 | 0|0|0 | 美国电话电报
99.98.238.52 | 美国 | 0 | 南卡罗来纳 | 0 | 美国电话电报
99.98.254.160 | 美国 | 0 | 加利福尼亚 | 0 | 美国电话电报
99.99.218.167 | 美国 | 0 | 德克萨斯 | 休斯顿 | 美国电话电报
99.99.232.239 | 美国 | 0 | 德克萨斯 | 0 | 美国电话电报
99.99.37.198 | 美国 | 0 | 加利福尼亚 | 0 | 美国电话电报
99.99.55.172 | 美国 | 0 | 俄亥俄 | 0 | 美国电话电报
总结: 当然这个查询的时间和服务器的硬件有很大的关系, 后来我在一台 CPU 为 16 核心的上测试, 查询结果可以达到秒级 10 万不同 ip 的归属地查询结果
来源: http://blog.51cto.com/wujianwei/2123493