WEBサービスを提供する際、どんなユーザがどこから、どんな端末でアクセスしてきているかを分析する事は、次の戦略を考える上で非常に有効です。それを実現するのがGoogle Analyticsをはじめとする、アクセス解析ツールですが、WEBページの解析に特化していて、WEBアプリやWEBページの機能内で使う事は難しいです。
そこで、今回は、サーバ側で取得したユーザ(クライアント)IPアドレスを元に、各種APIを使用して詳細情報を取得する方法について書いてみます。
インターネットの世界で現状主力として使われているIPアドレスは、国際的な規約によって、各国に範囲毎に配布されています。例えば10.xxx.xxx.xxx〜11.xxx.xxx.xxxの範囲は○○国に割当てと、いう感じ。その範囲が、各国内で企業や団体に順次配分される仕組みである。
このルールや、割当実績情報を集める事で、ある程度の規則性でIPアドレスから、アクセス元の情報を逆引きする事が可能である。とは言っても、世界中の情報を集め、更新していく作業は非常に困難でもある。世界中には、その情報をDB化し、さまざまな形で情報提供する専業の組織があり、有料/無料さまざまなサービスがある。
有料/無料は別にして、IPアドレスからの情報取得は、インターネットを経由したAPIという形で提供される場合がほとんどで、それらを総称してGeo Location APIとか、Geo Locationサービスなどと呼よばれます。
※最近HTML5のAPIとして同名の「Geo Location API」というものが登場しました。こちらは、ユーザが自分の端末のGPSやIPからの地理情報をホスト側に共有するかどうかという共通仕様のもので、似ていますが、厳密には本件と別のものです。
言わずと知れたGoogleがAPI Key不要のAPIとして簡易のGeo Locationを提供しています。
任意のIPに対しては問い合わせができず、アクセスしてきたクラインとの情報のみが取得できますので、リアルタイム処理が前提ですが、使い方も簡単なので、すぐに組み込めます。
// 通常のGoogle APIと違い、「?key=APIkey」の部分は省いてもOK
| API | 取得できる情報 |
|---|---|
| ClientLocation.latitude | 緯度 (例: 35.678) |
| ClientLocation.longitude | 経度 (例: 135.678) |
| ClientLocation.address.city | 都市名 (例: 横浜市) |
| ClientLocation.address.country | 国名 (例: Japan) |
| ClientLocation.address.country_code | ISO 国名コード (例: JP) |
| ClientLocation.address.region | 各国固有地域名 (例: 神奈川県) |
function getClientLocation() {
// Google APIの利用
var ClientLocation = google.loader.ClientLocation;
if (ClientLocation != null) {
// HTML表示の更新
document.getElementById("latitude").innerHTML = ClientLocation.latitude;
document.getElementById("longitude").innerHTML = ClientLocation.longitude;
document.getElementById("country_code").innerHTML = ClientLocation.address.country_code;
document.getElementById("country").innerHTML = ClientLocation.address.country;
document.getElementById("region").innerHTML = ClientLocation.address.region;
document.getElementById("city").innerHTML = ClientLocation.address.city;
} else {
alert("位置情報の取得に失敗しました");
}
}
世界有数のGeoData提供団体で、APIの提供だけではなく、DBそモノも公開しています。
MAXMIND社へのリンクとその使用を明示する事で誰でも無料で使用することができます。
レスポンスに各国の言葉での情報があるのは非常にありがたいですね。
1. JavaScriptを読み込む
2. APIをコールする
function getClientLocation() {
// 国コード(ISO country codes)を取得する
geoip2.country(onSuccess, onError);
var onSuccess = function(geoipResponse) {
alert("アクセス元 国コード:" + geoipResponse.country.iso_code);
};
var onError = function (error) {
alert("Error!");
};
};
// 国コード以外にも様々な情報が取得できます。 // (詳細はレスポンスをご参照下さい。) geoipResponse.country.iso_code // ISO国コード geoipResponse.country.names.ja // 国名(日本語) geoipResponse.city.names.ja // 市区名(日本語)
// jsonレスポンス
{
"city": {
"confidence": 25,
"geoname_id": 54321,
"names": {
"de": "Los Angeles",
"en": "Los Angeles",
"es": "Los Ángeles",
"fr": "Los Angeles",
"ja": "ロサンゼルス市",
"pt-BR": "Los Angeles",
"ru": "Лос-Анджелес",
"zh-CN": "洛杉矶"
}
},
"continent": {
"code": "NA",
"geoname_id": 123456,
"names": {
"de": "Nordamerika",
"en": "North America",
"es": "América del Norte",
"fr": "Amérique du Nord",
"ja": "北アメリカ",
"pt-BR": "América do Norte",
"ru": "Северная Америка",
"zh-CN": "北美洲"
}
},
"country": {
"confidence": 75,
"geoname_id": 6252001,
"iso_code": "US",
"names": {
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"pt-BR": "Estados Unidos",
"ru": "США",
"zh-CN": "美国"
}
},
"location": {
"accuracy_radius": 20,
"latitude": 37.6293,
"longitude": -122.1163,
"metro_code": 807,
"time_zone": "America/Los_Angeles"
},
"postal": {
"code": "90001",
"confidence": 10
},
// レスポンス (続き)
"registered_country": {
"geoname_id": 6252001,
"iso_code": "US",
"names": {
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"pt-BR": "Estados Unidos",
"ru": "США",
"zh-CN": "美国"
}
},
"represented_country": {
"geoname_id": 6252001,
"iso_code": "US",
"names": {
"de": "USA",
"en": "United States",
"es": "Estados Unidos",
"fr": "États-Unis",
"ja": "アメリカ合衆国",
"pt-BR": "Estados Unidos",
"ru": "США",
"zh-CN": "美国"
},
"type": "military"
},
"subdivisions": [{
"confidence": 50,
"geoname_id": 5332921,
"iso_code": "CA",
"names": {
"de": "Kalifornien",
"en": "California",
"es": "California",
"fr": "Californie",
"ja": "カリフォルニア",
"ru": "Калифорния",
"zh-CN": "加州"
}
}
],
"traits": {
"autonomous_system_number": "1239",
"autonomous_system_organization": "Linkem IR WiMax Network",
"domain": "example.com",
"is_anonymous_proxy": true,
"is_satellite_provider": true,
"isp": "Linkem spa",
"ip_address": "1.2.3.4",
"organization": "Linkem IR WiMax Network",
"user_type": "traveler"
},
"maxmind": {
"queries_remaining": 54321
}
}
JavaScript以外にも、.NET(C#), C, Java, Perl, PHP, Python, Apacheから呼び出せるAPIモジュールが用意されています。
また、多くのサードパーティがこのMAXMINDのDBを使用したRESTfullのAPIを提供しています。
こちらは、各種データベースをダウンロードする形で使います。
ですので、インターネットに接続していない/できない環境での組み込みの形に最適です。
1. ダウンロードしたCSVやバイナリをExcelやDBに取り込んでから、SQL等で問い合わせが出来ます。
// MySQLのテーブル定義 例
CREATE DATABASE ip2location;
USE ip2location;
CREATE TABLE 'ip2location_db1'(
'ip_from' INT(10) UNSIGNED,
'ip_to' INT(10) UNSIGNED,
'country_code' CHAR(2),
'country_name' VARCHAR(64),
INDEX 'idx_ip_from' ('ip_from'),
INDEX 'idx_ip_to' ('ip_to'),
INDEX 'idx_ip_from_to' ('ip_from', 'ip_to')
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
// MySQLへのインポート 例 LOAD DATA LOCAL INFILE 'IP2LOCATION-LITE-DB1.CSV' INTO TABLE 'ip2location_db1' FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' IGNORE 1 LINES;
C, PHP, Perl, Ruby, Python, Cocoa Objective-C, Pascal, Apache, Nginx, Node.js, CakePHPのモジュールが用意されています。
こちらは、WEBサービスとAPIが提供されてます。
1. 用意されたPHPのAPIをRESTfulで叩くだけです。
http://api.hostip.info/get_html.php?ip=12.215.42.19 // 結果 Country: UNITED STATES (US) City: Aurora, TX IP: 12.215.42.19
http://api.hostip.info/get_html.php?ip=12.215.42.19&position=true // 結果 Country: UNITED STATES (US) City: Aurora, TX Latitude: 33.0582 Longitude: -97.5159 IP: 12.215.42.19
// フォーム作成例
※IPアドレスを指定しなかった場合、クライアントのIPアドレスについて情報を返す仕様です。
複数のオンライン無料ツールと、DBのダウンロードが可能なサービスです。
DBの容量が結構大きいので、他のDbサービスよりもデータが充実していると思われます。
有料のプランになると、情報もかなり充実しているように見えます。
IPデータのダウンロードと、APIサービスが提供されており、それぞれ無料/有料のプランが用意されています。
簡易的なものであれば、無料のプランで十分対応が出来ると思います。
DB情報の大小や内容に応じて5種類のDBが用意されています。下位の2種類に関しては、無料でダウンロードすることができます。
| IP-country database | 3項目: 無料 ip_start, ip_end, country |
|---|---|
| IP-city database | 5項目: 無料 ip_start, ip_end, country, stateprov, city |
| IP-location database | 9項目: 有料 ip_start, ip_end, country, stateprov, city, latitude, longitude, timezone_offset, timezone_name |
| IP-ISP database | 6項目: 有料 ip_start, ip_end, country, isp_name, connection_type, organization_name |
| Full IP database | 12項目: 有料 ip_start, ip_end, country, stateprov, city, latitude, longitude, timezone_offset, timezone_name, isp_name, connection_type, organization_name |
// Full IP database
CREATE TABLE 'dbip_lookup' (
'addr_type' enum('ipv4','ipv6') NOT NULL,
'ip_start' varbinary(16) NOT NULL,
'ip_end' varbinary(16) NOT NULL,
'country' char(2) NOT NULL,
'stateprov' varchar(80) NOT NULL,
'city' varchar(80) NOT NULL,
'latitude' float NOT NULL,
'longitude' float NOT NULL,
'timezone_offset' float NOT NULL,
'timezone_name' varchar(64) NOT NULL,
'isp_name' varchar(128) NOT NULL,
'connection_type' enum('dialup','isdn','cable','dsl','fttx','wireless') DEFAULT NULL,
'organization_name' varchar(128) NOT NULL,
PRIMARY KEY ('ip_start')
);
1. API Keyを取得する。
上記ページから、必要情報を登録しAPI Keyを取得します。(無料版もあります)
2. 以下の仕様に基づき、RESTfulのリクエストを出すだけです。
http://api.db-ip.com/{methodname}?{parameters}
// 取得した自分のAPI Keyに関する情報取得
http://api.db-ip.com/keyinfo?api_key={api_key}
// 指定したAPIに関する情報が参照できます。
{
"api_key": "my_test_key", // API Key
"queries_per_day": "10000", // 1日当たりのクエリ許可回数
"queries_left": "2863", // 当日のクエリ残回数
"expires": "2015-06-09 16:12:43" // API Keyの有効期限
}
// 指定したIPアドレスに関する情報
http://api.db-ip.com/addrinfo?addr=173.194.67.1&api_key={api_key}
// 無料のAPI Keyの場合
{
"address": "173.194.67.1",
"country": "US",
"stateprov": "California",
"city": "Mountain View",
}
// 有料のAPI Keyの場合
{
"address": "173.194.67.1",
"country": "US",
"stateprov": "California",
"city": "Mountain View",
"latitude": "37.422",
"longitude": "-122.085",
"tz_offset": "-7",
"tz_name": "America/Los_Angeles",
"isp": "Google Inc.",
"ctype": "fttx",
"organization": "Google Inc."
}
IP2Locationのデータを使用したRESTfulのAPIサービスです。
データの正当性として、国レベルで99.5%以上、都市レベルで60%以上を網羅しているそうです。
一般的なRESTfulのAPIなので、下記仕様に従ってURLにリクエストを投げると、xmlやjsonといった指定形式でレスポンスを受け取れます。
IPv4の場合
http://api.ipinfodb.com/v3/{api_precision}/?key={api_key}&ip=74.125.45.100
IPv6の場合
http://api.ipinfodb.com/v3/{api_precision}/?key={api_key}&ip=2001:0200:0102::
| API Precision名 | データ粒度 | タイムゾーン | ドメイン検索 |
|---|---|---|---|
| ip-city | City | Yes | Yes |
| ip-country | Country | No | Yes |
| パラメータ | 必須 | デフォルト値 | 値 |
|---|---|---|---|
| key | Yes | 無料で取得できるAPI Keyを必須で指定 | |
| ip | No | アクセスしてきたクライアントのIPアドレス | IPアドレス |
| format | No | raw | raw, xml, jsonから選択 |
| callback | No | jsonのコールバックを使う場合は指定 |
http://api.ipinfodb.com/v3/ip-city/?key={api_key}&ip=74.125.45.100&format=xml
// xmlレスポンス
OK
74.125.45.100
US
UNITED STATES
CALIFORNIA
MOUNTAIN VIEW
94043
37.406
-122.079
-07:00
http://api.ipinfodb.com/v3/ip-city/?key={api_key}&ip=74.125.45.100&format=json
// jsonレスポンス
{
"statusCode" : "OK",
"statusMessage" : "",
"ipAddress" : "74.125.45.100",
"countryCode" : "US",
"countryName" : "UNITED STATES",
"regionName" : "CALIFORNIA",
"cityName" : "MOUNTAIN VIEW",
"zipCode" : "94043",
"latitude" : "37.406",
"longitude" : "-122.079",
"timeZone" : "-07:00"
}
ドキュメントが充実していて、PHPやASPでのプログラム例などかなり豊富に載っていますので、苦労なく各種言語で利用できると思います。
MAXMINのデータを使用したRESTfulのAPIサービスです。
登録も一切必要なく、1時間に1万回までのリクエストを受け付けてくれる、かなり太っ腹のサービスです。
一般的なRESTfulのAPIなので、下記仕様に従ってURLにリクエストを投げると、xmlやjsonといった指定形式でレスポンスを受け取れます。
http://freegeoip.net/{format}/{ip_or_hostname}
| パラメータ | 必須 | デフォルト値 | 値 |
|---|---|---|---|
| format | Yes | なし | csv, xml, jsonから選択 |
| パラメータ | 必須 | デフォルト値 | 値 |
|---|---|---|---|
| ip | No | アクセスしてきたクライアントのIPアドレス | IPアドレス又は、ドメイン名を指定 |
http://freegeoip.net/json/74.125.45.100
// jsonレスポンス
{
"ip" : "74.125.45.100"
"country_code" : "US"
"country_name" : "United States"
"region_code" : "CA"
"region_name" : "California"
"city" : "Mountain View"
"zipcode" : "94043"
"latitude" : 37.4192
"longitude" : -122.0574
"metro_code" : "807"
"area_code" : "650"
}
http://freegeoip.net/xml/74.125.45.100 // xmlレスポンス74.125.45.100 US United States CA California Mountain View 94043 37.4192 -122.0574 807 650