Getting a user country name from originating IP ad

2019-01-16 03:03发布

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.

10条回答
相关推荐>>
2楼-- · 2019-01-16 03:36

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.

查看更多
太酷不给撩
3楼-- · 2019-01-16 03:43

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"}}
查看更多
够拽才男人
4楼-- · 2019-01-16 03:45

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"
查看更多
放荡不羁爱自由
5楼-- · 2019-01-16 03:49

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
查看更多
仙女界的扛把子
6楼-- · 2019-01-16 03:49

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
    },
}
查看更多
疯言疯语
7楼-- · 2019-01-16 03:51

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

查看更多
登录 后发表回答