PHPでGeolite2ライブラリを使って、IPアドレスから地域情報を取得する方法について記載します。
コンソール上でのGeoLite2の実行結果
環境
Windows11 Home
PHP 8.3.8 & composer 2.7.7
手順
①MaxmindからIPのデータベース情報を取得
・Maxmindアカウントの作成(無料ユーザ登録)
・データベース情報のダウンロード
②GeoLite2を使ってIPから地域情報を取得
・DBの保存形式を確認
・Composerを使ってGeolite2をインストール
(インストールがうまくいかない場合)
・GeoLite2を使ってIPアドレスから地域情報を取得
データベース情報を取得
Maxmindの公式ページは次のリンクからジャンプできます。
https://www.maxmind.com/en/geoip-databases
表示すると、自身の地域情報が表示されます。
国名だけでなく、都市名、GPS情報(多分サーバの位置かなと思います)、郵便番号も表示されています。
①Maxmindアカウントの作成
データベース情報をダウンロードするためには、無料のアカウント登録が必要です。
有料アカウントもありますが、精度がよくなるだけであり、ダウンロード制限もないので、私は無料アカウントでで充分です。
ユーザ登録ページ GeoLite2 Sign Up | MaxMind
●ユーザ情報登録ページ
入力項目(全部必須入力のようです)
名前 会社 業界 国
使用目的 不正の検知目的とかウェブの分析といったところでしょうか
メールアドレス 有効なメールアドレスが必要です
電話番号 必須ではありません
Maxmindデータをどのように使用するか プラットフォームやソフトウェア、Web等
データをどのように活用するか 統計資料や不正検知、ウェブの分析等
送られてきたメールを使ってパスワードを設定すればアカウントを作成することができます。
ログインは初期設定で二段階認証になっており、ログインするたびにメールにpinコードが送られてきます。(いいね)
②データベース情報のダウンロード
ログイン後、画面の左にあるメニューバーから
GeoIP2/GeoLite2
を選択するとダウンロード画面が開きます。
圧縮されているので、解凍して実行ファイルと同じフォルダにコピーしておきます。
●ダウンロード画面
ダウンロードできるデータベースは次の通りです。
データベース | 説明 |
GeoLite2 ASN | IPアドレスとASNの対応表(6MB程度) (CVS 6MB程度、MMDB 3MB程度 ) |
GeoLite2 City | IPアドレスと都市名の対応表(145MB程度) (CVS 150MB程度、MMDB 60MB程度 ) |
GeoLite2 Country | IPアドレスと国名の対応表(4MB程度) (CVS 4MB程度、MMDB 3MB程度 ) |
都市名と国名は英語だけでなく、日本語で書かれたものもあり、かなり親切設計でした。
フォーマットの種類は次の2種類で提供されています。
csv形式 他のソフトウェアでDBを利用したい場合、読込が遅い
mmdb形式 mindmax社独自のDB形式、読込が早い
データの中身を確認したり、独自で読込ソフトウェアを作成するのならcsvでダウンロードする必要があります。
今回は、GeoLite2 Cityのcsvとmmdbの両方をダウンロードしました。
GeoLite2を使ってIPから地域情報を取得
取得したDB情報を使って地域情報を取得します。
①DBの保存形式を確認
GeoLite2 City CSV ファイルをダウンロードしたところ、次のファイル等が含まれていました。
ファイル名 | |
GeoLite2-City-Blocks-IPv4.csv | ipv4アドレスとgeoname_idの対応表 等 |
GeoLite2-City-Blocks-IPv6.csv | ipv6アドレスとgeoname_idの対応表 等 |
GeoLite2-City-Locations-ja.csv | geoname_idと、都市名、国名の対応表 等 |
指定されたIPアドレスを一度geoname_idに変換してから、geoname_idを使って都市名を取得するという流れですね。
mmdbファイルはバイナリ化されており、内容を可読化することはできません。
②Composerを使ってGeoLite2をインストール
・GeoLite2のインストールが失敗
次のコマンドでGeoLite2をインストールしたところ、警告が表示されて失敗しました。
c:\{インストールDIR} >composer require geoip2/geoip2
./composer.json has been created
Running composer update geoip2/geoip2
Loading composer repositories with package information
:
- guzzle/guzzle[v3.0.0, ..., v3.9.3] require ext-curl * -> it is missing from your system. Install or enable PHP's curl extension.
- maxmind/web-service-common[v0.0.2, ..., v0.9.0] require ext-curl * -> it is missing from your system. Install or enable PHP's curl extension.
To enable extensions, verify that they are enabled in your .ini files:
- C:\{PHP_HOME}\php.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with `--ignore-platform-req=ext-curl` to temporarily ignore these required extensions.
You can also try re-running composer require with an explicit version constraint, e.g. "composer require geoip2/geoip2:*" to figure out if any version is installable, or "composer require geoip2/geoip2:^2.1" if you know which you need.
Installation failed, deleting ./composer.json.
当環境では、php.ini 内でcurlが使用できなくなっているというエラーが発生しましたので、警告に従って、
C:\{PHP_HOME}\php.ini
を開いて
次のコメントを解除
;extension=curl
↓
extension=curl
としたところ、同じコマンドでインストールが成功しました。
③GeoLite2を使ってIPアドレスから地域情報を取得
composerでGeolite2をインストールしたフォルダで次のPHPプログラムを作成しました。
<?php
require './vendor/autoload.php';
use GeoIp2\Database\Reader;
use GeoIp2\Exception\AddressNotFoundException;
try {
# ダウンロードしたバイナリを指定
$my_reader = new Reader('./GeoLite2-City.mmdb');
# チェックしたいIPアドレスを指定
$ip = "61.120.205.110"; # とりあえず東京都のHPのIPを入力
$res = $my_reader->city($ip);
# IPを表示
var_dump("IPアドレス: $ip");
# 国コード
$isocode = $res->country->isoCode;
var_dump("国コード(isoCode):$isocode");
# 国名
$name = $res->country->name;
var_dump("国名(country name):$name");
# 国名 names['ja']が存在するかをチェックして表示
if (isset($res->country->names['ja'])) {
$name_ja = $res->country->names['ja'];
var_dump("国名(country name ja):$name_ja"); # 国名(日本語)
} else {
echo "日本語の国名情報がありません。";
}
# 都市名(日本語)が存在するかをチェックして表示
if (isset($res->city->names['ja'])) {
$city_ja = $res->city->names['ja'];
var_dump("都市名(city name ja):$city_ja"); # 都市名(日本語)
} else {
echo "日本語の都市名情報がありません。";
}
} catch (AddressNotFoundException $e) {
# 結果が見つからない場合の処理
echo "データベースに結果が見つかりませんでした。";
} catch (Exception $e) {
# その他のエラーをキャッチ
echo "エラーが発生しました: " . $e->getMessage();
}
?>
フォルダ構成は次の通り
c:\{実行フォルダ}
├― vendor (composerによって作成されたフォルダ)
| ├― autoload.php (Geoip ロードファイル)
| : 省略
├― composer.json(composerによって作成された定義ファイル)
├― composer.lock(composerによって作成された定義ファイル)
├― test.php (今回作成したphp実行ファイル)
├― GeoLite2-City.mmdb (ダウンロードしたDBファイル)
├― GeoLite2-City-Blocks-IPv4.csv (ダウンロードしたDBファイル なくても実行可)
├― GeoLite2-City-Locations-ja.csv (ダウンロードしたDBファイル なくても実行可)
実行結果は次の通りです。
C:\{実行フォルダ}>php test.php
string(30) "IPアドレス: 61.120.205.110"
string(24) "国コード(isoCode):JP"
string(26) "国名(country name):Japan"
string(30) "国名(country name ja):日本"
string(30) "都市名(city name ja):東京"
IPアドレスは東京都のHPのものを入力しました。
IPによっては、「●●区」「●●町」まで表示されます。
ちなみに、自身のIPアドレスを入力したところ、正確な都市名が表示されました。
GeoLite2は、ja表記が無い都市名を表示しようとするとExceptionを吐いてくるので、try~catchで囲んでおく必要があります。
最後に
Geolite2を使ってIPアドレスから地域情報を取得することができました。
GoogleAnalize等で利用者の都市名が表示されるのは、こういう仕組みを利用しているのですね。
Maxmind社がどのようにしてIPの地域情報を集めているのかはわかりませんが、これだけの情報を無料で使わせてくれることに感謝です。
GeoIPのライセンスを読むと、「MaxMindはサービスを無料で提供していますが、将来的に有料にする権利を保持します。」等と書かれていたので、無料のうちに使って経験を積んだほうがいいと感じています。