# 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` | 获取实时天气+nowcasting | ✅ 稳定可用 | | **逐小时预报** | `https://assets.msn.cn/service/weather/hourlyforecast` | 未来10天逐小时预报 | ✅ 稳定可用(新增) | | **每日预报** | `https://assets.msn.cn/service/weather/dailyforecast` | 未来10天每日汇总 | ✅ 稳定可用 | | **天气趋势** | `https://assets.msn.cn/service/weather/weathertrends` | 历史+趋势+日历 | ❌ 已失效(500错误) | | api.msn.cn 当前 | `https://api.msn.cn/weather/current` | 用城市名获取 | ✅ 可用(但城市名不准) | | api.msn.cn 预报 | `https://api.msn.cn/weather/forecast` | 预报 | ❌ 500错误 | **推荐**:只用 `assets.msn.cn` 的三个接口(current + hourlyforecast + dailyforecast)即可满足大部分需求。 --- ## 三、关键参数说明 ### 必须参数 - **`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" } # 获取逐小时预报(今天剩余小时 + 后续几天) $uri_hourly = "https://assets.msn.cn/service/weather/hourlyforecast?apiKey=$apiKey&lat=39.904172&lon=116.407417&units=C&locale=zh-cn" $hourlyResp = Invoke-RestMethod -Uri $uri_hourly -Headers $headers $todayHourly = $hourlyResp.value[0].responses[0].weather[0].days[0].hourly Write-Host "`n今天逐小时预报:" foreach ($h in $todayHourly) { Write-Host " $($h.valid.ToString("HH:mm")): $($h.temp)C, $($h.cap), 体感$($h.feels)C, 降水$($h.precip)%, 湿度$($h.rh)%, 风速$($h.windSpd)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" # 逐小时预报(今天剩余+未来几天) curl -H "User-Agent: Mozilla/5.0" \ -H "Referer: https://www.msn.com/zh-cn/weather" \ "https://assets.msn.cn/service/weather/hourlyforecast?apiKey=j5i4gDqHL6nGYwx5wi5kRhXjtf2c5qgFX9fzfk0TOo&lat=39.904172&lon=116.407417&units=C&locale=zh-cn" ``` --- ## 五、返回数据结构 ### 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": "中等" } } // ... 更多天 ] }] }] }] } ``` ### hourlyforecast 接口响应 ```json { "@odata.context": "api.msn.com/weather/$metadata#hourlyforecast", "value": [{ "responses": [{ "weather": [{ "days": [ { // days[0] = 今天,从当前小时开始到23点 // days[1..9] = 未来9天,每天24个整点 "hourly": [ { "valid": "2026-05-11T07:00:00+08:00", // 时间 "temp": 19.0, // 温度 °C "feels": 23.0, // 体感温度 °C "cap": "晴", // 天气描述 "precip": 0.0, // 降水概率 % "rh": 61.0, // 相对湿度 % "baro": 1009.0, // 气压 hPa "windSpd": 4.0, // 风速 km/h "windDir": 355, // 风向(度) "windGust": 18.0, // 阵风 km/h "uv": 1.0, // 紫外线指数 "cloudCover": 6.0, // 云量 % "vis": 10.0, // 能见度 km "dewPt": 11.0, // 露点 °C "rainAmount": 0.0, // 降雨量 mm "snowAmount": 0.0, // 降雪量 mm "icon": 1, // 图标代码 "symbol": "d000", // 天气符号 "sky": "CLR" // 天空状况代码 } // ... 更多小时 ] } ] }] }] }] } ``` > **注意**:`days[0].daily` 为 null(今天尚未结束),逐小时数据从 `days[0].hourly` 获取。 --- ## 六、多城市验证结果 | 城市 | 经纬度 | 状态 | 示例数据 | |------|--------|------|----------| | 北京 | 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 # 逐小时预报 $hourlyUri = "https://assets.msn.cn/service/weather/hourlyforecast?apiKey=$apiKey&lat=$Lat&lon=$Lon&units=C&locale=$Locale" $hourly = Invoke-RestMethod -Uri $hourlyUri -Headers $headers return @{ Current = $current.value[0].responses[0].weather[0].current Forecast = $forecast.value[0].responses[0].weather[0].days Hourly = $hourly.value[0].responses[0].weather[0].days } } # 使用示例 $weather = Get-MSNWeather -Lat 39.904172 -Lon 116.407417 $weather.Current.temp # 当前温度 $weather.Hourly[0].hourly # 今天逐小时数据 ``` --- ## 九、补充:天气图标对照 接口返回的 `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+紫外线+nowcasting) | | 推荐用途 | 个人项目、内部工具、原型开发 | | 不推荐用途 | 商业产品、长期运行服务 | ## 现状更新 **2026-05-11 更新:** - `weathertrends` 接口已失效(500 Internal Server Error) - 新发现 `hourlyforecast` 接口,提供未来 10 天逐小时预报数据,与 `current`、`dailyforecast` 同样稳定 - 云图(卫星/雷达)无 REST API 可用,MSN 网页使用 tile 图片服务(`assets.msn.com/weathermapdata/`),不适合程序化调用 **建议**:如果用于生产环境,推荐同时准备备用方案(如和风天气、OpenWeatherMap 等)。