Identifying country by IP address

前端 未结 13 897
盖世英雄少女心
盖世英雄少女心 2020-12-01 05:24

Is there a way to figure out the country name just by looking at an IP address? I mean, do countries have specific ranges of IP addresses? For example, Australia can have IP

相关标签:
13条回答
  • 2020-12-01 05:39

    Here is my solution in Python 3.x to return geo-location info given a dataframe containing IP Address(s); efficient parallelized application of function on vectorized pd.series/dataframe is the way to go.

    Will contrast performance of two popular libraries to return location.

    TLDR: use geolite2 method.

    1. geolite2 package from geolite2 library

    Input

    # !pip install maxminddb-geolite2
    import time
    from geolite2 import geolite2
    geo = geolite2.reader()
    df_1 = train_data.loc[:50,['IP_Address']]
    
    def IP_info_1(ip):
        try:
            x = geo.get(ip)
        except ValueError:   #Faulty IP value
            return np.nan
        try:
            return x['country']['names']['en'] if x is not None else np.nan
        except KeyError:   #Faulty Key value
            return np.nan
    
    s_time = time.time()
    # map IP --> country
    #apply(fn) applies fn. on all pd.series elements
    df_1['country'] = df_1.loc[:,'IP_Address'].apply(IP_info_1)
    print(df_1.head(), '\n')
    print('Time:',str(time.time()-s_time)+'s \n')
    
    print(type(geo.get('48.151.136.76')))
    

    Output

           IP_Address         country
    0   48.151.136.76   United States
    1    94.9.145.169  United Kingdom
    2   58.94.157.121           Japan
    3  193.187.41.186         Austria
    4   125.96.20.172           China 
    
    Time: 0.09906983375549316s 
    
    <class 'dict'>
    

    2. DbIpCity package from ip2geotools library

    Input

    # !pip install ip2geotools
    import time
    s_time = time.time()
    from ip2geotools.databases.noncommercial import DbIpCity
    df_2 = train_data.loc[:50,['IP_Address']]
    def IP_info_2(ip):
        try:
            return DbIpCity.get(ip, api_key = 'free').country
        except:
            return np.nan
    df_2['country'] = df_2.loc[:, 'IP_Address'].apply(IP_info_2)
    print(df_2.head())
    print('Time:',str(time.time()-s_time)+'s')
    
    print(type(DbIpCity.get('48.151.136.76',api_key = 'free')))
    

    Output

           IP_Address country
    0   48.151.136.76      US
    1    94.9.145.169      GB
    2   58.94.157.121      JP
    3  193.187.41.186      AT
    4   125.96.20.172      CN
    
    Time: 80.53318452835083s 
    
    <class 'ip2geotools.models.IpLocation'>
    

    A reason why the huge time difference could be due to the Data structure of the output, i.e direct subsetting from dictionaries seems way more efficient than indexing from the specicialized ip2geotools.models.IpLocation object.

    Also, the output of the 1st method is dictionary containing geo-location data, subset respecitively to obtain needed info:

    x = geolite2.reader().get('48.151.136.76')
    print(x)
    
    >>>
        {'city': {'geoname_id': 5101798, 'names': {'de': 'Newark', 'en': 'Newark', 'es': 'Newark', 'fr': 'Newark', 'ja': 'ニューアーク', 'pt-BR': 'Newark', 'ru': 'Ньюарк'}},
    
     'continent': {'code': 'NA', 'geoname_id': 6255149, 'names': {'de': 'Nordamerika', 'en': 'North America', 'es': 'Norteamérica', 'fr': 'Amérique du Nord', 'ja': '北アメリカ', 'pt-BR': 'América do Norte', 'ru': 'Северная Америка', 'zh-CN': '北美洲'}}, 
    
    'country': {'geoname_id': 6252001, 'iso_code': 'US', 'names': {'de': 'USA', 'en': 'United States', 'es': 'Estados Unidos', 'fr': 'États-Unis', 'ja': 'アメリカ合衆国', 'pt-BR': 'Estados Unidos', 'ru': 'США', 'zh-CN': '美国'}}, 
    
    'location': {'accuracy_radius': 1000, 'latitude': 40.7355, 'longitude': -74.1741, 'metro_code': 501, 'time_zone': 'America/New_York'}, 
    
    'postal': {'code': '07102'}, 
    
    'registered_country': {'geoname_id': 6252001, 'iso_code': 'US', 'names': {'de': 'USA', 'en': 'United States', 'es': 'Estados Unidos', 'fr': 'États-Unis', 'ja': 'アメリカ合衆国', 'pt-BR': 'Estados Unidos', 'ru': 'США', 'zh-CN': '美国'}}, 
    
    'subdivisions': [{'geoname_id': 5101760, 'iso_code': 'NJ', 'names': {'en': 'New Jersey', 'es': 'Nueva Jersey', 'fr': 'New Jersey', 'ja': 'ニュージャージー州', 'pt-BR': 'Nova Jérsia', 'ru': 'Нью-Джерси', 'zh-CN': '新泽西州'}}]}
    
    0 讨论(0)
  • 2020-12-01 05:40

    I agree with above answers, the best way to get country from ip address is Maxmind.

    If you want to write code in java, you might want to use i.e. geoip-api-1.2.10.jar and geoIP dat files (GeoIPCity.dat), which can be found via google.

    Following code may be useful for you to get almost all information related to location, I am also using the same code.

    public static String getGeoDetailsUsingMaxmind(String ipAddress, String desiredValue) 
        {
            Location getLocation;
            String returnString = "";
            try
            {
                String geoIPCity_datFile = System.getenv("AUTOMATION_HOME").concat("/tpt/GeoIP/GeoIPCity.dat");
                LookupService isp = new LookupService(geoIPCity_datFile);
                getLocation = isp.getLocation(ipAddress);
                isp.close();
    
                //Getting all location details 
                if(desiredValue.equalsIgnoreCase("latitude") || desiredValue.equalsIgnoreCase("lat"))
                {
                    returnString = String.valueOf(getLocation.latitude);
                }
                else if(desiredValue.equalsIgnoreCase("longitude") || desiredValue.equalsIgnoreCase("lon"))
                {
                    returnString = String.valueOf(getLocation.longitude);
                }
                else if(desiredValue.equalsIgnoreCase("countrycode") || desiredValue.equalsIgnoreCase("country"))
                {
                    returnString = getLocation.countryCode;
                }
                else if(desiredValue.equalsIgnoreCase("countryname"))
                {
                    returnString = getLocation.countryName;
                }
                else if(desiredValue.equalsIgnoreCase("region"))
                {
                    returnString = getLocation.region;
                }
                else if(desiredValue.equalsIgnoreCase("metro"))
                {
                    returnString = String.valueOf(getLocation.metro_code);
                }
                else if(desiredValue.equalsIgnoreCase("city"))
                {
                    returnString = getLocation.city;
                }
                else if(desiredValue.equalsIgnoreCase("zip") || desiredValue.equalsIgnoreCase("postalcode"))
                {
                    returnString = getLocation.postalCode;
                }
                else
                {
                    returnString = "";
                    System.out.println("There is no value found for parameter: "+desiredValue);
                }
    
                System.out.println("Value of: "+desiredValue + " is: "+returnString + " for ip address: "+ipAddress);
            }
            catch (Exception e) 
            {
                System.out.println("Exception occured while getting details from max mind. " + e);
            }
            finally
            {
                return returnString;
            }
        }
    
    0 讨论(0)
  • 2020-12-01 05:41

    You can try using https://ip-api.io - geo location api that returns country among other IP information.

    For example with Node.js

    const request = require('request-promise')
    
    request('http://ip-api.io/api/json/1.2.3.4')
      .then(response => console.log(JSON.parse(response)))
      .catch(err => console.log(err))
    
    0 讨论(0)
  • 2020-12-01 05:45

    I know that it is a very old post but for the sake of the users who are landed here and looking for a solution, if you are using Cloudflare as your DNS then you can activate IP geolocation and get the value from the request header,

    here is the code snippet in C# after you enable IP geolocation in Cloudflare through the network tab

     var countryCode = HttpContext.Request.Headers.Get("cf-ipcountry"); // in older asp.net versions like webform use HttpContext.Current.Request. ...
     var countryName = new RegionInfo(CountryCode)?.EnglishName;
    

    you can simply map it to other programming languages, please take a look at the Cloudflare's documentation here


    but if you are really insisting on using a 3rd party solution to have more precise information about the visitors using their IP here is a complete, ready to use implementation using C#:

    the 3rd party I have used is https://ipstack.com, you can simply register for a free plan and get an access token to use for 10K API requests each month, I am using the JSON model to retrieve and like to convert all the info the API gives me, here we go:

    The DTO:

        using System;
        using Newtonsoft.Json;
    
         public partial class GeoLocationModel
         {
            [JsonProperty("ip")]
            public string Ip { get; set; }
    
            [JsonProperty("hostname")]
            public string Hostname { get; set; }
    
            [JsonProperty("type")]
            public string Type { get; set; }
    
            [JsonProperty("continent_code")]
            public string ContinentCode { get; set; }
    
            [JsonProperty("continent_name")]
            public string ContinentName { get; set; }
    
            [JsonProperty("country_code")]
            public string CountryCode { get; set; }
    
            [JsonProperty("country_name")]
            public string CountryName { get; set; }
    
            [JsonProperty("region_code")]
            public string RegionCode { get; set; }
    
            [JsonProperty("region_name")]
            public string RegionName { get; set; }
    
            [JsonProperty("city")]
            public string City { get; set; }
    
            [JsonProperty("zip")]
            public long Zip { get; set; }
    
            [JsonProperty("latitude")]
            public double Latitude { get; set; }
    
            [JsonProperty("longitude")]
            public double Longitude { get; set; }
    
            [JsonProperty("location")]
            public Location Location { get; set; }
    
            [JsonProperty("time_zone")]
            public TimeZone TimeZone { get; set; }
    
            [JsonProperty("currency")]
            public Currency Currency { get; set; }
    
            [JsonProperty("connection")]
            public Connection Connection { get; set; }
    
            [JsonProperty("security")]
            public Security Security { get; set; }
         }
    
        public partial class Connection
        {
            [JsonProperty("asn")]
            public long Asn { get; set; }
    
            [JsonProperty("isp")]
            public string Isp { get; set; }
        }
    
        public partial class Currency
        {
            [JsonProperty("code")]
            public string Code { get; set; }
    
            [JsonProperty("name")]
            public string Name { get; set; }
    
            [JsonProperty("plural")]
            public string Plural { get; set; }
    
            [JsonProperty("symbol")]
            public string Symbol { get; set; }
    
            [JsonProperty("symbol_native")]
            public string SymbolNative { get; set; }
        }
    
        public partial class Location
        {
            [JsonProperty("geoname_id")]
            public long GeonameId { get; set; }
    
            [JsonProperty("capital")]
            public string Capital { get; set; }
    
            [JsonProperty("languages")]
            public Language[] Languages { get; set; }
    
            [JsonProperty("country_flag")]
            public Uri CountryFlag { get; set; }
    
            [JsonProperty("country_flag_emoji")]
            public string CountryFlagEmoji { get; set; }
    
            [JsonProperty("country_flag_emoji_unicode")]
            public string CountryFlagEmojiUnicode { get; set; }
    
            [JsonProperty("calling_code")]
            public long CallingCode { get; set; }
    
            [JsonProperty("is_eu")]
            public bool IsEu { get; set; }
        }
    
        public partial class Language
        {
            [JsonProperty("code")]
            public string Code { get; set; }
    
            [JsonProperty("name")]
            public string Name { get; set; }
    
            [JsonProperty("native")]
            public string Native { get; set; }
        }
    
        public partial class Security
        {
            [JsonProperty("is_proxy")]
            public bool IsProxy { get; set; }
    
            [JsonProperty("proxy_type")]
            public object ProxyType { get; set; }
    
            [JsonProperty("is_crawler")]
            public bool IsCrawler { get; set; }
    
            [JsonProperty("crawler_name")]
            public object CrawlerName { get; set; }
    
            [JsonProperty("crawler_type")]
            public object CrawlerType { get; set; }
    
            [JsonProperty("is_tor")]
            public bool IsTor { get; set; }
    
            [JsonProperty("threat_level")]
            public string ThreatLevel { get; set; }
    
            [JsonProperty("threat_types")]
            public object ThreatTypes { get; set; }
        }
    
        public partial class TimeZone
        {
            [JsonProperty("id")]
            public string Id { get; set; }
    
            [JsonProperty("current_time")]
            public DateTimeOffset CurrentTime { get; set; }
    
            [JsonProperty("gmt_offset")]
            public long GmtOffset { get; set; }
    
            [JsonProperty("code")]
            public string Code { get; set; }
    
            [JsonProperty("is_daylight_saving")]
            public bool IsDaylightSaving { get; set; }
        }
    

    The Helper:

        using System.Configuration;
        using System.IO;
        using System.Net;
        using System.Threading.Tasks;
    
        public class GeoLocationHelper
        {
            public static async Task<GeoLocationModel> GetGeoLocationByIp(string ipAddress)
            {
                var request = WebRequest.Create(string.Format("http://api.ipstack.com/{0}?access_key={1}", ipAddress, ConfigurationManager.AppSettings["ipStackAccessKey"]));
                var response = await request.GetResponseAsync();
                using (var stream = new StreamReader(response.GetResponseStream()))
                {
                    var jsonGeoData = await stream.ReadToEndAsync();
                    return Newtonsoft.Json.JsonConvert.DeserializeObject<GeoLocationModel>(jsonGeoData);
                }
            }
        }
    
    0 讨论(0)
  • 2020-12-01 05:45

    Yes, you can download the IP address ranges by country from https://lite.ip2location.com/ip-address-ranges-by-country

    You can see that each country has multiple ranges and changes frequently.

    0 讨论(0)
  • IP addresses are quite commonly used for geo-targeting i.e. customizing the content of a website by the visitor's location / country but they are not permanently associated with a country and often get re-assigned.

    To accomplish what you want, you need to keep an up to date lookup to map an IP address to a country either with a database or a geolocation API. Here's an example :

    > https://ipapi.co/8.8.8.8/country
    US
    
    > https://ipapi.co/8.8.8.8/country_name
    United States
    

    Or you can use the full API to get complete location for IP address e.g.

    https://ipapi.co/8.8.8.8/json
    
    {
        "ip": "8.8.8.8",
        "city": "Mountain View",
        "region": "California",
        "region_code": "CA",
        "country": "US",
        "country_name": "United States",
        "continent_code": "NA",
        "postal": "94035",
        "latitude": 37.386,
        "longitude": -122.0838,
        "timezone": "America/Los_Angeles",
        "utc_offset": "-0800",
        "country_calling_code": "+1",
        "currency": "USD",
        "languages": "en-US,es-US,haw,fr",
        "asn": "AS15169",
        "org": "Google Inc."
    }
    
    0 讨论(0)
提交回复
热议问题