■2005-10-08
* [今月のAcme] Acme::Test::Weather
実際には先月のAcme。Acme-Test-Weather。天候をテストの判定条件に利用できるようにするモジュールです。
use Test::Weather; plan tests => 1; isnt_raining();
今の天気が雨の時はテストに失敗します! CAIDA::NetGeoClientというモジュールを通じて、お使いのマシンのIPアドレスから都市名を取得し、wunderground.comで天候を調べるという仕組みです。ただ、このモジュールのレビューアが述べているように、依存モジュールであるCAIDA::NetGeoClientはCPANからは手に入りません。実際にはSee Alsoにあるサイトから手に入るのですが、何年もメンテナンスがされていないとあります。Geo::IPを使って書き直してくれとレビューアもいっています。ここではCAIDA::NetGeoClientをGeo::IPのラッパとして書き直してみましょう。
package CAIDA::NetGeoClient; use Geo::IP; use Geography::States; sub new { my $gi = Geo::IP->open(GEOIP_CITY_EDITION_REV1); bless { _gi => $gi }, shift; } sub getRecord { my $self = shift; my $ip = shift; my $record = $self->{_gi}->record_by_addr($ip); return { COUNTRY => $record->country_code, CITY => $record->city, STATE => Geography::States ->new('USA') ->state($record->region), }; }
たぶん動くんじゃないかと思いますが、都市名を取得するにはMaxMindの有償データが必要なため、試していません。残念でした。
これで話が終わるとなんですので、hostip.infoを利用して書き直した版をご用意しました。これでAcme::Test::Weatherを試すことができます(運良く都市情報が取得できれば)。
package CAIDA::NetGeoClient; use WWW::HostipInfo; use Geography::States; sub new { my $hostip = new WWW::HostipInfo; bless { _hostip => $hostip }, shift; } sub getRecord { my $self = shift; my $ip = shift; my $record = $self->{_hostip}->get_info($ip); return { COUNTRY => $record->country_code, CITY => $record->city, STATE => ($record->region ? Geography::States->new('USA') ->state(uc($record->region)) : ''), }; }
念のため言っておきますと、テスト上のマシンにglobalなIPアドレスが振られていないと使えません。ここで登場するWWW::HostipInfoについては次の項目にて。
* [Perl][メモ] hostip.infoを利用する
hostip.infoは、IPアドレスから国名と都市名(および経度、緯度)が取得できる(コミュニティベースの)サイトです。意外なことにCPANにこのAPIを利用するモジュールが無かったので書いてみました→CPANにアップ。
use WWW::HostipInfo; my $hostip = new WWW::HostipInfo; my $ip = 'xxx.xxx.xxx.xxx'; my $info = $hostip->get_info($ip); my $country = $info->country_name; my $city = $info->city; my $region = $info->region; # USAの州とか
こんな感じで利用できます。
* [メモ] IPアドレスデータベースの利用
上記のhostip.infoには、月に一度更新されるMySQL用のダンプデータが公開されています(利用する際はhostip.infoに負荷をかけないために"Downloading the Source"の項目を読みましょう)。MySQL 4.0に入れようとしたらsystaxエラーになったので、下記のコマンドで修正して導入。
perl -pe's/\) ENGINE.*/\) ENGINE=MyISAM CHARACTER SET latin1;/' hostip_current.sql > modified_hostip.sql
10/8に落とした時点でダンプデータが300Mほどあり、MySQLに入れると400Mほどスペースをとりました。データ上は、日本の都市は72ありました(typoっぽいのや東京を指しているらしいEdo, Tokioなども含む)。 216.177.121.11の都市名を調べるなら
SELECT name FROM cityByCountry JOIN ip4_216 AS i USING(city) WHERE i.b=177 AND i.c=121
とか。
WWW::HostipInfoの件ですが、ここ一週間くらい、www.hostip.infoではどうもうまくいってないようです。で、WWW::HostipInfoもwww.hostip.infoをhttp://66.102.124.100.ip.anet.comに書換えて、利用してます。
あー、そうなんですよねえ。どうしようかなあ。一時的に修正してCPANにあげようかしら?