【Java】通過ip地址獲取詳細地域信息(不通過API使用本地庫)

首先說一下之前使用了的是百度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是否內網(使用正則表達式)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章