This commit is contained in:
muzihuaner
2026-03-18 13:48:17 +08:00
parent 7153c6d8da
commit 3b003d344b
2 changed files with 478 additions and 237 deletions

View File

@@ -1,244 +1,73 @@
<?php
$file = 'counter.dat';
$file = 'counter.dat';
// 读取并自增
$counter = (int)@file_get_contents($file);
$counter++;
// 使用 LOCK_EX 防止并发写入冲突
file_put_contents($file, $counter, LOCK_EX);
?>
<?php
// 天气查询 API - 使用国内平台数据
header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
// 获取参数
$city = $_GET['city'] ?? $_GET['q'] ?? null;
$type = $_GET['type'] ?? 'json'; // json, xml
$lang = $_GET['lang'] ?? 'zh'; // zh, en
// 验证参数
if (!$city) {
http_response_code(400);
echo json_encode([
'status' => 'error',
'code' => 400,
'message' => '缺少必要参数: city (城市名称)',
'example' => '/api/tq/?city=北京&type=json&lang=zh'
], JSON_UNESCAPED_UNICODE);
exit;
}
// 非法字符检查
if (!preg_match('/^[\u4e00-\u9fff\w\s\-]+$/u', $city) || strlen($city) > 50) {
http_response_code(400);
echo json_encode([
'status' => 'error',
'code' => 400,
'message' => '无效的城市名称'
], JSON_UNESCAPED_UNICODE);
exit;
}
$result = null;
$error = null;
// 方案1: 心知天气 API (国内数据源,优先使用)
// 方案2: 和风天气 API (国内数据源)
// 方案3: wttr.in (备选)
// 尝试方案1: 心知天气 API (中国天气网数据)
$url1 = "https://api.seniverse.com/v1/now.json?location=" . urlencode($city) . "&language=" . ($lang === 'en' ? 'en' : 'zh-Hans');
$ch1 = curl_init();
curl_setopt($ch1, CURLOPT_URL, $url1);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_TIMEOUT, 8);
curl_setopt($ch1, CURLOPT_USERAGENT, 'Mozilla/5.0 QuickAPI/1.0');
curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
$response1 = curl_exec($ch1);
$http_code1 = curl_getinfo($ch1, CURLINFO_HTTP_CODE);
curl_close($ch1);
if ($http_code1 == 200 && $response1) {
$data1 = json_decode($response1, true);
if ($data1 && isset($data1['results']) && count($data1['results']) > 0) {
$results = $data1['results'][0];
$location = $results['location'];
$now = $results['now'];
$result = [
'status' => 'success',
'code' => 200,
'city' => $location['name'] ?? $city,
'region' => $location['country'] ?? null,
'coordinates' => [
'latitude' => (float)$location['lat'] ?? null,
'longitude' => (float)$location['lon'] ?? null
],
'current' => [
'temperature' => (float)$now['temperature'] ?? null,
'feels_like' => (float)$now['feels_like'] ?? null,
'condition' => $now['text'] ?? 'Unknown',
'condition_code' => $now['code'] ?? null,
'wind_speed' => (float)$now['wind_speed'] ?? null,
'wind_speed_kph' => ((float)$now['wind_speed'] * 3.6) ?? null,
'wind_direction' => $now['wind_direction'] ?? null,
'wind_direction_code' => $now['wind_direction_code'] ?? null,
'humidity' => (int)$now['humidity'] ?? null,
'visibility' => (float)$now['visibility'] ?? null,
'pressure' => (int)$now['pressure'] ?? null
],
'source' => '心知天气',
'updated_at' => date('Y-m-d H:i:s')
];
}
}
// 如果方案1失败尝试方案2: 和风天气 API
if (!$result) {
$url2 = "https://devapi.qweather.com/v7/weather/now?location=" . urlencode($city) . "&lang=" . ($lang === 'en' ? 'en' : 'zh');
$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, $url2);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_TIMEOUT, 8);
curl_setopt($ch2, CURLOPT_USERAGENT, 'Mozilla/5.0 QuickAPI/1.0');
curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
$response2 = curl_exec($ch2);
$http_code2 = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
curl_close($ch2);
if ($http_code2 == 200 && $response2) {
$data2 = json_decode($response2, true);
if ($data2 && isset($data2['now'])) {
$now = $data2['now'];
$result = [
'status' => 'success',
'code' => 200,
'city' => $city,
'current' => [
'temperature' => (int)$now['temp'] ?? null,
'feels_like' => (int)$now['feelsLike'] ?? null,
'condition_code' => $now['icon'] ?? null,
'condition' => $now['text'] ?? 'Unknown',
'wind_speed' => (float)$now['windSpeed'] ?? null,
'wind_direction' => $now['windDir'] ?? null,
'wind_direction_code' => (int)$now['wind_degree'] ?? null,
'humidity' => (int)$now['humidity'] ?? null,
'pressure' => (int)$now['pressure'] ?? null,
'visibility' => (int)$now['vis'] ?? null,
'dew_point' => (int)$now['dewPoint'] ?? null
],
'source' => '和风天气',
'updated_at' => date('Y-m-d H:i:s')
];
}
}
}
// 如果国内方案都失败尝试方案3: wttr.in (备选)
if (!$result) {
$url3 = "https://wttr.in/" . urlencode($city) . "?format=j1&lang=" . ($lang === 'en' ? 'en' : 'zh-CN');
$ch3 = curl_init();
curl_setopt($ch3, CURLOPT_URL, $url3);
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch3, CURLOPT_TIMEOUT, 8);
curl_setopt($ch3, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) QuickAPI/1.0');
curl_setopt($ch3, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch3, CURLOPT_SSL_VERIFYHOST, false);
$response3 = curl_exec($ch3);
$http_code3 = curl_getinfo($ch3, CURLINFO_HTTP_CODE);
curl_close($ch3);
if ($http_code3 == 200 && $response3) {
$data3 = json_decode($response3, true);
if ($data3 && isset($data3['current_condition'])) {
$current = $data3['current_condition'][0];
$desc = $current['desc'] ?? [];
$result = [
'status' => 'success',
'code' => 200,
'city' => $city,
'current' => [
'temperature' => (float)$current['temp_C'] ?? null,
'temperature_f' => (float)$current['temp_F'] ?? null,
'feels_like' => (float)$current['FeelsLikeC'] ?? null,
'condition' => is_array($desc) ? ($desc[$lang === 'en' ? 'en' : 'zh-CN'] ?? $desc[0] ?? 'Unknown') : 'Unknown',
'humidity' => (int)$current['humidity'] ?? null,
'wind_speed' => (float)$current['windspeedKmph'] ?? null,
'wind_speed_ms' => (float)$current['windspeedKmph'] / 3.6 ?? null,
'wind_direction' => $current['winddir16Point'] ?? null,
'pressure' => (int)$current['pressure'] ?? null,
'precipitation' => (float)$current['precipMM'] ?? null,
'visibility' => (float)$current['visibility'] ?? null,
'uv_index' => (int)$current['uvIndex'] ?? null,
'cloud_cover' => (int)$current['cloudcover'] ?? null
],
'source' => 'wttr.in',
'updated_at' => date('Y-m-d H:i:s')
];
}
}
}
// 返回结果
if ($result) {
if ($type === 'xml' || $type === 'XML') {
header('Content-type: application/xml; charset=UTF-8');
echo arrayToXml($result, null, null, 'weather');
} else {
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
} else {
http_response_code(500);
echo json_encode([
'status' => 'error',
'code' => 500,
'message' => $error ?? '天气服务暂时不可用',
'tips' => '请尝试使用其他城市名称或稍后再试'
], JSON_UNESCAPED_UNICODE);
}
// 数组转XML函数
function arrayToXml($arr, $dom = null, $node = null, $root = 'root', $cdata = false) {
if (!$dom) {
$dom = new DOMDocument('1.0', 'utf-8');
}
if (!$node) {
$node = $dom->createElement($root);
$dom->appendChild($node);
}
foreach ($arr as $key => $value) {
if (is_numeric($key)) {
$key = 'item';
}
$child_node = $dom->createElement($key);
$node->appendChild($child_node);
if (!is_array($value)) {
if (!$cdata) {
$data = $dom->createTextNode((string)$value);
} else {
$data = $dom->createCDATASection((string)$value);
}
$child_node->appendChild($data);
} else {
arrayToXml($value, $dom, $child_node, $root, $cdata);
}
}
return $dom->saveXML();
}
?>
file_put_contents($file, $counter, LOCK_EX);
header("Content-type: text/html; charset=UTF-8");
if(!$_GET['msg'])exit("抱歉,出错了!\n请输入城市名!");
$msg = $_GET['msg'];
$n = $_GET['n'];
$str = file_get_contents("compress.zlib://http://m.nmc.cn/f/rest/autocomplete?q=$msg&limit=10&timestamp=1547115792491");//56691|威宁|553100|贵州省|weining|AGZ
$str=str_replace('|','<br>',$str);
$str = str_replace(PHP_EOL,'<hr><hr>', $str);
$str = "<hr>".$str."<hr>";
$stre = '/<hr>(.*?)<br>(.*?)<br>(.*?)<br>(.*?)<br>(.*?)<br>(.*?)<hr>/';
$result = preg_match_all($stre,$str,$trstr);
if($result== 0){
echo "搜索不到与".$_GET["msg"]."的相关天气,请稍后重试或换个关键词试试。";
}else{
if($result== 1){
$a=$trstr[1][0];
$data = file_get_contents("compress.zlib://http://m.nmc.cn/f/rest/real/".$a."");
preg_match_all('/"city":"(.*?)","province":"(.*?)"},"week":"(.*?)","moon":"(.*?)","jie_qi":"(.*?)","publish_time":"(.*?)","weather":{"temperature":(.*?),"temperatureDiff":(.*?),"airpressure":(.*?),"humidity":(.*?),"rain":(.*?),"rcomfort":(.*?),"icomfort":(.*?),"info":"(.*?)","img":"(.*?)","feelst":(.*?)},"wind":{"direct":"(.*?)","power":"(.*?)","speed":"(.*?)"},"warn":{"alert":"(.*?)","pic":"(.*?)","province":"(.*?)","city":"(.*?)","url":"(.*?)","issuecontent":"(.*?)"/',$data,$data);//1地名2省5节气6更新时间7现在温度9气压10湿度12舒适度14天气16体感温度17风向18风力19风速
$a = $data[1][0]; //小地名
$b = $data[2][0]; //省
$s = $data[5][0]; //节气
$c = $data[6][0]; //更新时间
$d = $data[7][0]; //现在温度
$e = $data[9][0]; //气压hPa
$f = $data[10][0]; //湿度
$g = $data[12][0]; //舒适度
$h = $data[14][0]; //天气情况
$i = $data[16][0]; //体感温度
$q = $data[17][0]; //风向
$w = $data[18][0]; //程度
$r = $data[25][0]; //预警
echo "".$a."".$b."\\n\\n天气".$h." 舒适度:".$g."\\n时实温度".$d."℃ 体感:".$i."\\n气压".$e."hPa 湿度:".$f."%\\n风向".$q." 程度:".$w."";
if($r== 9999){}else{echo "\\n预警提示$r";}
echo "\\n更新时间".$c."\\n".$s."";
}else{
if($n== null){
for( $i = 0 ; $i < $result && $i < 15 ; $i ++ ){
$s=$trstr[2][$i];//小地名
$c=$trstr[4][$i];//省
echo ($i+1)."".$c."$s\n";}
echo "共搜索到与【".$_GET["msg"]."】的相关天气信息".$result."条!";
}else{
$n = $_GET['n'];
$i=($n-1);
$a=$trstr[1][$i];//id
$data = file_get_contents("compress.zlib://http://m.nmc.cn/f/rest/real/".$a."");
preg_match_all('/"city":"(.*?)","province":"(.*?)"},"week":"(.*?)","moon":"(.*?)","jie_qi":"(.*?)","publish_time":"(.*?)","weather":{"temperature":(.*?),"temperatureDiff":(.*?),"airpressure":(.*?),"humidity":(.*?),"rain":(.*?),"rcomfort":(.*?),"icomfort":(.*?),"info":"(.*?)","img":"(.*?)","feelst":(.*?)},"wind":{"direct":"(.*?)","power":"(.*?)","speed":"(.*?)"},"warn":{"alert":"(.*?)","pic":"(.*?)","province":"(.*?)","city":"(.*?)","url":"(.*?)","issuecontent":"(.*?)"/',$data,$data);//1地名2省5节气6更新时间7现在温度9气压10湿度12舒适度14天气16体感温度17风向18风力19风速
$a = $data[1][0]; //小地名
$b = $data[2][0]; //省
$s = $data[5][0]; //节气
$c = $data[6][0]; //更新时间
$d = $data[7][0]; //现在温度
$e = $data[9][0]; //气压hPa
$f = $data[10][0]; //湿度
$g = $data[12][0]; //舒适度
$h = $data[14][0]; //天气情况
$i = $data[16][0]; //体感温度
$q = $data[17][0]; //风向
$w = $data[18][0]; //程度
$s = $data[19][0]; //风速m/s
$r = $data[25][0]; //预警
echo "".$a."".$b."\r\n\r\n天气:".$h." 舒适度:".$g."\r\n时实温度:".$d."℃ 体感:".$i."\r\n气压:".$e."hPa 湿度:".$f."%\r\n风向:".$q." 程度:".$w."";
if($r== 9999){}else{echo "\r\n预警提示:$r";}
echo "\r\n更新时间:".$c."\r\n".$s."";}}}
?>