首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

透過 IP 位址呼叫新浪 API 獲取城市名稱並轉換為拼音

     編輯:PHP 綜合知識

前言

在 Web 開發中,根據使用者的 IP 位址自動偵測所在城市,並將中文城市名轉換為拼音格式,是實現個性化服務(如天氣預報、本地化內容推薦)的常見需求。本文將詳細介紹如何使用 PHP 結合新浪 IP 查詢 API,實現從 IP 獲取城市並轉換為拼音的完整流程。

核心功能流程

  1. 獲取客戶端真實 IP:支援多層代理環境,優先讀取 HTTP_CLIENT_IP、HTTP_X_FORWARDED_FOR,最後回退到 REMOTE_ADDR。
  2. 呼叫新浪 IP 查詢 API:使用 cURL 發送請求至 https://int.dpool.sina.com.cn/iplookup/iplookup.php?format=json&ip=,取得 JSON 格式的地理位置資訊。
  3. 中文城市名轉拼音:引入 pinyin.php 類別庫,將城市中文名轉為拼音,並針對多音字城市(如重慶、廈門、長沙等)進行人工修正。
  4. 導向目標頁面:將處理後的拼音城市名作為參數跳轉至業務頁面。

完整程式碼實作

<?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 獲取的優先級判斷

真實客戶端 IP 可能被代理伺服器隱藏,HTTP_X_FORWARDED_FOR 可能包含多個 IP(格式為 client, proxy1, proxy2),實際專案中建議取第一個非私有 IP,或使用成熟的庫(如 symfony/http-foundation 的 Request::getClientIp())。

新浪 API 回傳結構

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 呼叫壓力。
  • 非同步處理:若業務允許,可將 IP 解析放入佇列非同步執行,避免阻塞頁面載入。
  • HTTPS 升級:新浪舊版 API 僅支援 HTTP,生產環境建議遷移至支援 HTTPS 的現代 IP 定位服務。
  • 隱私合規:依據《個人資料保護法》等法規,明確告知使用者收集 IP 位置資訊的目的並取得同意。

結語

本文示範了從 IP 獲取城市並轉拼音的經典實作路徑。隨著舊版 API 逐漸淘汰,建議新專案直接採用支援 HTTPS、提供 SDK 的現代地理位置服務,並將多音字修正表作為配置檔獨立維護,以提升系統的可維護性與擴展性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved