2019年3月10日日曜日

Perl モジュールの GeoIP2 を使う (on FreeBSD)

 今回は,GeoIP2 を使った話を書こうと思う。

 きっかけは,FreeBSD の ports ツリーから,「Geo::IP」用のエントリーが削除されたことに始まる。 確か「/usr/ports/net/p5-Geo-IP」だったかな? Geo-IP は MaxMind 社のデータベースを使うためのモジュールで,これまで無料で使える精度のあまり高くない「GeoLite」データベースを使うのに利用していた。 しかし,MaxMind 社がデータベースの構造を変えたみたいで,今後は「GeoIP2」を使え,というメッセージが出てきた。 そこで,「GeoIP2」を使うべく,下記の perl モジュールをインストールしてみた。
/usr/ports/net/p5-GeoIP2/

 すると,インストールは簡単にできた。問題は使い方。これがわかるのに意外と手間取ってしまった。

 まず,ports から GeoIP2 をインストールすると,
・GeoIP2
・GeoIP2::Database::Reader
・GeoIP2::Model::City
などがインストールされ,さらに
/usr/local/lib/libmaxminddb.so
がインストールされる。
 さらに,これら以外に
MaxMind::DB::Reader
というモジュールがインストールされる。

 使い方やどのような関数が使えるか,は,「meta::cpan」の中の GeoIP2 のページ
https://metacpan.org/pod/GeoIP2::Database::Reader
と,そこからリンクが張ってある以下のような場所などに書いてある。
https://metacpan.org/pod/GeoIP2::Model::Cityhttps://metacpan.org/pod/GeoIP2::Record::Cityhttps://metacpan.org/pod/GeoIP2::Record::Countryhttps://metacpan.org/pod/GeoIP2::Record::Continenthttps://metacpan.org/pod/GeoIP2::Record::Location

 ここから,以下のようにすれば GeoIP2 を perl のスクリプトで使うことができる。

(1) スクリプトの中で,GeoIP2 の使用の宣言を行う
use GeoIP2::Database::Reader;
ここでは読み取りようのモジュールを読み込んでいる。

(2) 必要なデータベースをダウンロードしておく。
https://dev.maxmind.com/geoip/geoip2/geolite2
ここでは,無料の GeoLite2 をダウンロードしてみた。

(3) 読み取り用の変数の定義
my $reader = GeoIP2::Database::Reader->new(
    file    => 'xxxxxx/GeoIP2/GeoLite2-City/GeoLite2-City.mmdb',
    locales => [ 'ja', 'en', ]
    );
ここでは,$reader という変数を用意し,データベースファイルと言語を指定している。

(4) データの取得
if ($remote_address !~ /^192\.168\./) {
    my $record = $reader->city(ip => $remote_address);

    my $Latitude = $record->location()->latitude();
    my $Longitude = $record->location()->longitude();
    my $Country_Code = $record->continent()->name();
    my $Country = Encode::encode('utf8',$record->country()->name());
    my $Region = Encode::encode('utf8',$record->continent()->name());
    my $City = Encode::encode('utf8',$record->city()->name());
}
ここでは,IP アドレスから情報を得ている。 そのために,IP を指定し,その情報を $record 変数に入れている。 そこから,適度な関数を用いて,いろいろな値を読み出している。
 注意点として,ローカル用の IP アドレスだとエラーとなることがある点である。 そのため,最初に if 文でローカル IP を避けている。

 データ構造が変わったため,読み出しの関数も微妙に変わっている。 その情報が得られれば,GeoIP2 を使うのは難しくはない。

 しかし,FreeBSD で GeoIP2 をインストールすると,読み出しルーチンとして PurePerl のものしかインストールされない。 これがとても遅くて,それが Geo-IP からなかなか GeoIP2 に移行できなかった理由だった。 その辺りについては,次のエントリーに書こう。

0 件のコメント: