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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1988049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:05:43  来源:igfitidea点击:

Getting a user country name from originating IP address with Ruby on Rails

ruby-on-railsip-geolocation

提问by TK.

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

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

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

我可以通过remote_ip. 但是获得国家名称的最简单方法是什么?

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.

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

回答by Chandra Patni

You can use geoipgem.

您可以使用geoip宝石。

environment.rb

环境文件

config.gem 'geoip'

Download GeoIP.dat.gzfrom http://www.maxmind.com/app/geolitecountry. unzip the file. The below assumes under #{RAILS_ROOT}/dbdir.

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

@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

回答by Nadeem Yasin

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

它只会让你的生活更轻松。将以下行放入 Gemfile 并发出 bundle install 命令

gem 'geocoder'

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

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

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

回答by stef

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"

回答by JRL

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

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

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. :

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

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.

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

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.

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

回答by Ben Dowling

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:

您可以用来执行此操作的一项服务是我自己的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"
}

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

如果你只想要这个国家,你可以通过请求获得 /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

然后,您可以使用http://country.io 中的数据或使用http://ipinfo.io/developers/full-country-names 中的示例从国家/地区代码映射到名称

回答by ttarik

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

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

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

超级简单,无需下载数据库,每天有 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"
# }  

No Gem

没有宝石

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

它也可以在没有 gem 的情况下使用,只需使用 Ruby 的Net::HTTPand 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:

该请求将返回 JSON,因此您可以解析它并按如下方式访问它:

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

回答by Artelius

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

geoip宝石不再与新的MaxMind数据库工作。有一个新的 gem 可以做到这一点,MaxMind-DB-Reader-ruby

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

只需从MaxMind下载 City 或 Country 二进制文件、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

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

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

回答by Pioz

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

宝石geoip可以用新宝石替换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

回答by Vlam

Try the IP2Location Ruby

尝试 IP2Location Ruby

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

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

Pre-requisite

先决条件

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

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

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"

回答by Jonathan

Here's a Ruby example calling the ipdata.coAPI.

这是一个调用ipdata.coAPI的 Ruby 示例。

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

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

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

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

Replace 78.8.53.5with any ip you want to look up

替换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

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
    },
}