在某些场景下,可能需要用到根据ip地址获取ip所对应的城市名。
貌似腾讯、百度等开放接口已经失效或者免费服务接口关闭等原因,很多免费接口已不能使用,本文暂时给出如下三种方法来做:
- 使用淘宝的开放接口
- 使用新浪的开放接口
- 使用MaxMind提供的GeoIp离线包
接下来,我们就一起来看看这三种方法的具体使用方法,所有的示例采用Java代码完成。
淘宝和新浪开放的api都返回JSON格式的数据。
完成淘宝和新浪api接口调用,本文使用如下的依赖包:
- <properties>
- <http-client.version>4.5.2</http-client.version>
- <fast-json.version>1.2.23</fast-json.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpclient</artifactId>
- <version>${http-client.version}</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>${fast-json.version}</version>
- </dependency>
- </dependencies>
使用淘宝的开放接口
接口地址
淘宝的开放接口URL格式为:
http://ip.taobao.com/service/getIpInfo.php?ip=<IP_ADDRESS>
示例:
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=<IP_ADDRESS>
示例:
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
解压缩之后,可以看到解压后的GeoLiteCity.dat文件。
准备依赖包
- <properties>
- <geoip-api.version>1.2.15</geoip-api.version>
- </properties>
- <dependencies>
- <dependency>
- <groupId>com.maxmind.geoip</groupId>
- <artifactId>geoip-api</artifactId>
- <version>${geoip-api.version}</version>
- </dependency>
- </dependencies>
代码示例
- 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地址对应的城市名称,也请留言,一起分享,谢谢。