Je souhaite extraire un nom de pays d'utilisateur des adresses IP des visiteurs.
Je pourrais obtenir l'adresse IP avec remote_ip
. Mais quel pourrait être le moyen le plus facile d’obtenir le nom du pays?
Il n'est pas nécessaire que ce soit super précis. Une bibliothèque Ruby (gem ou plugin) pour le faire?
Je veux une solution simple et facile pour cela.
Vous pouvez utiliser geoip
gem.
environment.rb
config.gem 'geoip'
Téléchargez GeoIP.dat.gz
à partir de http://www.maxmind.com/app/geolitecountry
. Décompressez le fichier. La liste ci-dessous est définie 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
Vous pouvez également utiliser " Geocoder "
Cela vous facilitera simplement la vie. Mettez la ligne suivante dans votre Gemfile et lancez la commande bundle install
gem 'geocoder'
En utilisant cette gemme, vous pouvez facilement obtenir le pays, l'adresse IP ou même la ville de l'adresse IP d'origine. Voir un exemple ci-dessous
request.ip # => "182.185.141.75"
request.location.city # => ""
request.location.country # => "Pakistan"
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"
Le plus simple consiste à utiliser un service Web existant à cet effet.
Il existe des plugins qui vous permettent de faire beaucoup plus, notamment en rendant vos modèles sensibles à la géolocalisation (geokit-Rails) automatiquement, mais si vous avez simplement besoin d'un code de pays, envoyez simplement un HTTP Get à http://api.hostip.info/country.php
(il existe d'autres services mais ceci on ne nécessite pas de clé API) le renverra, par exemple :
Net::HTTP.get_response(URI.parse('http://api.hostip.info/country.php'))
=> US
Ou polling http://api.hostip.info/ renverra une réponse XML complète avec la ville, la latitude, la longitude, etc.
Sachez que les résultats que vous obtenez ne sont pas précis à 100%. Par exemple, en ce moment je suis en France mais rapporté comme en Allemagne. Ce sera le cas pour à peu près n'importe quel service basé sur IP.
Un service que vous pouvez utiliser pour ce faire est le mien, https://ipinfo.io . Il vous donne le code du pays et une foule 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, vous pouvez l'obtenir en demandant /country
$ curl ipinfo.io/country
US
Vous pouvez ensuite mapper un code de pays sur un nom à l'aide des données de http://country.io ou de l'exemple présenté à http://ipinfo.io/developers/full-country-names
Je viens de publier une gemme pour l'API IPLocate.io que j'ai créée.
Super facile, pas de bases de données à télécharger, et 1 500 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"
# }
Il peut également être utilisé sans joyau en utilisant simplement les Net::HTTP
et URI
de Ruby:
response = Net::HTTP.get( URI.parse( "https://www.iplocate.io/api/lookup/8.8.8.8" ) )
La demande renverra JSON afin que vous puissiez l'analyser et y accéder comme suit:
country = JSON.parse( response )["country"]
# => "US"
Vous pouvez essayer Yandex locator gem , le 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"}}
Voici un exemple Ruby appelant le ipdata.co API.
Il est rapide et offre des performances fiables grâce à 10 points d'extrémité globaux capables chacun de traiter plus de 10 000 requêtes par seconde!
Cette réponse utilise une clé API 'test' très limitée et destinée uniquement à tester quelques appels. Signup pour votre propre clé d’API gratuite et recevez jusqu’à 1500 demandes de développement par jour.
Remplacez 78.8.53.5
par l'adresse IP que vous souhaitez 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?api-key=test', headers
puts response
Ça vous donnerait
{
"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
},
}
Essayez le Ruby IP2Location
https://github.com/ip2location/ip2location-Ruby
Téléchargez gratuitement la base de données LITE à partir de http://lite.ip2location.com/ et utilisez ci-dessous.
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"
La gemme geoip
ne fonctionne plus avec les nouvelles bases de données MaxMind. Il existe un nouveau joyau qui fait cela, MaxMind-DB-Reader-Ruby .
Téléchargez simplement les bases de données binaires Ville ou Pays, gzippées à partir de MaxMind , décompressez-les et utilisez le type de code suivant:
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
Adaptez-vous en fonction de vos besoins. J'ai créé une méthode dans un initialiseur que je peux appeler si nécessaire.