2014年12月6日土曜日

GeoIP を使い、IP アドレスから国や場所の情報を Python3 で取得

GeoIP を使い、IP アドレスから国や場所の情報を Python3 で取得する方法を調べてみました。

http://fishrimper.blogspot.jp/2014/11/geoip-ip.html ではコマンドラインで取得する方法でしたが、今回は Python3 です。

環境:
Ubuntu 14.04 (Trusty Tahr) Server

パッケージをインストール

$ sudo apt-get install python3-geoip
$ sudo apt-get install geoip-database-contrib
データベースファイルを更新
$ sudo geoip-database-contrib_update

python3-geoip パッケージには example が含まれていませんが、 python2.7 版の python-geoip パッケージや https://pypi.python.org/pypi/GeoIP/ からダウンロードできるソースコードには example が含まれているのでそちらもあわせて参照して下さい。

データベースファイルの場所を確認

$ ls -l /usr/share/GeoIP/
total 47120
-rw-r--r-- 1 root root  3756721 Dec  1 22:40 GeoIPASNum.dat
-rw-r--r-- 1 root root  4398436 Dec  1 22:40 GeoIPASNumv6.dat
lrwxrwxrwx 1 root root       31 Dec  6 17:28 GeoIPCity.dat -> /etc/alternatives/GeoIPCity.dat
-rw-r--r-- 1 root root   748606 Dec  3 06:43 GeoIP.dat
-rw-r--r-- 1 root root  1361009 Dec  3 06:43 GeoIPv6.dat
-rw-r--r-- 1 root root 18678957 Dec  3 06:57 GeoLiteCity.dat
-rw-r--r-- 1 root root 19295330 Dec  3 06:37 GeoLiteCityv6.dat

GeoIP モジュールでは必要に応じてこれらのファイルを直接オープンして使います。

GeoIP.dat から位置情報を取得

GeoIP インスタンス作成
$ python3
>>> import GeoIP
>>> gi = GeoIP.new(GeoIP.GEOIP_MEMORY_CACHE)

GeoIP.GEOIP_MEMORY_CACHE を指定しましたが、GeoIP.GEOIP_STANDARD とか他にもいろいろあり、メモリをより多く使うが高速だったり、ファイルから読み出すのでメモリをそれほど使わないが低速だったりそれぞれ長所、短所があるようです。 詳しくは https://github.com/maxmind/geoip-api-c に書かれてます。

上では GeoIP.new() でインスタンスを作成しましたが、この場合はデフォルトで /usr/share/GeoIP/GeoIP.dat を使うようです。

GeoIP.open() で明示的にデータベースファイルを指定することもできるようです。

>>> gi = GeoIP.open('/usr/share/GeoIP/GeoIP.dat', GeoIP.GEOIP_MEMORY_CACHE)

データベースのエディションを確認

>>> gi.database_edition
'GeoIP Country Edition'

データベースの情報を確認

>>> gi.database_info
'GEO-106FREE 20141202 Build 1 Copyright (c) 2014 MaxMind Inc All Rights Reserved'

IP アドレスから国コード取得

>>> gi.country_code_by_addr('173.194.38.66')
'US'

ホスト名から国コード取得

>>> gi.country_code_by_name('google.com')
'US'

IP アドレスから国名取得

>>> gi.country_name_by_addr('173.194.38.66')
'United States'

ホスト名から国名取得

>>> gi.country_name_by_name('google.com')
'United States'

GeoIPCity.dat から位置情報を取得

GeoIP インスタンス作成
$ python3
>>> import GeoIP
>>> gi = GeoIP.open('/usr/share/GeoIP/GeoIPCity.dat', GeoIP.GEOIP_MEMORY_CACHE)

データベースのエディションを確認

>>> gi.database_edition
'GeoIP City Edition, Rev 1'

データベースの情報を確認

>>> gi.database_info
'GEO-533LITE 20141202 Build 1 Copyright (c) 2014 MaxMind Inc All Rights Reserved'
IP アドレスから位置情報取得
>>> from pprint import pprint
>>> pprint(gi.record_by_addr('173.194.38.66'))
{'area_code': 650,
 'city': 'Mountain View',
 'country_code': 'US',
 'country_code3': 'USA',
 'country_name': 'United States',
 'dma_code': 807,
 'latitude': 37.4192008972168,
 'longitude': -122.05740356445312,
 'metro_code': 807,
 'postal_code': '94043',
 'region': 'CA',
 'region_name': 'California',
 'time_zone': 'America/Los_Angeles'}

GeoIP.dat とは異なり、GeoIPCity.dat の場合は一括で情報を取得するようです。

ホスト名から位置情報取得
>>> pprint(gi.record_by_name('google.com'))
{'area_code': 650,
 'city': 'Mountain View',
 'country_code': 'US',
 'country_code3': 'USA',
 'country_name': 'United States',
 'dma_code': 807,
 'latitude': 37.4192008972168,
 'longitude': -122.05740356445312,
 'metro_code': 807,
 'postal_code': '94043',
 'region': 'CA',
 'region_name': 'California',
 'time_zone': 'America/Los_Angeles'}

データベースの更新

http://fishrimper.blogspot.jp/2014/11/geoip-ip.html と同様に、しばらく経過するとデータベースが古くなり正確な情報を取得できなくなるはずなので、こまめに $ sudo geoip-database-contrib_update を実行すると最新の GeoIP データベースに更新できるようです。


その他

データベースファイルには GeoIPASNum.dat というものもあったのですが、 example が無く使い方がわからなかったので調べてみました。

GeoIP インスタンス作成
$ python3
>>> import GeoIP
>>> gi = GeoIP.open('/usr/share/GeoIP/GeoIPASNum.dat', GeoIP.GEOIP_MEMORY_CACHE)

データベースのエディションを確認

>>> gi.database_edition
'GeoIP ASNum Edition'

データベースの情報を確認

>>> gi.database_info
'GEO-117 20141201 Build 1 Copyright (c) 2014 MaxMind Inc All Rights Reserved'
ヘルプを確認
>>> help(gi)
Help on GeoIP object:

class GeoIP(builtins.object)
 |  GeoIP database object
 |
 |  Methods defined here:
... snip ...

gi インスタンスが持っているメソッドなどの情報をヘルプで確認できます。

ヘルプに出てくるメソッドのうち、使用するデータベースによって使えるものが限られるようですが、 GeoIPASNum.dat の場合は以下が使えました。

IP アドレスから AS 番号取得
>>> gi.name_by_addr('173.194.38.66')
'AS15169 Google Inc.'

AS 番号を取得できるようです。

ホスト名から AS 番号取得
>>> gi.name_by_name('google.com')
'AS15169 Google Inc.'

0 件のコメント:

コメントを投稿