您的位置:首页 > 理论基础 > 计算机网络

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

2016-12-29 00:00 197 查看
在某些场景下,可能需要用到根据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地址对应的城市名称,也请留言,一起分享,谢谢。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java HttpClient JSON API