首先說一下之前使用了的是百度api和阿里免費的api查詢,但是大老闆說萬一人家接口哪一天有限制訪問怎麼辦,或者網絡通訊哪一天不好怎麼辦,或者人家其實有收集我們的數據怎麼辦?那這裏就必須有自己的庫了,然後找了很久很久,大老闆發現一個MaxMind GeoIP2,免費的還有維護今天是2019年6月(最新數據是2019年2月更新的),所以選擇了這個....接下來正題開始
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();
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是否內網(使用正則表達式)