MaxMind社のGeoLite2というIPアドレスから国や都市といった位置情報を返すデータベースがあります。
より精度の高いGeoIPは有償ですが、GeoLite2はCreativeCommons(表示・継承)ライセンスで無償配布されています。
またこのデータベースを利用するGeoIP2ライブラリも各種言語版が同社のGitHubから配布されています。Java版のライブラリはこちら。
このGitHubページの説明ではウェブサービス版のクライアントや有償DBの使い方の説明が主ですが、無償版のGeoLite2もこのライブラリを使って問題無く利用出来ます。
GeoLite2の利用にあたってはRDB等のセットアップは不要で、メモリ上にデータを読み込んで利用することが出来るため大変手軽です。精度が低いとはいえざっくり国名を引っ張る程度であれば十分だと思います。ログ解析等の目的で大量のIPアドレスに国情報をつけたいときなどに便利です。
使い方
一般的なMavenプロジェクトを例に使用方法を説明します。
GeoIP2ライブラリをプロジェクトに追加
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>2.2.0</version>
</dependency>
GeoLite2データベースをダウンロードして解凍・プロジェクトに追加
上記ページからGeoLite2 CityまたはGeoLite2 Country databaseの"MaxMind DB binary"版をダウンロード、解凍して下さい。解凍時のサイズは都市情報も含むCity版で35MB程度、国情報だけのCountry版はその十分の一程度です。
データベースファイルの読み込み方法ですが、今回の例ではクラスローダー経由で読み込みます。/src/main/resourceディレクトリ以下にサンプルプログラムのパッケージと同じ階層のディレクトリを作成してデータベースファイルを配備します。
サンプルコード
qiita.comの地理情報を取得してみます。この例では都市名まで取得出来ていますが、実際は仮に都市名が取得出来たらラッキー程度に考えておいた方が無難かもしれません。
public class GeoLiteSample {
public static void main(String[] args) throws Exception {
// クラスパスからデータベースファイルを読み込むInputStreamを作成
InputStream in = GeoLiteSample.class.getResourceAsStream("GeoLite2-City.mmdb");
// DatabaseReader.Builderクラスを用いてInputStreamからDatabaseReaderオブジェクトを作成
DatabaseReader cityDB = new DatabaseReader.Builder(in).build();
// 都市情報を問い合わせ。引数はInetAddressオブジェクトです
CityResponse res = cityDB.city(InetAddress.getByName("www.qiita.com"));
// 大陸名を表示 -> Asia
System.out.println(res.getContinent().getName());
// 国名を表示 -> Japan
System.out.println(res.getCountry().getName());
// 地域名を表示 -> Tōkyō (東京都)
// 日本の場合LeastSpecificSubdivisionもMostSpecificSubdivisionも県名
System.out.println(res.getLeastSpecificSubdivision().getName());
System.out.println(res.getMostSpecificSubdivision().getName());
// 都市名を表示 -> Tokyo
System.out.println(res.getCity().getName());
// 各地域情報からは国コードや言語別の表示名を取得出来ます
// 国コード -> JP
System.out.println(res.getCountry().getIsoCode());
// 日本語での地域名 -> 東京都
System.out.println(res.getLeastSpecificSubdivision().getNames().get("ja"));
// 緯度・経度・タイムゾーン -> [latitude=35.685, longitude=139.7514, timeZone=Asia/Tokyo]
System.out.println(res.getLocation());
}
}