在 Web 開發中,根據使用者的 IP 位址自動偵測所在城市,並將中文城市名轉換為拼音格式,是實現個性化服務(如天氣預報、本地化內容推薦)的常見需求。本文將詳細介紹如何使用 PHP 結合新浪 IP 查詢 API,實現從 IP 獲取城市並轉換為拼音的完整流程。
HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR,最後回退到 REMOTE_ADDR。https://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=,取得 JSON 格式的地理位置資訊。pinyin.php 類別庫,將城市中文名轉為拼音,並針對多音字城市(如重慶、廈門、長沙等)進行人工修正。<?php
include './pinyin.php';
// 1. 獲取客戶端真實 IP
function getIp() {
$onlineip = '';
if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
$onlineip = getenv('HTTP_CLIENT_IP');
} elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
$onlineip = getenv('HTTP_X_FORWARDED_FOR');
} elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
$onlineip = getenv('REMOTE_ADDR');
} elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
$onlineip = $_SERVER['REMOTE_ADDR'];
}
return $onlineip;
}
// 2. 呼叫新浪 API 獲取城市資訊
function getLocation($ip) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "https://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=" . $ip);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
$str = curl_exec($curl);
curl_close($curl);
return $str;
}
// 主流程
$currentIP = getIp();
$getLocation = getLocation($currentIP);
$currentInfo = json_decode($getLocation, true);
// 3. 處理無效 IP 情況
if ($currentInfo['ret'] == '-1') {
$currentInfo['city'] = 'unknown';
}
$currentCityName = $currentInfo['city'];
$pin = new Pinyin(); // 假設 pinyin.php 定義了 Pinyin 類
$currentCityEName = $pin->Pinyin($currentCityName, 'UTF8');
// 4. 多音字城市修正對照表
$polyphoneMap = [
'zhongqing' => 'chongqing', // 重慶
'shenfang' => 'shifang', // 什邡
'chengdou' => 'chengdu', // 成都
'yueshan' => 'leshan', // 樂山
'junxian' => 'xunxian', // 浚縣
'shamen' => 'xiamen', // 廈門
'zhangsha' => 'changsha', // 長沙
'weili' => 'yuli', // 玉里
'zhaoyang' => 'chaoyang', // 朝陽
'danxian' => 'shanxian', // 單縣
];
$currentCityEName = $polyphoneMap[$currentCityEName] ?? $currentCityEName;
// 5. 跳轉至業務頁面(示例導向 jb51.net)
header("Location: https://www.jb51.net?city=" . urlencode($currentCityEName));
exit;
真實客戶端 IP 可能被代理伺服器隱藏,HTTP_X_FORWARDED_FOR 可能包含多個 IP(格式為 client, proxy1, proxy2),實際專案中建議取第一個非私有 IP,或使用成熟的庫(如 symfony/http-foundation 的 Request::getClientIp())。
API 回傳 JSON 範例:
{
"ret": 1,
"start": "123.123.123.0",
"end": "123.123.123.255",
"country": "中國",
"province": "廣東",
"city": "深圳",
"district": "",
"isp": "電信",
"type": "",
"desc": ""
}
需注意 ret 為 -1 表示查詢失敗,需做容錯處理。
大多數拼音類庫基於字典映射,無法完全覆蓋地名多音字。建議維護一份城市級多音字修正表,並定期同步最新行政區劃資料。若專案對準確度要求極高,可考慮接入商業級地理編碼服務(如高德、騰訊位置服務)。
本文示範了從 IP 獲取城市並轉拼音的經典實作路徑。隨著舊版 API 逐漸淘汰,建議新專案直接採用支援 HTTPS、提供 SDK 的現代地理位置服務,並將多音字修正表作為配置檔獨立維護,以提升系統的可維護性與擴展性。