Java - 通过IP地址获取用户所在地

最近在做一个互联网项目,不可避免和其他互联网项目一样,需要各种类似的功能。其中一个就是通过用户访问网站的IP地址显示当前用户所在地。在没有查阅资料之前,我第一个想到的是应该有这样的RESTFUL服务,可能会有免费的,也有可能会是收费的。后来查阅了相关资料和咨询了客服人员发现了一款相当不错的库:GEOIP。

中文官网:http://www.maxmind.com/zh/home?pkit_lang=zh

英文官网:http://www.maxmind.com/en/home

而且GeoIP也提供了如我之前猜测的功能:Web Services,具体可以看这里:http://dev.maxmind.com/geoip/legacy/web-services

这里我就把官方的实例搬过来吧,Web Services :

首先来个Java 版本:

  1. import java.net.MalformedURLException;  
  2. import java.net.URL;  
  3. import java.io.BufferedReader;  
  4. import java.io.InputStreamReader;  
  5. import java.io.IOException;  
  6.   
  7. public class OmniReader {  
  8.     public static void main(String[] args) throws Exception {  
  9.         String license_key = "YOUR_LICENSE_KEY";  
  10.         String ip_address = "24.24.24.24";  
  11.   
  12.         String url_str = "http://geoip.maxmind.com/e?l=" + license_key + "&i=" + ip_address;  
  13.   
  14.         URL url = new URL(url_str);  
  15.         BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));  
  16.         String inLine;  
  17.           
  18.         while ((inLine = in.readLine()) != null) {  
  19.             // Alternatively use a CSV parser here.  
  20.             Pattern p = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)");   
  21.             Matcher m = p.matcher(inLine);  
  22.   
  23.             ArrayList fields = new ArrayList();  
  24.             String f;  
  25.             while (m.find()) {  
  26.                 f = m.group(1);  
  27.                 if (f!=null) {  
  28.                     fields.add(f);  
  29.                 }  
  30.                 else {  
  31.                     fields.add(m.group(2));  
  32.                 }  
  33.             }  
  34.               
  35.             String countrycode = fields.get(0);  
  36.             String countryname = fields.get(1);  
  37.             String regioncode = fields.get(2);  
  38.             String regionname = fields.get(3);  
  39.             String city = fields.get(4);  
  40.             String lat = fields.get(5);  
  41.             String lon = fields.get(6);  
  42.             String metrocode = fields.get(7);  
  43.             String areacode = fields.get(8);  
  44.             String timezone = fields.get(9);  
  45.             String continent = fields.get(10);  
  46.             String postalcode = fields.get(11);  
  47.             String isp = fields.get(12);  
  48.             String org = fields.get(13);  
  49.             String domain = fields.get(14);  
  50.             String asnum = fields.get(15);  
  51.             String netspeed = fields.get(16);  
  52.             String usertype = fields.get(17);  
  53.             String accuracyradius = fields.get(18);  
  54.             String countryconf = fields.get(19);  
  55.             String cityconf = fields.get(20);  
  56.             String regionconf = fields.get(21);  
  57.             String postalconf = fields.get(22);  
  58.             String error = fields.get(23);  
  59.         }  
  60.   
  61.         in.close();  
  62.     }  
  63. }  

C#版本:
  1. private string GetMaxMindOmniData(string IP) {  
  2.   System.Uri objUrl = new System.Uri("http://geoip.maxmind.com/e?l=YOUR_LICENSE_KEY&i=" + IP);  
  3.   System.Net.WebRequest objWebReq;  
  4.   System.Net.WebResponse objResp;  
  5.   System.IO.StreamReader sReader;  
  6.   string strReturn = string.Empty;  
  7.   
  8.   try  
  9.     {  
  10.       objWebReq = System.Net.WebRequest.Create(objUrl);  
  11.       objResp = objWebReq.GetResponse();  
  12.   
  13.       sReader = new System.IO.StreamReader(objResp.GetResponseStream());  
  14.       strReturn = sReader.ReadToEnd();  
  15.   
  16.       sReader.Close();  
  17.       objResp.Close();  
  18.     }  
  19.   catch (Exception ex)  
  20.     {  
  21.     }  
  22.   finally  
  23.     {  
  24.       objWebReq = null;  
  25.     }  
  26.   
  27.   return strReturn;  
  28. }  

Ruby版本:
  1. #!/usr/bin/env ruby  
  2.   
  3. require 'csv'  
  4. require 'net/http'  
  5. require 'open-uri'  
  6. require 'optparse'  
  7. require 'uri'  
  8.   
  9. fields = [:country_code,  
  10.           :country_name,  
  11.           :region_code,  
  12.           :region_name,  
  13.           :city_name,  
  14.           :latitude,  
  15.           :longitude,  
  16.           :metro_code,  
  17.           :area_code,  
  18.           :time_zone,  
  19.           :continent_code,  
  20.           :postal_code,  
  21.           :isp_name,  
  22.           :organization_name,  
  23.           :domain,  
  24.           :as_number,  
  25.           :netspeed,  
  26.           :user_type,  
  27.           :accuracy_radius,  
  28.           :country_confidence,  
  29.           :city_confidence,  
  30.           :region_confidence,  
  31.           :postal_confidence,  
  32.           :error]  
  33.   
  34. options = { :license => "YOUR_LICENSE_KEY":ip => "24.24.24.24" }  
  35. OptionParser.new { |opts|  
  36.   opts.banner = "Usage: omni-geoip-ws.rb [options]"  
  37.   
  38.   opts.on("-l""--license LICENSE""MaxMind license key"do |l|  
  39.     options[:license] = l  
  40.   end  
  41.   
  42.   opts.on("-i""--ip IPADDRESS""IP address to look up"do |i|  
  43.     options[:ip] = i  
  44.   end  
  45. }.parse!  
  46.   
  47. uri = URI::HTTP.build(:scheme => 'http',  
  48.                       :host   => 'geoip.maxmind.com',  
  49.                       :path   => '/e',  
  50.                       :query  => URI.encode_www_form(:l => options[:license],  
  51.                                                      :i => options[:ip]))  
  52.   
  53. response = Net::HTTP.get_response(uri)  
  54.   
  55. unless response.is_a?(Net::HTTPSuccess)  
  56.   abort "Request failed with status #{response.code}"  
  57. end  
  58.   
  59. omni = Hash[fields.zip(response.body.encode('utf-8''iso-8859-1').parse_csv)]  
  60.   
  61. if omni[:error]  
  62.   abort "MaxMind returned an error code for the request: #{omni[:error]}"  
  63. else  
  64.   puts  
  65.   puts "MaxMind Omni data for #{options[:ip]}";  
  66.   puts  
  67.   omni.each { |key, val| printf "  %-20s  %s\n", key, val }  
  68.   puts  
  69. end  

最后再来个Perl版本吧:
  1. #!/usr/bin/env perl  
  2.   
  3. use strict;  
  4. use warnings;  
  5.   
  6. use Encode qw( decode );  
  7. use Getopt::Long;  
  8. use LWP::UserAgent;  
  9. use Text::CSV_XS;  
  10. use URI;  
  11. use URI::QueryParam;  
  12.   
  13. my @fields = qw(  
  14.     country_code  
  15.     country_name  
  16.     region_code  
  17.     region_name  
  18.     city_name  
  19.     latitude  
  20.     longitude  
  21.     metro_code  
  22.     area_code  
  23.     time_zone  
  24.     continent_code  
  25.     postal_code  
  26.     isp_name  
  27.     organization_name  
  28.     domain  
  29.     as_number  
  30.     netspeed  
  31.     user_type  
  32.     accuracy_radius  
  33.     country_confidence  
  34.     city_confidence  
  35.     region_confidence  
  36.     postal_confidence  
  37.     error  
  38. );  
  39.   
  40. my $license_key = 'YOUR_LICENSE_KEY';  
  41. my $ip_address  = '24.24.24.24';  
  42.   
  43. GetOptions(  
  44.     'license:s' => \$license_key,  
  45.     'ip:s'      => \$ip_address,  
  46. );  
  47.   
  48. my $uri = URI->new('http://geoip.maxmind.com/e');  
  49. $uri->query_param( l => $license_key );  
  50. $uri->query_param( i => $ip_address );  
  51.   
  52. my $ua = LWP::UserAgent->new( timeout => 5 );  
  53. my $response = $ua->get($uri);  
  54.   
  55. die 'Request failed with status ' . $response->code()  
  56.     unless $response->is_success();  
  57.   
  58. my $csv = Text::CSV_XS->new( { binary => 1 } );  
  59. $csv->parse( decode( 'ISO-8859-1', $response->content() ) );  
  60.   
  61. my %omni;  
  62. @omni{@fields} = $csv->fields();  
  63.   
  64. binmode STDOUT, ':encoding(UTF-8)';  
  65.   
  66. if ( defined $omni{error} && length $omni{error} ) {  
  67.     die "MaxMind returned an error code for the request: $omni{error}\n";  
  68. }  
  69. else {  
  70.     print "\nMaxMind Omni data for $ip_address\n\n";  
  71.     for my $field (@fields) {  
  72.         print sprintf( "  %-20s  %s\n", $field, $omni{$field} );  
  73.     }  
  74.     print "\n";  
  75. }  

以上都是基于Web Services的,这里我再写个使用本地库的实例,而项目中也使用的是本地库。

首先在项目中需要添加库文件:GeoLiteCity,然后就可以利用这个文件得到城市和国家信息了。项目中如何获取到用户访问的IP地址就不用我说了吧,做过Web开发的人应该都知道。Request里面获取。Java代码:

  1. public class GeoBusiness {  
  2.     /** 
  3.      * @param args 
  4.      * @throws IOException 
  5.      */  
  6.     public static void main(String[] args) throws IOException {  
  7.         // TODO Auto-generated method stub  
  8.         System.out.println(getLocationByIp("220.181.111.147").getCity());  
  9.         System.out.println(getLocationByIp("220.181.111.147").getCountryName());  
  10.     }  
  11.   
  12.     public static Location getLocationByIp(String ipaddr) throws IOException {  
  13.         String sep = System.getProperty("file.separator");  
  14.         String dir = Play.configuration.getProperty("geoip.datdir");  
  15.         String dbfile = dir + sep + "GeoLiteCity.dat";  
  16.         LookupService cl = new LookupService(dbfile,  
  17.                 LookupService.GEOIP_MEMORY_CACHE);  
  18.         Location location = cl.getLocation(ipaddr);  
  19.   
  20.         cl.close();  
  21.         return location;  
  22.     }  
  23. }  

更详细的功能比如获取省,经纬度可以参考我最前面给出的网址。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
纯真 IP 库是一个比较常用的 IP 归属地查询库,可以在 Java 中通过读取纯真 IP 库的二进制文件来获取 IP 地址的国家和地区信息。 以下是一个使用纯真 IP 库查询 IP 地址归属地的示例代码: ```java import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; public class IP2CountryExample { public static void main(String[] args) { String ip = "127.0.0.1"; try { File file = new File("C:\\Program Files (x86)\\QQBrowser\\QQBrowser.exe"); RandomAccessFile raf = new RandomAccessFile(file, "r"); // 读取索引区头信息 int indexStart = raf.readIntLE(); int indexEnd = raf.readIntLE(); int indexCount = (indexEnd - indexStart) / 7 + 1; // 二分查找 IP 地址所在的索引 long ipLong = ipToLong(ip); int low = 0, high = indexCount - 1; while (low <= high) { int mid = (low + high) / 2; long midIp = readIp(raf, indexStart + mid * 7); if (ipLong < midIp) { high = mid - 1; } else if (ipLong > midIp) { low = mid + 1; } else { // 找到了对应的索引 int countryOffset = readInt24(raf); raf.seek(countryOffset); byte countryFlag = raf.readByte(); if (countryFlag == 1) { // 表示国家信息被重定向到其他位置 int redirectOffset = readInt24(raf); raf.seek(redirectOffset); } String country = raf.readLine(); System.out.println("Country: " + country); break; } } raf.close(); } catch (IOException ex) { ex.printStackTrace(); } } // 把 IP 地址转换成 long 类型 private static long ipToLong(String ip) { String[] ips = ip.split("\\."); long result = 0; for (int i = 0; i < ips.length; i++) { result = result * 256 + Integer.parseInt(ips[i]); } return result; } // 从文件指定位置读取 3 字节无符号整数 private static int readInt24(RandomAccessFile raf) throws IOException { byte[] bytes = new byte[3]; raf.readFully(bytes); return ((bytes[2] & 0xFF) << 16) | ((bytes[1] & 0xFF) << 8) | (bytes[0] & 0xFF); } // 从文件指定位置读取 4 字节无符号整数 private static long readInt32(RandomAccessFile raf, long pos) throws IOException { raf.seek(pos); int ch1 = raf.read(); int ch2 = raf.read(); int ch3 = raf.read(); int ch4 = raf.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new IOException("EOF"); } return ((long) ch1 << 24) + ((long) ch2 << 16) + ((long) ch3 << 8) + (ch4 & 0xFF); } // 从文件指定位置读取 4 字节有符号整数 private static int readInt32LE(RandomAccessFile raf, long pos) throws IOException { raf.seek(pos); int ch1 = raf.read(); int ch2 = raf.read(); int ch3 = raf.read(); int ch4 = raf.read(); if ((ch1 | ch2 | ch3 | ch4) < 0) { throw new IOException("EOF"); } return (ch4 << 24) | (ch3 << 16) | (ch2 << 8) | ch1; } // 从文件指定位置读取 4 字节无符号整数 private static long readUInt32LE(RandomAccessFile raf, long pos) throws IOException { return readInt32LE(raf, pos) & 0xFFFFFFFFL; } // 从文件指定位置读取 IP 地址 private static long readIp(RandomAccessFile raf, long pos) throws IOException { return readUInt32LE(raf, pos); } } ``` 在这个示例中,我们使用了纯真 IP 库的二进制文件,通过读取索引区头信息和 IP 地址所在的索引,然后读取对应的国家信息来获取 IP 地址的归属地信息。需要注意的是,这个示例代码仅仅是一个演示,实际使用中需要根据具体的纯真 IP 库版本进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值