【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是否内网(使用正则表达式)
---------------------