關於把 IP 地址轉換為地理位置可以使用網絡上很多的 API,好處就是不用在本地存儲一個 IP 數據庫,而且一般網絡上的 IP 庫會自動更新,不利的地方就是太依賴於網絡,性能表現也可能會弱些。比如像下面的 API:
http://api.hostip.info/get_html.php?ip=58.63.236.31
http://api.hostip.info/flag.php?ip=58.63.236.31
這里介紹 PHP 如何使用 GeoLiteCity.dat 庫把 IP 轉換為地理位置,GeoLiteCity.dat 可以在http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz 下,解壓出 GeoLiteCity.dat,即可,我們可以手動去更新新的 IP 庫。
下面 PHP 解析 IP 的過程參考自 WordPress 插件 Visitor Maps and Who's Online 的實現。可以找到該插件的兩個文件 include-whos-online-geoip.php 和 visitor-maps.php 告訴了我們怎么做。你可以點擊這里的鏈接下載到這兩個文件,我這里把 include-whos-online-geoip.php 改名為 geoipcity.inc.php,然后參考 visitor-maps.php 中的 get_location_info($user_ip) 函數,那么我們可以寫出自己的解析 IP 地址的程序 resolve_ip.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
<?php
require_once("geoipcity.inc.php");
//ini_set("memory_limit","96M");
//最簡單的函數只要這一個
function get_ip_record($user_ip) {
global $path_visitor_maps;
//假定 GeoLiteCity.data 放在與此文件同一目錄下
$gi = geoip_open_VMWO('GeoLiteCity.dat', VMWO_GEOIP_STANDARD);
$record = geoip_record_by_addr_VMWO($gi, "$user_ip");
geoip_close_VMWO($gi);
//你可以直接使用上面取出的 $record 數據
return $record;
}
function get_location_info($user_ip) {
$record = get_ip_record($user_ip);
//或者使用下面加工后的 $location_info
global $GEOIP_REGION_NAME;
$location_info = array(); // Create Result Array
$location_info['city_name'] = (isset($record->city)) ? $record->city : ''; //城市
$location_info['state_name'] = (isset($record->country_code) && isset($record->region)) //州名
? $GEOIP_REGION_NAME[$record->country_code][$record->region] : '';
$location_info['state_code'] = (isset($record->region)) ? strtoupper($record->region) : ''; //州代號
$location_info['country_name'] = (isset($record->country_name)) ? $record->country_name : '--'; //國家名
$location_info['country_code'] = (isset($record->country_code)) ? strtoupper($record->country_code) : '--'; //國家代號
$location_info['latitude'] = (isset($record->latitude)) ? $record->latitude : '0'; //維度
$location_info['longitude'] = (isset($record->longitude)) ? $record->longitude : '0'; //經度
//php 站點設置了 utf-8 字符集必要時進行轉碼
$charset = 'utf-8';
// this fixes accent characters on UTF-8, only when the blog charset is set to UTF-8
if ( strtolower($charset) == 'utf-8' && function_exists('utf8_encode') ) {
if ($location_info['city_name'] != '' ) {
$location_info['city_name'] = utf8_encode($location_info['city_name']);
}
if ($location_info['state_name'] != '') {
$location_info['state_name'] = utf8_encode($location_info['state_name']);
}
if ($location_info['country_name'] != '') {
$location_info['country_name'] = utf8_encode($location_info['country_name']);
}
}
return $location_info;
}
//查詢一個 IP 測試下
$record = get_ip_record("206.19.49.154");
var_dump($record);
$location = get_location_info("206.19.49.154");
var_dump($location);
?>
|
執行后輸出如下(可以作為系統腳本直接用 php resolve_ip.php 來執行):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
object(geoiprecord_VMWO)#2 (10) {
["country_code"]=>
string(2) "US"
["country_code3"]=>
string(3) "USA"
["country_name"]=>
string(13) "United States"
["region"]=>
string(2) "TX"
["city"]=>
string(10) "Richardson"
["postal_code"]=>
string(5) "75080"
["latitude"]=>
float(32.9722)
["longitude"]=>
float(-96.7376)
["area_code"]=>
int(972)
["dma_code"]=>
float(623)
}
array(7) {
["city_name"]=>
string(10) "Richardson"
["state_name"]=>
string(5) "Texas"
["state_code"]=>
string(2) "TX"
["country_name"]=>
string(13) "United States"
["country_code"]=>
string(2) "US"
["latitude"]=>
float(32.9722)
["longitude"]=>
float(-96.7376)
}
|
只要取你想要的數據就是了,里面還有諸如區號,郵編等數所,GeoLiteCity.dat 是個二進制文件,比普通文本要緊湊省空間。
不知道您有沒有多留一份心,有無瀏覽鏈接:http://geolite.maxmind.com/download/geoip/api/php/,是這樣的:
看到 GeoIp 給我們提供了不少的例子,那么多 sample.php,而實際上前面用到的 geoipcity.inc.php,就是 geopip.inc、geoipcity.inc 和 geoipregionvars.php 三個程序的內容合體。
再往上看:
官方提供的 API 何止 PHP 啊,幾乎能全線滿足您的實際需求了,c、java、perl、python、vb、ruby、tcl 等......,放其他程序里以后也不用愁了。
再進到 http://geolite.maxmind.com/download/geoip/database/ 瞧瞧:
正考慮着呢,不是說 IPv4 快用凈了嗎?IPv6 的數據也正為我們准備着呢?當然,天朝的 IPv9 恐怕永遠不會有的。
本只是把 Visitor Maps and Who's Online 里的解析 IP 的做法抽出來用用,可總能不斷 深入再深入,不知道可喜還是可怕了。