Files
YunShu/docs/MSN天气API探索报告.md
2026-05-08 10:12:31 +08:00

298 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MSN 天气 API 探索报告
**生成时间**: 2026-05-03
**探索目标**: 确认 MSN 天气是否有免费可用的 API 接口
---
## 一、核心结论
**MSN 没有官方公开的免费 REST API**,但存在**微软官方内部 API**(通过浏览器抓包获得),在国内访问速度快,可直接调用。
- ❌ **不是**官方对外公开的 API无文档、无 SLA
- ✅ **是**微软官方的后台接口(`assets.msn.cn` / `api.msn.cn` 均为微软域名)
- ⚠️ 属于**非公开内部 API**,随时可能变更或失效
---
## 二、可用接口汇总
| 接口 | URL | 功能 | 稳定性 |
|------|-----|------|--------|
| **当前天气** | `https://assets.msn.cn/service/weather/current` | 获取实时天气 | ✅ 稳定可用 |
| **每日预报** | `https://assets.msn.cn/service/weather/dailyforecast` | 未来10天预报 | ✅ 稳定可用 |
| **天气趋势** | `https://assets.msn.cn/service/weather/weathertrends` | 历史+趋势+日历 | ✅ 可用(参数复杂) |
| api.msn.cn 当前 | `https://api.msn.cn/weather/current` | 用城市名获取 | ✅ 可用(但城市名不准) |
| api.msn.cn 预报 | `https://api.msn.cn/weather/forecast` | 预报 | ❌ 500错误 |
**推荐**:只用 `assets.msn.cn` 的两个接口即可满足大部分需求。
---
## 三、关键参数说明
### 必须参数
- **`apiKey`**: `j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo`
- 固定值,修改任意字符即返回 401 Unauthorized
- 从微软 MSN 天气前端代码中提取
- **`lat`** / **`lon`**: 经纬度WGS84 坐标系)
- **`locale`**: 语言区域,如 `zh-cn``en-us`
### 可选参数
- **`units`**: 温度单位,`C`(摄氏)或 `F`(华氏)
- **`days`**: 预报天数dailyforecast 接口最大10天
### 不需要的参数
- `user`: 测试发现不带也能正常工作
- `cm``ocid``fdhead` 等: weathertrends 专用dailyforecast 不需要
### 必须请求头
```http
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Referer: https://www.msn.com/zh-cn/weather
```
不带这些请求头会返回 `401 Authorization Required`
---
## 四、调用示例
### PowerShell 示例
```powershell
$apiKey = "j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo"
$headers = @{
"User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
"Referer" = "https://www.msn.com/zh-cn/weather"
}
# 获取当前天气(北京)
$uri_current = "https://assets.msn.cn/service/weather/current?apiKey=$apiKey&lat=39.904172&lon=116.407417&units=C&locale=zh-cn"
$currentResp = Invoke-RestMethod -Uri $uri_current -Headers $headers
$current = $currentResp.value[0].responses[0].weather[0].current
Write-Host "温度: $($current.temp)C"
Write-Host "天气: $($current.cap)"
Write-Host "体感: $($current.feels)C"
Write-Host "湿度: $($current.rh)%"
Write-Host "风速: $($current.windSpd)km/h"
Write-Host "气压: $($current.baro)hPa"
Write-Host "紫外线: $($current.uv) ($($current.uvDesc))"
Write-Host "AQI: $($current.aqi) ($($current.aqiSeverity))"
# 获取未来7天预报
$uri_forecast = "https://assets.msn.cn/service/weather/dailyforecast?apiKey=$apiKey&lat=39.904172&lon=116.407417&units=C&locale=zh-cn&days=7"
$forecastResp = Invoke-RestMethod -Uri $uri_forecast -Headers $headers
$days = $forecastResp.value[0].responses[0].weather[0].days
Write-Host "`n未来7天预报:"
foreach ($day in $days) {
$d = $day.daily
Write-Host " $($d.valid.ToString().Substring(0,10)): $($d.tempLo)-$($d.tempHi)C, 降水$($d.precip)%, 风速$($d.windMax)km/h"
}
```
### curl 示例
```bash
# 当前天气
curl -H "User-Agent: Mozilla/5.0" \
-H "Referer: https://www.msn.com/zh-cn/weather" \
"https://assets.msn.cn/service/weather/current?apiKey=j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo&lat=39.904172&lon=116.407417&units=C&locale=zh-cn"
# 7天预报
curl -H "User-Agent: Mozilla/5.0" \
-H "Referer: https://www.msn.com/zh-cn/weather" \
"https://assets.msn.cn/service/weather/dailyforecast?apiKey=j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo&lat=39.904172&lon=116.407417&units=C&locale=zh-cn&days=7"
```
---
## 五、返回数据结构
### current 接口响应
```json
{
"@odata.context": "api.msn.com/weather/$metadata#current",
"value": [{
"responses": [{
"weather": [{
"current": {
"temp": 20.0, // 当前温度
"cap": "晴", // 天气描述
"capAbbr": "晴", // 简短描述
"feels": 20.0, // 体感温度
"rh": 14.0, // 相对湿度 %
"baro": 1006.0, // 气压 hPa
"windSpd": 25.0, // 风速 km/h
"windDir": 360, // 风向(度)
"windGust": 43.0, // 阵风速度
"uv": 5.0, // 紫外线指数
"uvDesc": "中等", // 紫外线描述
"vis": 30.0, // 能见度 km
"dewPt": -8.0, // 露点温度
"aqi": 22.0, // AQI指数
"aqiSeverity": "优", // AQI等级
"cloudCover": 15.0, // 云量 %
"created": "2026-05-03T14:29:06+08:00"
}
}],
"source": {
"location": "北京, 北京市, 中国",
"coordinates": {"lat": 39.904172, "lon": 116.407417}
}
}]
}]
}
```
### dailyforecast 接口响应
```json
{
"@odata.context": "api.msn.com/weather/$metadata#dailyforecast",
"value": [{
"responses": [{
"weather": [{
"days": [
{
"daily": {
"valid": "2026-05-03T00:00:00", // 日期
"tempLo": 8, // 最低温
"tempHi": 21, // 最高温
"precip": 5.0, // 降水概率 %
"windMax": 10.0, // 最大风速
"windMaxDir": 286, // 风向
"rhHi": 35.85, // 最高湿度
"rhLo": 14.0, // 最低湿度
"icon": 1, // 图标代码
"symbol": "d000", // 天气符号
"uv": 5.0, // 紫外线指数
"uvDesc": "中等"
}
}
// ... 更多天
]
}]
}]
}]
}
```
---
## 六、多城市验证结果
| 城市 | 经纬度 | 状态 | 示例数据 |
|------|--------|------|----------|
| 北京 | 39.904172, 116.407417 | ✅ 正常 | 20°C, 晴, 湿度14% |
| 上海 | 31.2304, 121.4737 | ✅ 正常 | 21°C, 多云, 湿度54% |
| 广州 | 23.1291, 113.2644 | ✅ 正常 | 24°C, 多云, 湿度79% |
| 成都 | 30.5728, 104.0668 | ✅ 正常 | 23°C, 局部多云, 湿度42% |
---
## 七、限制与注意事项
### 1. apiKey 固定
- 当前 key 硬编码在微软前端代码中
- 修改任意字符即失效(返回 401
- **长期有效性未知**,微软可能随时更换
### 2. 非公开接口
- 无官方文档
- 无 SLA服务等级协议保证
- 数据结构可能随时变更
### 3. 需要特定请求头
必须携带 `User-Agent``Referer`,否则返回 401。
### 4. 限流未知
未测试请求频率限制,建议生产环境加入适当的请求间隔。
### 5. 城市名接口不可靠
`api.msn.cn` 使用城市名参数可能返回错误城市(测试"北京"返回了也门首都萨那)。
### 6. 法律合规
- 这是非公开接口,用于个人项目/内部工具问题不大
- **不建议用于商业产品**(随时可能失效,且无使用授权)
---
## 八、推荐方案
### 最简调用方案
```powershell
function Get-MSNWeather {
param(
[double]$Lat,
[double]$Lon,
[string]$Locale = "zh-cn"
)
$apiKey = "j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo"
$headers = @{
"User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
"Referer" = "https://www.msn.com/zh-cn/weather"
}
# 当前天气
$currentUri = "https://assets.msn.cn/service/weather/current?apiKey=$apiKey&lat=$Lat&lon=$Lon&units=C&locale=$Locale"
$current = Invoke-RestMethod -Uri $currentUri -Headers $headers
# 7天预报
$forecastUri = "https://assets.msn.cn/service/weather/dailyforecast?apiKey=$apiKey&lat=$Lat&lon=$Lon&units=C&locale=$Locale&days=7"
$forecast = Invoke-RestMethod -Uri $forecastUri -Headers $headers
return @{
Current = $current.value[0].responses[0].weather[0].current
Forecast = $forecast.value[0].responses[0].weather[0].days
}
}
# 使用示例
$weather = Get-MSNWeather -Lat 39.904172 -Lon 116.407417
$weather.Current.temp # 当前温度
```
---
## 九、补充:天气图标对照
接口返回的 `icon``symbol` 字段对应天气图标:
- `0`: 晴天
- `1`: 大部晴朗
- `2`: 局部多云
- `3`: 多云
- `4`: 阴天
- `5-6`: 有雾
- `7-8`: 阴沉
- `9-12`: 阵雨
- `13-18`: 雷雨
- `19-22`: 雨夹雪
- `23-26`: 小雪
- `27-30`: 中到大雪
图标完整 URL
```
http://img-s-msn-com.akamaized.net/tenant/amp/entityid/AAehR3S.img
```
(其中 `AAehR3S` 是从 `urlIcon` 字段获取)
---
## 十、总结
| 项目 | 结论 |
|------|------|
| 是否有免费 API | ✅ 有(非公开内部接口) |
| 国内速度 | ✅ 快msn.cn 国内节点) |
| 稳定性 | ⚠️ 未知(非官方,随时可能变) |
| 数据完整性 | ✅ 完整(当前+预报+AQI+紫外线等) |
| 推荐用途 | 个人项目、内部工具、原型开发 |
| 不推荐用途 | 商业产品、长期运行服务 |
**建议**如果用于生产环境推荐同时准备备用方案如和风天气、OpenWeatherMap 等)。