2010-01-01 5 views
29

Je souhaite extraire un nom de pays utilisateur des adresses IP des visiteurs. J'ai pu obtenir l'adresse IP avec remote_ip. Mais qu'est-ce qui pourrait être le moyen le plus facile d'obtenir le nom du pays?Obtention d'un nom de pays utilisateur à partir de l'adresse IP d'origine avec Ruby on Rails

Il n'est pas nécessaire d'être super précis. Toute bibliothèque ruby ​​(gem ou plugin) pour le faire?

Je veux une solution simple et facile pour cela.

+0

https://ipdata.co est un grand service pour cela, essayez un test rapide dans le navigateur avec une visite à https: // api. ipdata.co – Jonathan

Répondre

47

Vous pouvez utiliser geoip gem.

environment.rb

config.gem 'geoip' 

Télécharger GeoIP.dat.gz de http://www.maxmind.com/app/geolitecountry. décompressez le fichier. Le ci-dessous suppose sous #{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 
+1

On dirait qu'ils ont changé le format de ce fichier, car si le nom complet est ce que vous voulez, location_location [5] est le chemin à parcourir. – miccet

+2

En fait, à partir de geoip 1.1.1, vous pouvez user @ geoip.country (ip) .country_name – ndrix

6

Le plus simple est d'utiliser un service Web existant pour cela.

Il existe des plugins qui vous permettent d'en faire beaucoup plus, notamment de rendre vos modèles géolocalisés (geokit-rails) automatiquement, mais si tout ce dont vous avez besoin est un code de pays, envoyez simplement un HTTP Get to http://api.hostip.info/country.php (il y a autres services, mais celui-ci ne nécessite pas de clé API) le retournera, par exemple :

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


Ou vote http://api.hostip.info/ renvoie une réponse XML complète avec la ville, latitude, longitude, etc.

Soyez conscient que les résultats que vous obtenez ne sont pas précis à 100%. Par exemple, en ce moment je suis en France mais signalé comme en Allemagne. Ce sera le cas pour pratiquement tous les services IP.

+0

Vous pouvez transmettre l'adresse IP de l'utilisateur visiteur à cette API en tant que paramètre http://api.hostip.info/?ip = 217.132.3.54 ce qui signifie que vous pouvez faire Net :: HTTP.get_response (URI.parse ('http://api.hostip.info/country.php?ip=' + request.remote_ip)) (Je ne sais pas pourquoi; le caractère apparaît et je ne peux pas m'en débarrasser) – stef

+1

Ouais cela semble être l'option la plus simple. Une autre API que vous pouvez utiliser est http://ipinfo.io, qui renverra des détails JSON complets si vous le demandez juste, ou vous pouvez obtenir juste la chaîne de pays avec http://ipinfo.io/country –

+0

@BenDowling +1 pour [ipinfo.io] (http://ipinfo.io/) - Je viens de tester une douzaine d'exemples du monde réel et hostip.info a échoué le plus alors que ipinfo.io n'a pas manqué. Des prix très raisonnables/limites de taux aussi. – Yarin

8

J'utilise ce 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" 
+0

Incroyable, c'est ce que je cherchais. Merci beaucoup ! – sidney

+0

Réponse parfaite. Merci beaucoup! J'ai également ajouté quelque chose comme 'locale = 'US' si locale == 'XX''. Dans certains cas, api.hostip.info a renvoyé «XX», donc je l'attrape aussi. – Tobias

+0

En y repensant, il y a un risque que ce service expire, donc vous devriez probablement mettre cela sur un appel asynchrone et le renvoyer au navigateur via un socket Web ou par interrogation.Et cache le résultat dans quelque chose comme memcache ou redis. – stef

23

Vous pouvez également utiliser "Geocoder"

Il va simplement vous rendre la vie plus facile. Mettez la ligne suivante dans votre Gemfile et délivrer le paquet commande install

gem 'geocoder' 

L'utilisation de ce petit bijou, vous pouvez facilement obtenir le pays, IP ou même ville de l'IP d'origine. Voir un exemple ci-dessous

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

Y at-il une limite avec cette gemme? Quel type de fournisseur utilisez-vous avec cette gemme? J'ai compris qu'il y a des limites de 2500 demandes par jour. Corrigez-moi si j'ai tort, s'il-vous plait. Je vous remercie!. La documentation est un peu confuse. – hyperrjas

+0

@hyperrjas oui si vous utilisez API de Google, vous pouvez vérifier le quota par chaque fournisseur à partir de ce lien https://github.com/alexreisner/geocoder#listing-and-comparison – mohamagdy

1

Vous pouvez Yandex locator gem, service renvoie la longitude, la latitude et la précision.

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"}} 
2

Un service que vous pouvez utiliser pour ce faire est le mien, https://ipinfo.io.Il vous donne le code du pays et un tas d'autres détails:

$ 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" 
} 

Si vous voulez juste le pays que vous pouvez obtenir qu'en demandant /country

$ curl ipinfo.io/country 
US 

Vous pouvez ensuite la carte à partir d'un code de pays à un nom en utilisant les données de http://country.io, ou en utilisant l'exemple à http://ipinfo.io/developers/full-country-names

+0

'% x (curl 'ipinfo.io/country ') 'est le bon code à utiliser. Renvoie-t-il le pays du serveur ou le pays du client? Y a-t-il des limites de quota ou d'autres limitations à respecter? – Asarluhi

+1

Si vous l'appelez depuis le serveur, il retournera l'adresse IP du serveur - vous devez transmettre l'adresse IP du client. Voir https://ipinfo.io/developers –

1

Voici un exemple Ruby appelant l'API https://ipdata.co.

Il est rapide et très évolutif avec 10 points de terminaison globaux capables de gérer des appels> 800M par jour.

Remplacer 78.8.53.5 avec un IP que vous voulez rechercher

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', headers 
puts response 

Ce serait vous donner

{ 
    "ip": "78.8.53.5", 
    "city": "G\u0142og\u00f3w", 
    "region": "Lower Silesia", 
    "country_name": "Poland", 
    "country_code": "PL", 
    "continent_name": "Europe", 
    "continent_code": "EU", 
    "latitude": 51.663, 
    "longitude": 16.0757, 
    "asn": "AS12741", 
    "organisation": "Netia SA", 
    "postal": "67-200", 
    "currency": "PLN", 
    "currency_symbol": "z\u0142", 
    "calling_code": "48", 
    "flag": "https://ipdata.co/flags/pl.png", 
    "time_zone": "Europe/Warsaw" 
} 
0

Je viens de publier un petit bijou pour le IPLocate.io API que j'ai créé.

Super facile, aucune base de données à télécharger, et 1500 demandes gratuites par jour:

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" 
# } 
0

Essayez le IP2Location Ruby

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

Pré-requis

Télécharger le Lite gratuitement base de données de http://lite.ip2location.com/ et utiliser ci-dessous.

Installer

gem install ip2location_ruby 

Utilisation

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"