【Java】通过ip地址获取详细地域信息(不通过API使用本地库)

MaxMind GeoIP2

服务能识别互联网用户的地点位置与其他特征,应用广泛,包括个性化定制内容、诈欺检测、广告定向、网站流量分析、执行规定、地理目标定位、地理围栏定位 (geo-fencing)以及数字版权管理。目前使用 GeoIP 更多是配合Nginx或Apache服务器进行日志分析获取网站访问量地域分布状况。

GeoIP 分为商业版和免费版,免费版比商业版精度差了许多,经测试对于城市定位确实有差距,能否接受看你的精度要求!(老板说免费的可以了,哈哈)

下载GeoIP2的库,这个库是经常更新的,如果数据要求很高的,需要经常更新(我们不高,预计一年一次)

官网下载地址https://dev.maxmind.com/geoip/geoip2/geolite2/ 

 

但是好像网站不太稳定,我这边3个都下载好了,可【点击下载】

 

关于Java如何使用

不用担心,已经有开源库,maven下载一个

<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.12.0</version>
</dependency>
没有maven,怎么办?不怕,我上传了,可【点击下载】

 

使用用到的工具类

import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.AsnResponse;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.model.CountryResponse;
import com.maxmind.geoip2.record.City;
import com.maxmind.geoip2.record.Country;
import com.maxmind.geoip2.record.Location;
import com.maxmind.geoip2.record.Postal;
import com.maxmind.geoip2.record.Subdivision;
 

调用ASN

这个是获取自治系统编号的

public static void testAsn(String testIp) throws Exception {
//GeoIP2数据库文件,把数据库文件直接放d盘下(可以随意喜欢的位置)
File database = new File("D:/GeoLite2-ASN.mmdb");

// 创建 DatabaseReader对象
DatabaseReader reader = new DatabaseReader.Builder(database).build();

InetAddress ipAddress = InetAddress.getByName(testIp);

AsnResponse response = reader.asn(ipAddress);

System.out.println(response.getAutonomousSystemOrganization());
System.out.println(response.getAutonomousSystemNumber());

}
 

调用Country

这个是获取Country级别的,数据库文件小很多,速度可以优化很多

public static void testCity(String testIp) throws Exception {
//GeoIP2数据库文件,把数据库文件直接放d盘下(可以随意喜欢的位置)
File database = new File("D:/test/ip/GeoLite2-City.mmdb");

// 创建 DatabaseReader对象
DatabaseReader reader = new DatabaseReader.Builder(database).build();

InetAddress ipAddress = InetAddress.getByName(testIp);

CityResponse response = reader.city(ipAddress);

Country country = response.getCountry();
System.out.println(country.getIsoCode()); // 'US'
System.out.println(country.getName()); // 'United States'
System.out.println(country.getNames().get("zh-CN")); // '美国'

Subdivision subdivision = response.getMostSpecificSubdivision();
System.out.println(subdivision.getName()); // 'Minnesota'
System.out.println(subdivision.getIsoCode()); // 'MN'
System.out.println(subdivision.getNames().get("zh-CN"));

City city = response.getCity();
System.out.println(city.getName()); // 'Minneapolis'
System.out.println(city.getNames().get("zh-CN"));

Postal postal = response.getPostal();
System.out.println(postal.getCode()); // '55455'

Location location = response.getLocation();
System.out.println(location.getLatitude()); // 44.9733
System.out.println(location.getLongitude()); // -93.2323
}
调用City

这个是获取City级别的,文件相对比较大,看情况使用(不用担心,我们就是这样用的,速度还行暂时)

public static void testCity(String testIp) throws Exception {
//GeoIP2-City 数据库文件,把数据库文件直接放d盘下(可以随意喜欢的位置)
File database = new File("D:/test/ip/GeoLite2-City.mmdb");

// 创建 DatabaseReader对象
DatabaseReader reader = new DatabaseReader.Builder(database).build();

InetAddress ipAddress = InetAddress.getByName(testIp);

CityResponse response = reader.city(ipAddress);

Country country = response.getCountry();
System.out.println(country.getIsoCode()); // 'US'
System.out.println(country.getName()); // 'United States'
System.out.println(country.getNames().get("zh-CN")); // '美国'

Subdivision subdivision = response.getMostSpecificSubdivision();
System.out.println(subdivision.getName()); // 'Minnesota'
System.out.println(subdivision.getIsoCode()); // 'MN'
System.out.println(subdivision.getNames().get("zh-CN"));

City city = response.getCity(http://www.my516.com);
System.out.println(city.getName()); // 'Minneapolis'
System.out.println(city.getNames().get("zh-CN"));

Postal postal = response.getPostal();
System.out.println(postal.getCode()); // '55455'

Location location = response.getLocation();
System.out.println(location.getLatitude()); // 44.9733
System.out.println(location.getLongitude()); // -93.2323
}
 

测试模块

public static void main(String[] args) throws Exception {

String testIp="128.101.101.101";

//测试Asn
testAsn(testIp);

//测试国家
testCountry(testIp);

//测试城市
testCity(testIp);

}
 

Ps:如果ip是内网怎么办?不用担心,一定会报错,因为根本不可能找到数据,哈哈

解决方法:把ip先放进去判断是否是内网先再查询,这里我是使用正则表达式,之前发过了,请看【Java】判断IP是否内网(使用正则表达式)


---------------------

posted @ 2019-07-11 00:44  水至清明  阅读(1496)  评论(0编辑  收藏  举报