IPアドレスから地域を特定する - MaxMind DB Reader, GeoIP2 Java API
MaxMind が提供している無償の IP Geolocation DB である GeoLite と Java 用ライブラリを使って IP アドレスから国や都市を特定してみました。
今回は Java 用ライブラリの下記 2種類を試してみる事にします。
どちらも Maven のセントラルリポジトリから入手でき、MaxMind DB Reader は low-level API、GeoIP2 は high-level API な印象となっています。
また、GeoLite には下記 2種類があり、上記ライブラリで使えるのは GeoLite2 の方です。
今回のソースは http://github.com/fits/try_samples/tree/master/blog/20141004/
MaxMind DB Reader
MaxMind DB Reader を使って IP アドレスから地域を取得するコードを Groovy で実装しました。
GeoLite2 の DB ファイルを引数にして com.maxmind.db.Reader
をインスタンス化し、get
メソッドへ IP アドレスから作成した InetAddress
を渡すだけです。
Reader の get
メソッドで取得する地域情報は JSONデータ (com.fasterxml.jackson.databind.JsonNode
) となります。
get_location_dbreader.groovy
@Grab('com.maxmind.db:maxmind-db:1.0.0') import com.maxmind.db.Reader if (args.length < 2) { println '<maxmind db file> <ip>' return } def reader = new Reader(new File(args[0])) println reader.get(InetAddress.getByName(args[1])) reader.close()
実行には、GeoLite2 Free Downloadable Databases から GeoLite2 City と GeoLite2 Country のどちらかの MaxMind DB をダウンロード・解凍し .mmdb ファイルを取得しておきます。
今回は GeoLite2 City の MaxMind DB GeoLite2-City.mmdb
を使って、IP アドレス 1.21.127.254
の地域判定を行ってみました。 (下記の出力結果は加工しています)
実行結果1
> groovy get_location_dbreader.groovy GeoLite2-City.mmdb 1.21.127.254 { "city":{"geoname_id":1850147,"names":{・・・,"en":"Tokyo",・・・,"ja":"東京",・・・}}, "continent":{"code":"AS","geoname_id":6255147,"names":{・・・,"en":"Asia",・・・,"ja":"アジア",・・・}}, "country":{"geoname_id":1861060,"iso_code":"JP","names":{・・・,"en":"Japan",・・・"ja":"日本",・・・}}, "location":{"latitude":35.685,"longitude":139.7514,"time_zone":"Asia/Tokyo"}, "registered_country":{"geoname_id":1861060,"iso_code":"JP","names":{"de":"Japan","en":"Japan",・・・,"ja":"日本",・・・}}, "subdivisions":[{"geoname_id":1850144,"iso_code":"13","names":{・・・,"ja":"東京都"}}] }
結果は、東京だと判定されました。
なお、上記では省略してますが、言語毎の名称は en と ja だけではなく de・es・fr・pt-BR・ru・zh-CN なども設定されています。
次に、別の IP アドレス 223.255.254.1
を試してみます。
実行結果2
> groovy get_location_dbreader.groovy GeoLite2-City.mmdb 223.255.254.1 { "continent":{"code":"AS","geoname_id":6255147,"names":{・・・,"en":"Asia",・・・}}, "country":{"geoname_id":1880251,"iso_code":"SG","names":{・・・,"en":"Singapore",・・・,"ja":"シンガポール",・・・}}, "location":{"latitude":1.3667,"longitude":103.8,"time_zone":"Asia/Singapore"}, "registered_country":{"geoname_id":1880251,"iso_code":"SG","names":{・・・,"en":"Singapore",・・・,"ja":"シンガポール",・・・}} }
今度の結果には city 情報を含んでおらず、特定できなかったようです。
ちなみに、地域が全く特定できなかった場合の get
メソッドの結果は null
となるようです。 (プライベート IP などを使えば確認できます)
GeoIP2 Java API
次に GeoIP2 の方を使った場合の Groovy スクリプトは下記のようになります。
使用する .mmdb によって DatabaseReader
の使用可能なメソッドが異なるようなので注意が必要です。
今回のように GeoLite2-City.mmdb
ファイルを使う場合、city
メソッドが使えますが、country
メソッドは使えないようです。 (UnsupportedOperationException
が発生しました)
get_location_geoip2.groovy
@Grab('com.maxmind.geoip2:geoip2:2.0.0') import com.maxmind.geoip2.DatabaseReader if (args.length < 2) { println '<maxmind db file> <ip>' return } def reader = new DatabaseReader.Builder(new File(args[0])).build() def res = reader.city(InetAddress.getByName(args[1])) println res.country println res.city reader.close()
実行結果は下記の通りです。
実行結果1
> groovy get_location_geoip2.groovy GeoLite2-City.mmdb 1.21.127.254 Japan Tokyo
実行結果2
> groovy get_location_geoip2.groovy GeoLite2-City.mmdb 223.255.254.1 Singapore