打造無刷新體驗的天氣查詢功能:前端下拉選單選城市 → AJAX POST 城市代碼 → PHP 串接中國天氣網 API → 回傳 JSON → 前端動態渲染。完整前後端代碼可直接部署。
中國天氣網公開 API (無需 Key):
https://www.weather.com.cn/data/sk/{city_id}.htmlhttps://www.weather.com.cn/data/city3jdata/china.html (可抓取所有城市代碼)101010100、上海 101020100、廣州 101280101<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>即時天氣查詢</title>
<style>
body { font-family: sans-serif; padding: 20px; }
#weatherInfo { margin-top: 15px; padding: 10px; background: #f0f8ff; border-radius: 4px; min-height: 80px; }
.loading { color: #666; font-style: italic; }
.error { color: #c00; }
</style>
</head>
<body>
<h2>城市天氣即時查詢</h2>
<select id="citySelect">
<option value="">-- 請選擇城市 --</option>
<option value="101010100">北京</option>
<option value="101020100">上海</option>
<option value="101030100">天津</option>
<option value="101040100">重慶</option>
<option value="101280101">廣州</option>
<option value="101210101">杭州</option>
<option value="101200101">武漢</option>
</select>
<div id="weatherInfo">選擇城市後將顯示即時天氣...</div>
<script>
const select = document.getElementById('citySelect');
const infoDiv = document.getElementById('weatherInfo');
select.addEventListener('change', function() {
const cityId = this.value;
if (!cityId) {
infoDiv.innerHTML = '請選擇城市';
return;
}
infoDiv.innerHTML = '<span class="loading">載入中...</span>';
// 使用 Fetch API (現代瀏覽器原生支援)
fetch('weather.php', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: 'cityid=' + encodeURIComponent(cityId)
})
.then(response => response.text()) // PHP 直接輸出 HTML 片段
.then(html => { infoDiv.innerHTML = html; })
.catch(err => { infoDiv.innerHTML = '<span class="error">請求失敗: ' + err + '</span>'; });
});
</script>
</body>
</html>
<?php
header('Content-Type: text/html; charset=utf-8');
header('Cache-Control: no-cache, must-revalidate');
$cityId = isset($_POST['cityid']) ? trim($_POST['cityid']) : '101010100'; // 預設北京
// 驗證城市代碼格式 (9位數字)
if (!preg_match('/^\d{9}$/', $cityId)) {
echo '<span class="error">無效城市代碼</span>';
exit;
}
$apiUrl = "https://www.weather.com.cn/data/sk/{$cityId}.html";
// 使用 cURL 更穩健 (支援超時、錯誤處理)
$ch = curl_init($apiUrl);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5, // 5秒超時
CURLOPT_CONNECTTIMEOUT => 3,
CURLOPT_USERAGENT => 'Mozilla/5.0 (WeatherBot)',
]);
$json = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode !== 200 || !$json) {
echo '<span class="error">氣象服務暫時不可用</span>';
exit;
}
$data = json_decode($json, true);
if (!isset($data['weatherinfo'])) {
echo '<span class="error">資料格式異常</span>';
exit;
}
$w = $data['weatherinfo'];
// 組裝顯示 HTML
echo '<strong>城市:</strong>' . htmlspecialchars($w['city']) . '<br>';
echo '<strong>溫度:</strong>' . htmlspecialchars($w['temp']) . '°C<br>';
echo '<strong>風向:</strong>' . htmlspecialchars($w['WD']) . '<br>';
echo '<strong>風力:</strong>' . htmlspecialchars($w['WS']) . '<br>';
echo '<strong>濕度:</strong>' . htmlspecialchars($w['SD']) . '<br>';
echo '<strong>更新時間:</strong>' . htmlspecialchars($w['time']) . '<br>';
?>
<?php
// get_cities.php
header('Content-Type: application/json; charset=utf-8');
$url = 'https://www.weather.com.cn/data/city3jdata/china.html';
$json = @file_get_contents($url);
if ($json) {
// 原始資料結構較複雜,這裡簡化輸出前端所需格式
// 實際專案建議抓取後快取到本地資料庫/Redis,避免頻繁請求外部 API
echo $json;
} else {
echo '[]';
}
?>
前端用 fetch('get_cities.php') 取得城市陣列,動態填充 <select>。
| 問題 | 解決方案 |
|---|---|
| 外部 API 回應慢/失敗 | PHP 端設定 cURL 超時;前端顯示載入狀態;快取 API 結果 (Redis/File cache 10-30 分鐘) |
| 跨域請求被瀏覽器攔截 | 前端請求自家 PHP (weather.php),由 PHP 代理外部 API,天然解決跨域 |
| 編碼亂碼 | API 回傳 UTF-8,PHP header('Content-Type: ... charset=utf-8'),前端頁面 <meta charset="utf-8"> |
| 城市代碼變更 | 定期同步官方城市列表,或使用高德/百度地圖 API 獲取更準確的城市編碼 |
使用另一個 API:https://www.weather.com.cn/data/zs/{city_id}.html (生活指數) 或 https://m.weather.com.cn/data/{city_id}.html (多日預報),解析 JSON 並前端用圖表/卡片展示。