11 月 1 日,上海闵行的天空灰蒙蒙的,没什么刺鼻气味。我问了 OpenClaw,想知道今天的空气怎么了。

它给了一份很详细的分析:昨天的雾还没散,南风把长三角的污染带过来,下午又有光化学反应。后面还接着解释,为什么去安吉山上会好一些。

几条原因都讲得很确定。我想再核对一下,结果这件事一直折腾到了晚上,最后还给自己的天气工具加了一组字段。

晚上十点多,我重新查了闵行附近一个坐标,把当天的小时数据存了下来。颗粒物和 AOD 用的是 CAMS global,天气数据来自 Open-Meteo。先交代这一点:下面这些数字都是模型给的,和监测站的实测还有一层距离。我当天实际记下来的,只有天空灰蒙蒙、没有刺鼻气味。

下面三幅图用了同一次查询中 09:00 到 21:00 的小时结果,各自保留单位。原表也留在后面,方便对照几个时刻。

2026-11-01 闵行代表坐标的大气模型小时序列。PM2.5、AOD、能见度分别使用各自纵轴;非监测站实测。

上海时间PM2.5(μg/m³)AOD能见度(km)
09:0024.40.4221.78
15:0043.11.0021.78
18:0043.50.596.48
21:0046.70.3816.38

PM2.5 从上午到夜间总体在升高。AOD 却在下午升上去,晚上又降了下来。

傍晚这段尤其值得看。15 点到 18 点,PM2.5 没变多少,能见度却从二十多公里掉到了六公里多。到了 21 点,能见度又回升了,但 PM2.5 还在往上走。

所以,晚上到底有没有变好?

这张表没法给一个干脆的答案。

PM2.5 描述近地面的颗粒物浓度,AOD 描述整根大气柱里气溶胶对光的消光。能见度又是近地面的水平视程。看远处的景物和抬头拍星,光经过的那段空气不一样。

这一天里,云和湿度也在变。天气模型给出的下午云量增加,18 点湿度到了 84%。这些东西叠在一起,才是我看见的那片天空。现在这份数据还分不清各自占了多少。

最初那份分析里,我也很在意“上山就能躲开污染层”这句话。拍星的人看到这个,很容易接着去查山顶的海拔。

但只拿上海的边界层高度,去和安吉某个山顶的海拔比较,中间缺了不少东西。山上当时的天气、当地的地形、气溶胶在不同高度的分布,都还不知道。AOD 本身也不告诉我,颗粒物集中在哪一层。

至于南风到底带来了哪里的污染,傍晚的 NO₂ 又有多少来自交通,这次也没查到足够的证据。先留着,不能因为几条曲线看着对得上,就把原因写定了。

工具这边倒是做完了一件事。

原来的天气查询主要返回云量、温度、风和降水。我把颗粒物、AOD、能见度和边界层加了进去,仍然放在同一次天气查询里。每个字段带着来源、单位和对应时间;查不到就留空。现在 NAS 上跑的 0.11.0 已经能返回这些数据了。

写接口时还有个细节挺容易忽略:CAMS global 的原生网格约 45 公里,时间间隔是 3 小时。接口给我一排小时数据,不等于每个小时都有一次独立观测。那些小数点看起来很精确,也不能拿来解释我家附近每条街的差别。数据来源说明

这一天最后留下的,还是两个不太一样的记录:我看到天空灰蒙蒙的;模型里,近地面颗粒物、整层消光和水平能见度各有各的变化。

以后再碰到这样的天,我想把数据和当时的照片一起留着。多攒几次,再看看哪些变化是模型提前说对的,哪些只是数字看起来很像那么回事。