跳到主内容

Python 历史天气数据采集怎么用:从接口选型到字段清洗的完整实操流程

"能不能把你之前那个天气采集器的脚本发我一份?我也要跑十年数据。"

这是上周收到的第 3 个同类请求。每次我都先回一句:你要的是哪十年的、用来干什么?因为如果只是要气温和降水,根本不用爬——Open-Meteo 的归档接口一条 GET 就能拿 1940 年至今的逐日数据,官方 CC BY 4.0 授权、免密钥、非商用每天 1 万次以内免费。我这次把三条路都真跑了一遍,包括哪条会让你白干两天。

先分流一句:如果你要的是"绕过某天气站签名校验、逆向 token、写 tkinter 界面"那套,站内这篇历史天气采集器的踩坑复盘写得更细,本篇不重复。这篇只讲换用公开 API 之后,接口怎么选、字段怎么洗。

需求背景

手上的活是给一个农业保险项目做近三十年气温与降水基线,城市二十来个、颗粒度到日。硬约束三条:数据要能合法对外交付、字段口径可追溯、不能靠人力去点。

这三个约束一摆,爬虫路线其实已经出局——不是跑不动,是交付时没法向客户证明数据来源合法。

方案A:爬网页表格

老办法。找到前端渲染表格的站,写 XPath 或正则抠出来。站内那篇复盘里写得很清楚:动态加载、每分钟 20 次就封 IP 半小时、签名 token 五分钟失效。

我把它列为对照项而不是主方案,理由是交付风险:爬下来的数字没法标注出处、没法说明口径。真要爬,务必先看对方 robots.txt、控制频率、只做技术学习。

代价:两天起步的逆向成本 + 长期维护成本 + 一整个说不清的合规口子。

方案B:归档接口直接拉(ERA5 再分析)

主方案就这条。端点 archive-api.open-meteo.com/v1/archive,底层是 ERA5 / ERA5-Land 再分析,覆盖 1940 年至今、全球网格无缺测。

GET https://archive-api.open-meteo.com/v1/archive
      ?latitude=39.9042&longitude=116.4074
      &start_date=2025-01-01&end_date=2025-01-31
      &daily=temperature_2m_max,temperature_2m_min,precipitation_sum
      &timezone=Asia%2FShanghai

实测:31 天一次返回,1.26 秒、1415 字节、零 null。响应里 daily_units 把每个变量单位标得明白(°C / mm / km/h),elevation 返回 47.0 米,utc_offset_seconds 是 28800——这些建议原样落库。

拉一整年(365 天、三个变量)也只 10,462 字节、6.24 秒,同样零 null。我顺手算了北京 2025 全年:最高 40.4℃ 在 6 月 22 日,最低 -12.7℃ 在 2 月 7 日,降水合计 711.0 毫米、雨日 111 天。

代价:它是再分析不是站点实测,空间分辨率 0.1–0.25 度,山区与城市热岛会被抹平;而且有更新延迟,我实测的可用上界是 2026-10-17,也就是昨天。

方案C:预报接口回看最近 92 天

只关心最近三个月的话,api.open-meteo.com/v1/forecast 加 past_days 更省事,实测 past_days=92 一次返回 93 天,格式与线上预报接口一致,做偏差校正时省一层转换。

代价清清楚楚:只有 92 天,做不了多年基线。

横向对比表

方案时间跨度一次请求实测授权主要代价
A 爬网页看对方留存不定(含封禁重试)不明合规与维护
B 归档 API1940 至今1.26s / 1.4 KB(31 天)CC BY 4.0再分析非实测
C 预报回看最近 92 天快且同格式CC BY 4.0跨度太短

怎么选

多年基线选 B,近三个月回填选 C,A 只在"必须要某站原始观测值且已获授权"时才考虑。

选完还有三个字段级坑,全是我这次踩出来的:

坑一:不传 timezone 就按 UTC 切片。默认返回的 timezone 是 GMT、utc_offset_seconds 是 0,中国跨 UTC+8、日界整差 8 小时。实测北京 2025 年 7 月 1 日降水:UTC 口径 1.1 毫米,上海时区口径 10.0 毫米——同一天差了近十倍。日聚合务必显式传 timezone,后处理掰不回来。

坑二:models 不指定,"最佳匹配"和纯 ERA5 能差两度。同一天(2025-01-01 北京)实测:默认 best_match 最高 3.2℃ / 最低 -2.0℃,era5 是 5.2 / -6.0,era5_land 是 4.3 / -5.3,最低温差了整整 4 度。报告里必须写明用哪一套,否则复现不了。

坑三:错误是 HTTP 400 + JSON,别只判状态码。日期越界返回 {"error":true,"reason":"Parameter 'end_date' is out of allowed range from 1940-01-01 to 2026-10-17"};start_date 晚于 end_date 只给一句 Bad Request;纬度传 999 会回 Latitude must be in range of -90 to 90°. Given: 999.0.。把 reason 写进日志,排查省很多事。

另外两个提效参数:latitude / longitude 支持逗号分隔一次传多城,返回会变成一个数组、每个元素各自带 elevation,二十个城市不用循环二十次;timeformat=unixtime 可以把时间直接换成时间戳(实测 1735660800)。

数据出处与授权:Open-Meteo 归档 API https://archive-api.open-meteo.com/v1/archive、预报 API https://api.open-meteo.com/v1/forecast,文档 https://open-meteo.com/en/docs。数据 CC BY 4.0,可商用但需署名并注明改动,非商用每日 1 万次以内免费、更高配额需订阅;服务端 AGPLv3 可自托管。以上为 2026-10-18 实测,配额与时延请以官方最新公布为准。采回来要落表的,站内公开网页表格导出能把返回整理成标准表格,公开榜单排名追踪则适合做多期对比。

常见问题

Q:ERA5 再分析能当实测数据用吗?
不能画等号。它是模式再分析,分辨率 0.1–0.25 度,山区与城市热岛会被平滑。做气候基线和趋势分析没问题,做"某站点某天的准确降水量"请走气象部门观测数据。

Q:为什么我拉不到最近三天?
归档有更新延迟,实测可用的结束日期是昨天。要最近几天的用预报接口的 past_days。

Q:一次能拉多少天?要不要分页?
不用分页。实测一次拉 365 天三个变量才 10 KB、6 秒出头。真正要留意的是别把二十个城市拆成二十次请求——用逗号拼起来一次发。

Q:单位能改吗?
能。temperature_unit=fahrenheit、windspeed_unit=ms 直接加在 URL 上,实测 3.2℃ 变 37.8°F、风速变 3.07 m/s。响应里 daily_units 会同步更新,落库前读它最稳。

Q:采集类的活还有什么要注意的?
合规第一条。用公开 API 就遵守授权条款(CC BY 4.0 要署名);爬网页先看 robots.txt、控制频率、只做技术学习。另外时间戳一定要留,跨期对比没它说不清口径。

相关阅读

分享到:

本文链接:https://www.biyeyuanma.cn/post/346.html

服务热线

加我微信

加我微信