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 版本:

 

import java.net.MalformedURLException;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class OmniReader {
    public static void main(String[] args) throws Exception {
        String license_key = "YOUR_LICENSE_KEY";
        String ip_address = "24.24.24.24";

        String url_str = "http://geoip.maxmind.com/e?l=" + license_key + "&i=" + ip_address;

        URL url = new URL(url_str);
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String inLine;
       
        while ((inLine = in.readLine()) != null) {
            // Alternatively use a CSV parser here.
            Pattern p = Pattern.compile("\"([^\"]*)\"|(?<=,|^)([^,]*)(?:,|$)");
            Matcher m = p.matcher(inLine);

            ArrayList fields = new ArrayList();
            String f;
            while (m.find()) {
                f = m.group(1);
                if (f!=null) {
                    fields.add(f);
                }
                else {
                    fields.add(m.group(2));
                }
            }
           
            String countrycode = fields.get(0);
            String countryname = fields.get(1);
            String regioncode = fields.get(2);
            String regionname = fields.get(3);
            String city = fields.get(4);
            String lat = fields.get(5);
            String lon = fields.get(6);
            String metrocode = fields.get(7);
            String areacode = fields.get(8);
            String timezone = fields.get(9);
            String continent = fields.get(10);
            String postalcode = fields.get(11);
            String isp = fields.get(12);
            String org = fields.get(13);
            String domain = fields.get(14);
            String asnum = fields.get(15);
            String netspeed = fields.get(16);
            String usertype = fields.get(17);
            String accuracyradius = fields.get(18);
            String countryconf = fields.get(19);
            String cityconf = fields.get(20);
            String regionconf = fields.get(21);
            String postalconf = fields.get(22);
            String error = fields.get(23);
        }

        in.close();
    }
}

 

private string GetMaxMindOmniData(string IP) {
  System.Uri objUrl = new System.Uri("
http://geoip.maxmind.com/e?l=YOUR_LICENSE_KEY&i=" + IP);
  System.Net.WebRequest objWebReq;
  System.Net.WebResponse objResp;
  System.IO.StreamReader sReader;
  string strReturn = string.Empty;

  try
    {
      objWebReq = System.Net.WebRequest.Create(objUrl);
      objResp = objWebReq.GetResponse();

      sReader = new System.IO.StreamReader(objResp.GetResponseStream());
      strReturn = sReader.ReadToEnd();

      sReader.Close();
      objResp.Close();
    }
  catch (Exception ex)
    {
    }
  finally
    {
      objWebReq = null;
    }

  return strReturn;
}

Ruby版本:

#!/usr/bin/env ruby

require 'csv'
require 'net/http'
require 'open-uri'
require 'optparse'
require 'uri'

fields = [:country_code,
          :country_name,
          :region_code,
          :region_name,
          :city_name,
          :latitude,
          :longitude,
          :metro_code,
          :area_code,
          :time_zone,
          :continent_code,
          :postal_code,
          :isp_name,
          :organization_name,
          :domain,
          :as_number,
          :netspeed,
          :user_type,
          :accuracy_radius,
          :country_confidence,
          :city_confidence,
          :region_confidence,
          :postal_confidence,
          :error]

options = { :license => "YOUR_LICENSE_KEY", :ip => "24.24.24.24" }
OptionParser.new { |opts|
  opts.banner = "Usage: omni-geoip-ws.rb [options]"

  opts.on("-l", "--license LICENSE", "MaxMind license key") do |l|
    options[:license] = l
  end

  opts.on("-i", "--ip IPADDRESS", "IP address to look up") do |i|
    options[:ip] = i
  end
}.parse!

uri = URI::HTTP.build(:scheme => 'http',
                      :host   => 'geoip.maxmind.com',
                      :path   => '/e',
                      :query  => URI.encode_www_form(:l => options[:license],
                                                     :i => options[:ip]))

response = Net::HTTP.get_response(uri)

unless response.is_a?(Net::HTTPSuccess)
  abort "Request failed with status #{response.code}"
end

omni = Hash[fields.zip(response.body.encode('utf-8', 'iso-8859-1').parse_csv)]

if omni[:error]
  abort "MaxMind returned an error code for the request: #{omni[:error]}"
else
  puts
  puts "MaxMind Omni data for #{options[:ip]}";
  puts
  omni.each { |key, val| printf "  %-20s  %s\n", key, val }
  puts
end

最后再来个Perl版本吧:

[python] view plain copy print ?
  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. else
  69.     print"\nMaxMind Omni data for $ip_address\n\n"
  70.     for my $field (@fields) { 
  71.         print sprintf("  %-20s  %s\n", $field, $omni{$field} ); 
  72.     } 
  73.     print"\n"
#!/usr/bin/env perl

use strict;
use warnings;

use Encode qw( decode );
use Getopt::Long;
use LWP::UserAgent;
use Text::CSV_XS;
use URI;
use URI::QueryParam;

my @fields = qw(
    country_code
    country_name
    region_code
    region_name
    city_name
    latitude
    longitude
    metro_code
    area_code
    time_zone
    continent_code
    postal_code
    isp_name
    organization_name
    domain
    as_number
    netspeed
    user_type
    accuracy_radius
    country_confidence
    city_confidence
    region_confidence
    postal_confidence
    error
);

my $license_key = 'YOUR_LICENSE_KEY';
my $ip_address  = '24.24.24.24';

GetOptions(
    'license:s' => \$license_key,
    'ip:s'      => \$ip_address,
);

my $uri = URI->new('http://geoip.maxmind.com/e');
$uri->query_param( l => $license_key );
$uri->query_param( i => $ip_address );

my $ua = LWP::UserAgent->new( timeout => 5 );
my $response = $ua->get($uri);

die 'Request failed with status ' . $response->code()
    unless $response->is_success();

my $csv = Text::CSV_XS->new( { binary => 1 } );
$csv->parse( decode( 'ISO-8859-1', $response->content() ) );

my %omni;
@omni{@fields} = $csv->fields();

binmode STDOUT, ':encoding(UTF-8)';

if ( defined $omni{error} && length $omni{error} ) {
    die "MaxMind returned an error code for the request: $omni{error}\n";
}
else {
    print "\nMaxMind Omni data for $ip_address\n\n";
    for my $field (@fields) {
        print sprintf( "  %-20s  %s\n", $field, $omni{$field} );
    }
    print "\n";
}


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

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

  1. publicclass GeoBusiness { 
  2.     /**
  3.      * @param args
  4.      * @throws IOException
  5.      */ 
  6.     publicstatic 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.     publicstatic 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.     } 
public class GeoBusiness {
	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		System.out.println(getLocationByIp("220.181.111.147").getCity());
		System.out.println(getLocationByIp("220.181.111.147").getCountryName());
	}

	public static Location getLocationByIp(String ipaddr) throws IOException {
		String sep = System.getProperty("file.separator");
		String dir = Play.configuration.getProperty("geoip.datdir");
		String dbfile = dir + sep + "GeoLiteCity.dat";
		LookupService cl = new LookupService(dbfile,
				LookupService.GEOIP_MEMORY_CACHE);
		Location location = cl.getLocation(ipaddr);

		cl.close();
		return location;
	}
}


更详细的功能比如获取省,经纬度可以参考我最前面给出的网址。

  • 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、付费专栏及课程。

余额充值