Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# IpgeobaseLocal

География российских и украинских IP-адресов. Поиск местонахождения (города) IP-адреса, локальный поиск
География российских и украинских IP-адресов. Поиск местонахождения (города) IP-адреса, локальный поиск.
Импорт данных о городах из ipgeobase в SQL.
Работает только если подключать как gem в Rails 3.2+

## Installation

Expand All @@ -18,7 +20,7 @@ Or install it yourself as:

## Usage

rake ipgeobase_local:update# => загрузка базы c ipgeobase.ru
rake ipgeobase_local:update # => загрузка/обновление базы c ipgeobase.ru

IpgeobaseLocal.load#предварительная загрузка базы в пямять

Expand All @@ -27,12 +29,14 @@ Or install it yourself as:
ip_meta.city # => Москва

ip_meta.country # => Россия

## Usage with Rails

config/initializers/ipgeo.rb

IpgeobaseLocal.base_directory = "db/geo_files/"
IpgeobaseLocal.load

## Contributing

1. Fork it
Expand Down
10 changes: 5 additions & 5 deletions lib/ipgeobase_local/ip_meta_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ class IpMetaData

def initialize(country='', region='', city='')
@country = country
@region = region
@city = city
@region = region
@city = city
end

def city;@city;end
def country;@country;end
def region;@region;end
def city; @city; end
def country; @country; end
def region; @region; end

end
end
21 changes: 14 additions & 7 deletions lib/ipgeobase_local/memory_base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ def self.parse(ip)
end

def self.load
instance.load_base #unless defined?(Rake)
instance
end

def initialize()
load_base unless defined?(Rake)
end

def find(ip)
Expand Down Expand Up @@ -44,17 +44,21 @@ def binary_find(ip)
false
end

private
def cidr_base; @cidr_base; end

def load_base
city_base = {}

city_base = {}
@cidr_base = []

cidr_file = "#{IpgeobaseLocal.base_directory}cidr_optim.txt"
cities_file = "#{IpgeobaseLocal.base_directory}cities.txt"
cidr_file = [IpgeobaseLocal.base_directory, 'cidr_optim.txt'].join('/')
cities_file = [IpgeobaseLocal.base_directory, 'cities.txt'].join('/')

unless File.exists?(cidr_file) && File.exists?(cities_file)
raise "Not exist ipgeobase files, pls run 'rake ipgeobase_local:update'"
raise "ipgeobase data files (#{cidr_file} and/or #{cities_file}) do not exist, please run 'rake ipgeobase_local:update'"
end

puts "Loading data from #{cidr_file} and #{cities_file}..."
CSV.foreach(cities_file, col_sep: "\t", quote_char:"'", encoding: "windows-1251:utf-8") do |line|
city_base[line[0]] = line[1..5]
end
Expand All @@ -72,9 +76,12 @@ def load_base
end
@cidr_base << {start: line[0].to_i, end: line[1].to_i, meta_data: IpMetaData.new(country, region, city)}
end

puts "Done."
@cidr_base
end

private

def convert_ip(ip)
if ::IPAddr.new(ip).ipv4?
part = ip.split(".").map{|i| i.to_i}
Expand Down
125 changes: 119 additions & 6 deletions lib/tasks/ipgeobase_local.rake
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ namespace :ipgeobase_local do
desc "Update base file form ipgeobase.ru"
task :update => :environment do
require 'net/http'
dir = "#{IpgeobaseLocal.base_directory}"
if dir.blank?
raise "Not set base directory"
base_dir = IpgeobaseLocal.base_directory
if base_dir.blank?
raise 'The destination directory is not defined, please assign IpgeobaseLocal.base_directory'
end
uri = URI('http://ipgeobase.ru/files/db/Main/geo_files.tar.gz')
file_name = uri.path.split('/').last
file_name = [dir, file_name].join
file_name = [base_dir, file_name].join('/')

FileUtils.mkdir_p "#{dir}"
FileUtils.mkdir_p base_dir

puts "Downloading geo data from #{uri}..."
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new uri.request_uri
http.request request do |response|
Expand All @@ -24,8 +25,120 @@ namespace :ipgeobase_local do
end
end
end
puts "Done."

system("tar -xzf #{file_name} -C #{dir}")
puts "Uncompressing geo data into #{base_dir}..."
system("tar -xzf #{file_name} -C #{base_dir}")
FileUtils.rm file_name
puts "Done."
end


# Предполагается наличие следующих моделей:

# class Country < ActiveRecord::Base
# attr_accessible :abbr2
# end

# class Region < ActiveRecord::Base
# belongs_to :country
# attr_accessible :country
# attr_accessible :name
# end

# class City < ActiveRecord::Base
# belongs_to :country
# belongs_to :region
# attr_accessible :country, :region
# attr_accessible :name
# end


# Предполагается наличие следующих таблиц/миграций:

# class CreateCountries < ActiveRecord::Migration
# def up
# execute "
# create table countries (
# id serial primary key,
# created_at timestamp not null,
# updated_at timestamp not null,
# deleted_at timestamp not null DEFAULT '1970-01-01 00:00:00',
# abbr2 varchar not null unique
# )"
# end
#
# def down
# execute "drop table countries"
# end
# end

# class CreateRegions < ActiveRecord::Migration
# def up
# execute "
# create table regions (
# id serial primary key,
# created_at timestamp not null,
# updated_at timestamp not null,
# deleted_at timestamp not null DEFAULT '1970-01-01 00:00:00',
# country_id int_id not null,
# name varchar not null,
# unique(country_id,name)
# )"
# end
#
# def down
# execute "drop table regions"
# end
# end

# class CreateCities < ActiveRecord::Migration
# def up
# execute "
# create table cities (
# id serial primary key,
# created_at timestamp not null,
# updated_at timestamp not null,
# deleted_at timestamp not null DEFAULT '1970-01-01 00:00:00',
# country_id int_id not null,
# region_id int_id not null,
# name varchar not null,
# unique(country_id,region_id,name)
# )"
# end
#
# def down
# execute "drop table cities"
# end
# end

desc "Импорт country/regions/cities в базу данных"
task :import_localities => :environment do
puts "Resetting the database..."
Country.connection.execute "truncate table countries; alter sequence countries_id_seq restart with 1;"
Region.connection.execute "truncate table regions; alter sequence regions_id_seq restart with 1;"
City.connection.execute "truncate table cities; alter sequence cities_id_seq restart with 1;"
puts "Done."

data = {}
cidr_base = IpgeobaseLocal::MemoryBase.load.cidr_base
puts "Exporting to SQL DB..."
cidr_base.each do |d|
d = d[:meta_data]
country = d.country
region = d.region
city = d.city
if country.present?
c = data[country] ||= { obj: Country.create({abbr2: country}) }
if region.present?
r = c[region] ||= { obj: Region.create({country: c[:obj], name: region}) }
if city.present?
cc = r[city] ||= { obj: City.create({country: c[:obj], region: r[:obj], name: city} ) }
end
end
end
end
puts "Done."
end
end