使用 Ruby on Rails 从原始 IP 地址获取用户国家/地区名称

发布于 2024-08-16 11:08:41 字数 171 浏览 5 评论 0原文

我想从访问者的 IP 地址中提取用户国家/地区名称。

我可以使用 remote_ip 获取 IP 地址。但可能是什么 获得国家名称的最简单方法?

它不必非常准确。有任何 ruby​​ 库(gem 或插件)可以做到这一点吗?

我想要一个简单易用的解决方案。

I want to extract a user country name from visitors' IP addresses.

I could get the IP address with remote_ip. But what could be
the easiest way to get the country name?

It doesn't have to be super accurate. Any ruby library (gem or plugin) to do this?

I want an simple and easy solution for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

猥琐帝 2024-08-23 11:08:41

您可以使用geoip gem。

environment.rb

config.gem 'geoip'

http://www.maxmind.com/app/geolitecountry 下载 GeoIP.dat.gz。解压缩文件。下面假设在 #{RAILS_ROOT}/db 目录下。

@geoip ||= GeoIP.new("#{RAILS_ROOT}/db/GeoIP.dat")    
remote_ip = request.remote_ip 
if remote_ip != "127.0.0.1" #todo: check for other local addresses or set default value
  location_location = @geoip.country(remote_ip)
  if location_location != nil     
    @model.country = location_location[2]
  end
end

You can use geoip gem.

environment.rb

config.gem 'geoip'

Download GeoIP.dat.gz from http://www.maxmind.com/app/geolitecountry. unzip the file. The below assumes under #{RAILS_ROOT}/db dir.

@geoip ||= GeoIP.new("#{RAILS_ROOT}/db/GeoIP.dat")    
remote_ip = request.remote_ip 
if remote_ip != "127.0.0.1" #todo: check for other local addresses or set default value
  location_location = @geoip.country(remote_ip)
  if location_location != nil     
    @model.country = location_location[2]
  end
end
沉鱼一梦 2024-08-23 11:08:41

您还可以使用“Geocoder”,

它会让您的生活更轻松。将以下行放入您的 Gemfile 中并发出捆绑安装命令

gem 'geocoder'

使用此 Gem,您可以轻松获取原始 IP 的国家/地区、IP 甚至城市。请参阅下面的示例

request.ip  # =>    "182.185.141.75"
request.location.city   # =>    ""
request.location.country    # =>    "Pakistan"

You can also use "Geocoder"

It will just make you life easier. Put the following line in your Gemfile and issue the bundle install command

gem 'geocoder'

Using this Gem, you can easily get the country, ip or even city of the originating IP. See an example below

request.ip  # =>    "182.185.141.75"
request.location.city   # =>    ""
request.location.country    # =>    "Pakistan"
青衫负雪 2024-08-23 11:08:41

我正在使用这一行:

locale = Timeout::timeout(5) { Net::HTTP.get_response(URI.parse('http://api.hostip.info/country.php?ip=' + request.remote_ip )).body } rescue "US"

I'm using this one-liner:

locale = Timeout::timeout(5) { Net::HTTP.get_response(URI.parse('http://api.hostip.info/country.php?ip=' + request.remote_ip )).body } rescue "US"
遗弃M 2024-08-23 11:08:41

最简单的方法是使用现有的 Web 服务。

有一些插件可以让您做更多的事情,包括自动使您的模型具有地理位置感知功能 (geokit-rails),但如果您需要的只是国家/地区代码,只需将 HTTP Get 发送到 http://api .hostip.info/country.php (还有其他服务,但这个不需要 API 密钥)将返回它,例如:

Net::HTTP.get_response(URI.parse('http://api.hostip.info/country.php'))
=> US

或轮询 http://api.hostip.info/ 将返回包含城市、纬度、经度等的完整 XML 响应。

请注意,您获得的结果不是 100%准确的。例如,现在我在法国,但报告为在德国。几乎所有基于 IP 的服务都是如此。

The simplest is to use an existing web service for this.

There are plugins that let you do much more, including making your models geolocation-aware (geokit-rails) automatically, but if all you need is a country code for example, simply sending an HTTP Get to http://api.hostip.info/country.php (there are other services but this one does not require an API key) will return it, e.g. :

Net::HTTP.get_response(URI.parse('http://api.hostip.info/country.php'))
=> US

Or polling http://api.hostip.info/ will return a full XML response with city, latitude, longitude, etc.

Be aware that the results you get are not 100% accurate. For example, right now I'm in France but reported as in Germany. This will be the case for pretty much any IP-based service.

花桑 2024-08-23 11:08:41

geoip gem 不再适用于新的 MaxMind 数据库。有一个新的 gem 可以做到这一点,MaxMind-DB-Reader-ruby

只需从 MaxMind 下载城市或国家二进制 gzip 数据库,解压并使用以下代码:

require 'maxmind/db'

reader = MaxMind::DB.new('GeoIP2-City.mmdb', mode: MaxMind::DB::MODE_MEMORY)

# you probably want to replace 1.1.1.1 with  request.remote_ip
# or request.env['HTTP_X_FORWARDED_FOR']
ip_addr = '1.1.1.1'
record = reader.get(ip_addr)
if record.nil?
  puts '#{ip_addr} was not found in the database'
else
  puts record['country']['iso_code']
  puts record['country']['names']['en']
end

reader.close

根据您的需求进行调整。我在初始化程序中创建了一个方法,我可以根据需要调用该方法。

The geoip gem no longer works with the new MaxMind databases. There is a new gem that does this, MaxMind-DB-Reader-ruby.

Simply download the City or Country binary, gzipped databases from MaxMind, unzip, and use the following sort of code:

require 'maxmind/db'

reader = MaxMind::DB.new('GeoIP2-City.mmdb', mode: MaxMind::DB::MODE_MEMORY)

# you probably want to replace 1.1.1.1 with  request.remote_ip
# or request.env['HTTP_X_FORWARDED_FOR']
ip_addr = '1.1.1.1'
record = reader.get(ip_addr)
if record.nil?
  puts '#{ip_addr} was not found in the database'
else
  puts record['country']['iso_code']
  puts record['country']['names']['en']
end

reader.close

Adapt based on your needs. I created a method in an initializer which I can call as necessary.

我只土不豪 2024-08-23 11:08:41

您可以使用我自己的一项服务来执行此操作,https://ipinfo.io。它为您提供国家/地区代码和一堆其他详细信息:

$ curl ipinfo.io
{
  "ip": "24.6.61.239",
  "hostname": "c-24-6-61-239.hsd1.ca.comcast.net",
  "city": "Mountain View",
  "region": "California",
  "country": "US",
  "loc": "37.3845,-122.0881",
  "org": "AS7922 Comcast Cable Communications, LLC",
  "postal": "94040"
}

如果您只想要国家/地区,您可以通过请求 /country 获得该信息,

$ curl ipinfo.io/country
US

然后您可以使用来自 http://country.io,或使用 http://ipinfo.io/developers/full-country-names

One service you could use to do this is my own, https://ipinfo.io. It gives you country code and a bunch of other details:

$ curl ipinfo.io
{
  "ip": "24.6.61.239",
  "hostname": "c-24-6-61-239.hsd1.ca.comcast.net",
  "city": "Mountain View",
  "region": "California",
  "country": "US",
  "loc": "37.3845,-122.0881",
  "org": "AS7922 Comcast Cable Communications, LLC",
  "postal": "94040"
}

If you just want the country you can get that by requesting /country

$ curl ipinfo.io/country
US

You can then map from a country code to a name using the data from http://country.io, or using the example at http://ipinfo.io/developers/full-country-names

蒗幽 2024-08-23 11:08:41

我刚刚为我创建的 IPLocate.io API 发布了一个 gem。

超级简单,无需下载数据库,每天有 1,500 个免费请求:

require 'iplocate'

# Look up an IP address
results = IPLocate.lookup("8.8.8.8")

# Or with an API key
results = IPLocate.lookup("8.8.8.8", "abcdef")

results["country"]
# "United States"

results["country_code"]
# "US"

results["org"]
# "Google LLC"

results.inspect
# {
#   "ip"=>"8.8.8.8",
#   "country"=>"United States",
#   "country_code"=>"US",
#   "city"=>nil,
#   "continent"=>"North America",
#   "latitude"=>37.751,
#   "longitude"=>-97.822,
#   "time_zone"=>nil,
#   "postal_code"=>nil,
#   "org"=>"Google LLC",
#   "asn"=>"AS15169"
# }  

无 Gem

也可以在没有 gem 的情况下使用 Ruby 的 Net::HTTPURI

response = Net::HTTP.get( URI.parse( "https://www.iplocate.io/api/lookup/8.8.8.8" ) )

该请求将返回 JSON,以便您可以解析它并访问它,如下所示:

country = JSON.parse( response )["country"]
# => "US"

I've just published a gem for the IPLocate.io API which I created.

Super easy, no databases to download, and 1,500 free requests per day:

require 'iplocate'

# Look up an IP address
results = IPLocate.lookup("8.8.8.8")

# Or with an API key
results = IPLocate.lookup("8.8.8.8", "abcdef")

results["country"]
# "United States"

results["country_code"]
# "US"

results["org"]
# "Google LLC"

results.inspect
# {
#   "ip"=>"8.8.8.8",
#   "country"=>"United States",
#   "country_code"=>"US",
#   "city"=>nil,
#   "continent"=>"North America",
#   "latitude"=>37.751,
#   "longitude"=>-97.822,
#   "time_zone"=>nil,
#   "postal_code"=>nil,
#   "org"=>"Google LLC",
#   "asn"=>"AS15169"
# }  

No Gem

It can also be used without a gem by just using Ruby's Net::HTTP and URI:

response = Net::HTTP.get( URI.parse( "https://www.iplocate.io/api/lookup/8.8.8.8" ) )

The request will return JSON so you can parse it and access it as follows:

country = JSON.parse( response )["country"]
# => "US"
爱人如己 2024-08-23 11:08:41

您可以尝试 Yandex locator gem,服务返回经度、纬度和精度。

conn = YandexLocator::Client.new
result = conn.lookup(ip: "109.252.52.39")
# => {"position"=>{"altitude"=>0.0, "altitude_precision"=>30.0, "latitude"=>55.75395965576172, "longitude"=>37.62039184570312, "precision"=>100000.0, "type"=>"ip"}}

You can try Yandex locator gem, service returns longitude, latitude and precision.

conn = YandexLocator::Client.new
result = conn.lookup(ip: "109.252.52.39")
# => {"position"=>{"altitude"=>0.0, "altitude_precision"=>30.0, "latitude"=>55.75395965576172, "longitude"=>37.62039184570312, "precision"=>100000.0, "type"=>"ip"}}
一生独一 2024-08-23 11:08:41

尝试 IP2Location Ruby

https://github.com/ip2location/ip2location-ruby

先决条件

http://lite.ip2location.com/ 下载免费的 LITE 数据库并在下面使用。

安装

gem install ip2location_ruby

使用

require 'ip2location_ruby'

i2l = Ip2location.new.open("./data/IP-COUNTRY-SAMPLE.BIN")
record = i2l.get_all('8.8.8.8')

print 'Country Code: ' + record.country_short + "\n"
print 'Country Name: ' + record.country_long + "\n"
print 'Region Name: ' + record.region + "\n"
print 'City Name: ' + record.city + "\n"
print 'Latitude: '
print record.latitude
print "\n"
print 'Longitude: '
print record.longitude
print "\n"
print 'ISP: ' + record.isp + "\n"
print 'Domain: ' + record.domain + "\n"
print 'Net Speed: ' + record.netspeed + "\n"
print 'Area Code: ' + record.areacode + "\n"
print 'IDD Code: ' + record.iddcode + "\n"
print 'Time Zone: ' + record.timezone + "\n"
print 'ZIP Code: ' + record.zipcode + "\n"
print 'Weather Station Code: ' + record.weatherstationname + "\n"
print 'Weather Station Name: ' + record.weatherstationcode + "\n"
print 'MCC: ' + record.mcc + "\n"
print 'MNC: ' + record.mnc + "\n"
print 'Mobile Name: ' + record.mobilebrand + "\n"
print 'Elevation: '
print record.elevation
print "\n"
print 'Usage Type: ' + record.usagetype + "\n"

Try the IP2Location Ruby

https://github.com/ip2location/ip2location-ruby

Pre-requisite

Download the free LITE database from http://lite.ip2location.com/ and use below.

Install

gem install ip2location_ruby

Usage

require 'ip2location_ruby'

i2l = Ip2location.new.open("./data/IP-COUNTRY-SAMPLE.BIN")
record = i2l.get_all('8.8.8.8')

print 'Country Code: ' + record.country_short + "\n"
print 'Country Name: ' + record.country_long + "\n"
print 'Region Name: ' + record.region + "\n"
print 'City Name: ' + record.city + "\n"
print 'Latitude: '
print record.latitude
print "\n"
print 'Longitude: '
print record.longitude
print "\n"
print 'ISP: ' + record.isp + "\n"
print 'Domain: ' + record.domain + "\n"
print 'Net Speed: ' + record.netspeed + "\n"
print 'Area Code: ' + record.areacode + "\n"
print 'IDD Code: ' + record.iddcode + "\n"
print 'Time Zone: ' + record.timezone + "\n"
print 'ZIP Code: ' + record.zipcode + "\n"
print 'Weather Station Code: ' + record.weatherstationname + "\n"
print 'Weather Station Name: ' + record.weatherstationcode + "\n"
print 'MCC: ' + record.mcc + "\n"
print 'MNC: ' + record.mnc + "\n"
print 'Mobile Name: ' + record.mobilebrand + "\n"
print 'Elevation: '
print record.elevation
print "\n"
print 'Usage Type: ' + record.usagetype + "\n"
一影成城 2024-08-23 11:08:41

以下是调用 ipdata.co API 的 Ruby 示例。

由于拥有 10 个全局端点,每个端点每秒能够处理超过 10,000 个请求,因此它速度快且性能可靠!

此答案使用“测试”API 密钥,该密钥非常有限,仅用于测试一些调用。 注册为您自己的免费 API 密钥,每天最多可收到 1500 个开发请求。

78.8.53.5 替换为您想要查找的任何 ip

require 'rubygems' if RUBY_VERSION < '1.9'
require 'rest_client'

headers = {
  :accept => 'application/json'
}

response = RestClient.get 'https://api.ipdata.co/78.8.53.5?api-key=test', headers
puts response

这会给您

{
    "ip": "78.8.53.5",
    "is_eu": true,
    "city": "G\u0142og\u00f3w",
    "region": "Lower Silesia",
    "region_code": "DS",
    "country_name": "Poland",
    "country_code": "PL",
    "continent_name": "Europe",
    "continent_code": "EU",
    "latitude": 51.6557,
    "longitude": 16.089,
    "asn": "AS12741",
    "organisation": "Netia SA",
    "postal": "67-200",
    "calling_code": "48",
    "flag": "https://ipdata.co/flags/pl.png",
    "emoji_flag": "\ud83c\uddf5\ud83c\uddf1",
    "emoji_unicode": "U+1F1F5 U+1F1F1",
    "carrier": {
        "name": "Netia",
        "mcc": "260",
        "mnc": "07"
    },
    "languages": [
        {
            "name": "Polish",
            "native": "Polski"
        }
    ],
    "currency": {
        "name": "Polish Zloty",
        "code": "PLN",
        "symbol": "z\u0142",
        "native": "z\u0142",
        "plural": "Polish zlotys"
    },
    "time_zone": {
        "name": "Europe/Warsaw",
        "abbr": "CEST",
        "offset": "+0200",
        "is_dst": true,
        "current_time": "2018-08-29T15:34:23.518065+02:00"
    },
    "threat": {
        "is_tor": false,
        "is_proxy": false,
        "is_anonymous": false,
        "is_known_attacker": false,
        "is_known_abuser": false,
        "is_threat": false,
        "is_bogon": false
    },
}

Here's a Ruby example calling the ipdata.co API.

It's fast and has reliable performance thanks to having 10 global endpoints each able to handle >10,000 requests per second!

This answer uses a 'test' API Key that is very limited and only meant for testing a few calls. Signup for your own Free API Key and get up to 1500 requests daily for development.

Replace 78.8.53.5 with any ip you want to look up

require 'rubygems' if RUBY_VERSION < '1.9'
require 'rest_client'

headers = {
  :accept => 'application/json'
}

response = RestClient.get 'https://api.ipdata.co/78.8.53.5?api-key=test', headers
puts response

That'd give you

{
    "ip": "78.8.53.5",
    "is_eu": true,
    "city": "G\u0142og\u00f3w",
    "region": "Lower Silesia",
    "region_code": "DS",
    "country_name": "Poland",
    "country_code": "PL",
    "continent_name": "Europe",
    "continent_code": "EU",
    "latitude": 51.6557,
    "longitude": 16.089,
    "asn": "AS12741",
    "organisation": "Netia SA",
    "postal": "67-200",
    "calling_code": "48",
    "flag": "https://ipdata.co/flags/pl.png",
    "emoji_flag": "\ud83c\uddf5\ud83c\uddf1",
    "emoji_unicode": "U+1F1F5 U+1F1F1",
    "carrier": {
        "name": "Netia",
        "mcc": "260",
        "mnc": "07"
    },
    "languages": [
        {
            "name": "Polish",
            "native": "Polski"
        }
    ],
    "currency": {
        "name": "Polish Zloty",
        "code": "PLN",
        "symbol": "z\u0142",
        "native": "z\u0142",
        "plural": "Polish zlotys"
    },
    "time_zone": {
        "name": "Europe/Warsaw",
        "abbr": "CEST",
        "offset": "+0200",
        "is_dst": true,
        "current_time": "2018-08-29T15:34:23.518065+02:00"
    },
    "threat": {
        "is_tor": false,
        "is_proxy": false,
        "is_anonymous": false,
        "is_known_attacker": false,
        "is_known_abuser": false,
        "is_threat": false,
        "is_bogon": false
    },
}
胡大本事 2024-08-23 11:08:41

gem geoip 可以替换为新的 gem maxminddb。它支持新的 MaxMind 数据库格式。

db = MaxMindDB.new('./GeoLite2-City.mmdb')
ret = db.lookup('74.125.225.224')

ret.found? # => true
ret.country.name # => 'United States'
ret.country.name('zh-CN') # => '美国'
ret.country.iso_code # => 'US'
ret.city.name(:fr) # => 'Mountain View'
ret.subdivisions.most_specific.name # => 'California'
ret.location.latitude # => -122.0574

The gem geoip can be replaced with the new gem maxminddb. It support new MaxMind db format.

db = MaxMindDB.new('./GeoLite2-City.mmdb')
ret = db.lookup('74.125.225.224')

ret.found? # => true
ret.country.name # => 'United States'
ret.country.name('zh-CN') # => '美国'
ret.country.iso_code # => 'US'
ret.city.name(:fr) # => 'Mountain View'
ret.subdivisions.most_specific.name # => 'California'
ret.location.latitude # => -122.0574
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文