本篇博文讲解如何获取客户端请求的 IP,结合 QQwry 纯真 IP 数据库,分析出用户使用的网络、所在城市地区的信息。
这些信息,将有助于运营同事们日常的工作,并且,在未来为产品同事提供用户地区分布的数据。
纯真版 IP 地址数据库是当前网络上最权威、地址最精确、IP 记录以及网吧数据最多的 IP 地址数据库。
收集了包括中国电信、中国移动、中国联通、铁通、长城宽带等各 ISP 的最新准确 IP 地址数据。
通过大家的共同努力打造一个没有未知数据,没有错误数据的 QQ IP。IP 数据库每5天更新一次。
纯真官网
从纯真官网下载数据包之后,解压安装后,打开“纯真IP地址数据库”,在打开的界面上,再次点击解压,将得到一个 txt 文件。
文件内的数据格式为
# 下载日期为 2015-03-05,445135 条 IP 记录
# 其中一行数据
1.61.128.0 1.61.146.255 黑龙江省齐齐哈尔市 联通
新建一个数据表:qqwry_ips,用于存储 txt 文件中的每一条 IP 记录。
为了方便,未来定位一个 IP 归属的范围,我们将 IP 的值,转换为对应的 Long 整形数。
模型 QqwryIp 的 Migration 定义如下
def change
create_table :qqwry_ips do |t|
t.string :start_long
t.string :end_long
t.string :country
t.string :location
t.string :start_ip
t.string :end_ip
t.timestamps
end
add_index :qqwry_ips, :start_long
add_index :qqwry_ips, :end_long
end
读取 txt 文件内容,导入数据库的 rake task 代码如下:
namespace :qqwry_ip do
desc "import qqwry ips data"
task :import => :environment do
puts "start import ip txt file."
total_count = 0
file = "#{Rails.root}/tmp/cn88.net.ip20150305.txt"
File.readlines(file).each_with_index do |line, index|
if line.present?
data = line.split(' ')
if QqwryIp.build_qqwry_ip(data[0], data[1], data[2], data[3])
total_count += 1
puts "success line: #{index}, start_ip: #{data[0]}, end_ip: #{data[1]}"
end
end
if index % 2000 == 0
sleep(1)
end
end
puts "finished, total_count: #{total_count}"
puts "end import ip txt file."
end
end
模型 QqwryIp 中计算 IP 对应的 Long 整形数值的方法:
def build_qqwry_ip(start_ip, end_ip, country, location)
create(start_long: ip2long(start_ip),
end_long: ip2long(end_ip),
country: country,
location: location,
start_ip: start_ip,
end_ip: end_ip)
end
def ip2long(value)
long = 0
value.split(/\./).each_with_index do |b, i|
long += b.to_i << 8*(3-i)
end
long
end
由于项目的架构为: Nginx,Unicorn,Grape,为了在 Grape API 中,顺利取得客户端请求携带的 IP 数据。
需要对 Nginx 做如下的配置:
server {
listen 80;
client_max_body_size 10m;
keepalive_timeout 5;
server_name www.servername.com;
root /path/tibet/public;
location / {
proxy_buffering on;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
proxy_pass http://127.0.0.1:3000;
}
}
Grape API 获取客户端请求的 IP 代码:
params[:request_real_ip] = request.env['HTTP_X_REAL_IP']
模型 QqwryIp 中读取 IP 地区信息的方法如下
def search_ip(ip)
ret = ["未知地区", ""]
return ret if ip.blank?
return ["来自本地", ""] if ip == "127.0.0.1"
longip = ip2long(ip)
record = select('country,location').where("? > start_long AND ? < end_long",
longip, longip).first
ret = [record.country, record.location] if record.present?
ret
end
在用户登录,注册等需要监控的操作,完成之后。
将获取到的客户端 IP,交由 Sidekiq 异步去解析 IP 所在地区,并记录到数据库中。
参考链接
纯真官网
使用ruby解析纯真IP库(qqwry.dat)
利用纯真IP库建立mysql ip数据库
2015-03-25