根据ip地址获取城市名的几种方法

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

在某些场景下,可能需要用到根据ip地址获取ip所对应的城市名。

根据ip地址获取城市名的几种方法_第1张图片

貌似腾讯、百度等开放接口已经失效或者免费服务接口关闭等原因,很多免费接口已不能使用,本文暂时给出如下三种方法来做:

  • 使用淘宝的开放接口
  • 使用新浪的开放接口
  • 使用MaxMind提供的GeoIp离线包

接下来,我们就一起来看看这三种方法的具体使用方法,所有的示例采用Java代码完成。

淘宝和新浪开放的api都返回JSON格式的数据。

完成淘宝和新浪api接口调用,本文使用如下的依赖包:

	
		4.5.2
		1.2.23
	
	
		
			org.apache.httpcomponents
			httpclient
			${http-client.version}
		
		
			com.alibaba
			fastjson
			${fast-json.version}
		
	

使用淘宝的开放接口

接口地址

淘宝的开放接口URL格式为:

http://ip.taobao.com/service/getIpInfo.php?ip=

示例:

http://ip.taobao.com/service/getIpInfo.php?ip=117.136.42.86

返回结果

{
	"data":{
		"region":"北京市",
		"area_id":"100000",
		"country_id":"CN",
		"isp":"移动",
		"region_id":"110000",
		"ip":"117.136.42.86",
		"country":"中国",
		"city":"北京市",
		"isp_id":"100025",
		"city_id":"110100",
		"area":"华北",
		"county":"",
		"county_id":"-1"
	},
	"code":0
}

代码示例

	public String getCityNameByTaoBaoAPI(String ip) {
		String url = "http://ip.taobao.com/service/getIpInfo.php?ip=" + ip;
		String cityName = "";
		HttpClient client = HttpClientBuilder.create().build();
		HttpGet request = new HttpGet(url);
		try {
			HttpResponse response = client.execute(request);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				String strResult = EntityUtils.toString(response.getEntity());
				try {
					JSONObject jsonResult = JSON.parseObject(strResult);
					System.out.println(JSON.toJSONString(jsonResult, true));
					JSONObject dataJson = jsonResult.getJSONObject("data");
					cityName = dataJson.getString("city");
					System.out.println(JSON.toJSONString(jsonResult, true));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return cityName;
	}

使用新浪的开放

接口地址

新浪的开放接口URL格式为:

http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=

示例:

http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=117.136.42.60

返回结果

{
	"ret":1,
	"desc":"",
	"start":-1,
	"isp":"",
	"province":"北京",
	"type":"",
	"district":"",
	"end":-1,
	"city":"北京",
	"country":"中国"
}

代码示例

public static String getCityNameBySinaAPI(String ip) {
		String url = "http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip="
				+ ip;
		String cityName = "";
		HttpClient client = HttpClientBuilder.create().build();
		HttpGet request = new HttpGet(url);
		try {
			HttpResponse response = client.execute(request);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == HttpStatus.SC_OK) {
				String strResult = EntityUtils.toString(response.getEntity());
				try {
					JSONObject jsonResult = JSON.parseObject(strResult);
					cityName = jsonResult.getString("city");
					System.out.println(JSON.toJSONString(jsonResult, true));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return cityName;
	}

使用GeoLiteCity离线包

下载离线包

下载GeoLiteCity离线包,并解压到本地。

下载地址http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz

163544_dg4q_2911530.png

解压缩之后,可以看到解压后的GeoLiteCity.dat文件。

准备依赖包

	
		1.2.15
	
	
		
			com.maxmind.geoip
			geoip-api
			${geoip-api.version}
		
	

代码示例

import java.io.IOException;
import java.net.InetAddress;

import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;

public class GeoLiteCityExample {

	public static final String GEO_LITE_FILE_LOCATION = "D:\\ips\\GeoLiteCity.dat";

	public String getCityName(String ip) {
		try {
			LookupService lookupService = new LookupService(
					GEO_LITE_FILE_LOCATION, LookupService.GEOIP_MEMORY_CACHE);
			Location location = lookupService.getLocation(ip);
			if (location != null) {
				return location.city;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}

	public String getCityName(InetAddress inetAddress) {
		try {
			LookupService lookupService = new LookupService(
					GEO_LITE_FILE_LOCATION, LookupService.GEOIP_MEMORY_CACHE);
			Location location = lookupService.getLocation(inetAddress);
			if (location != null) {
				return location.city;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "";
	}
}

测试代码如下:

import java.net.InetAddress;
import java.net.UnknownHostException;

public class Main {
	public static void main(String[] args) {
		GeoLiteCityExample example = new GeoLiteCityExample();
		String ip = "223.95.66.34";
		String cityName = example.getCityName(ip);
		// Hangzhou
		System.out.println(cityName);

		try {
			InetAddress inetAddress = InetAddress.getByName(ip);
			cityName = example.getCityName(inetAddress);
			// Hangzhou
			System.out.println(cityName);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}
	}
}

Location类说明

当拿到com.maxmind.geoip.Location类后,上述示例只是拿了一个属性city来获取城市的名称,其实还能获取更多的属性,如国家,经纬度等。

package com.maxmind.geoip;

public class Location {
	public String countryCode;
	public String countryName;
	public String region;
	public String city;
	public String postalCode;
	public float latitude;
	public float longitude;
	public int dma_code;
	public int area_code;
	public int metro_code;
//省略其它
}

有兴趣的读者,可以尝试一下~~。

至此,使用Maxmind提供的GeoLiteCity离线包,通过ip获取对应城市名的示例也完成了。

小结

本篇博文给出了三个方法用于获取IP对应的城市名称使用淘宝开放API、使用新浪开放API和使用MaxMind提供的离线包

从体验上来看,

新浪接口返回结果还是挺快的。淘宝的接口可能做了连续访问的限制,有时候没有正常返回结果。

使用离线包的方式更加稳定,但是,返回结果是拼音。有些城市拼音一样,如果要进一步确定中文城市名,需要做些额外的操作来保证。

(打算写个多线程程序,将离线包中的中国城市IP信息存放到数据库中去,以后结合缓存加快处理 ~~)

今天就写到这吧

大家如果有其它不错的方式-- 获取IP地址对应的城市名称,也请留言,一起分享,谢谢。

转载于:https://my.oschina.net/wangmengjun/blog/815697

你可能感兴趣的:(根据ip地址获取城市名的几种方法)