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();
    }
}

C#版本:

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

#!/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代码:

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;
	}
}

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


你可能感兴趣的:(Java - 通过IP地址获取用户所在地)