Python | Met Office | 爬取全球气象站点数据

文摘   2024-10-19 15:57   北京  

Met Office

Met Office 是英国的国家气象服务机构,成立于 1854年,隶属于英国商务、能源与产业战略部,它是全球最知名的气象机构之一。

HadISD(Hadley Centre Integrated Surface Database,哈德莱中心综合地面数据库)Met Office开发的全球sub-daily气象数据集,基于美国 NOAA(国家海洋和大气管理局)下属的 NCEI(国家环境信息中心)的 ISD(Integrated Surface Database, 综合地面气象数据库) 数据集。

HadISD 进行了多项质量控制,剔除明显的打字或仪器错误。可用的变量包括温度露点温度海平面气压风速风向降水量云量云底高度,以及重要天气的记录。数据通常每小时每三小时或每六小时记录一次。

从校正后的 HadISD 中的站点获取的全球和区域年平均风速的时间序列

一些站点的数据记录超过 50 年,另一些则有较多缺失数据。每个观测站都有独立的记录,若站点位置发生短距离迁移,可能会出现时间互补的多个记录。数据更新频率大约为每月一次。全球约有 10,000 个站点的数据(按 WMO 识别号列出),数据以 netCDF 文件格式提供,总大小约为 23 GB

HadISD 站点在 1x1 度网格上的分布。这些是 ISD 的子集,至少每 6 小时报告一次,并且有足够长的记录

截止本文发出,HadISD最新版本是3.4.1.202408p,数据时间跨度从 1931年1月1日2024年8月

飓风Helene经过北卡罗来纳州后,阿什维尔地区发生大面积洪水,导致部分NOAA-NCEI 网站和数据集中断。这意味着将于 2024 年 10 月上旬的 HadISD 更新 (v3.4.1.202409p) 将被推迟

Hurricane Helene

HadISD的优缺点

优点

  • 站点集非常全面并定期更新,能够实现接近全球范围的分析,无需依赖网格化产品。
  • 未强制执行不均匀性修正或其他调整,允许用户根据需要检查和分析原始观测数据。
  • 由于 ISD 数据中明显有问题的数据已经被筛选出,在数据覆盖良好的区域,计算通常可以直接进行,无需进一步的质量控制(QC)工作。

缺点

  • 只有温度露点气压风速云层信息经过了质量控制,并且每个变量的质量控制测试是单独进行的。因此,详细分析仍然可能遇到质量控制问题。
  • 数据未进行同化处理,因此不能保证时间上的一致性,这同样适用于附近站点之间的空间一致性。
HadISD 中的站点分布和数据记录时间

数据的下载

首先我们打开数据的官网:https://www.metoffice.gov.uk/hadobs/hadisd/index.html

点击 DOWNLOAD DATA 按钮。

点击第一个“here”

将里面的的所有站点信息复制进txt文本,站点信息的网址为:https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/files/hadisd_station_info_v341_202408p.txt(截止本文发出时站点数据网址),保存进一个txt文件。

这里我们举一个例子,以东方人以及西方人都熟悉的阿尔卑斯山脉举例,爬取该地区站点数据。

阿尔卑斯山脉

首先读取数据,筛选经纬度范围内的站点。

import pandas as pd
import os
site = pd.read_csv('hadisd_station_info_v341_202408p.txt'
                   delim_whitespace=True, header=None
                   names=['id','latitude''longitude''altitude']) 

site_alps = site[(site['longitude'] >= 5) & (site['longitude'] <= 16) &
                 (site['latitude'] >= 44) & (site['latitude'] <= 47.5)]
print(site_alps)

将显示站点id以及经纬度,海拔高度。

                id  latitude  longitude  altitude
980   066040-99999    47.000      6.950     487.0
981   066045-99999    47.084      6.793    1026.6
982   066050-99999    47.133      7.067    1631.0
983   066090-99999    46.550      7.017    1973.0
984   066099-99999    47.399      8.648     448.1
           ...       ...        ...       ...
2213  161480-99999    44.224     12.307       5.5
2214  161490-99999    44.020     12.612      12.5
2246  162591-99999    44.824     10.296      49.1
2247  162592-99999    44.547      7.623     386.2
2248  162593-99999    45.429     10.331     108.5

[210 rows x 4 columns]

这里显示了有210个站点位于阿尔卑斯山脉地区。

接下来我们下载数据,数据的是经过 Gzip(GNU zip)压缩算法进行压缩的nc数据。

# data saving folder
save_folder_path = r'your_data_path'
os.makedirs(save_folder_path, exist_ok=True)

# download target site data
for site_id in site_alps['id']:
    download_url = f'https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_{site_id}.nc.gz' 
    print(f'downloading {site_id} data from {download_url}')
    response = requests.get(download_url)
    response.raise_for_status() # fault report
    # save file
    # write/read in binary format
    download_file_path = os.path.join(save_folder_path,f'{site_id}.nc.gz')
    
    with open(download_file_path,'wb'as file:
        file.write(response.content)
    print(f'site {site_id} saved')
downloading 161220-99999 data from https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_161220-99999.nc.gz
site 161220-99999 saved
downloading 161240-99999 data from https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_161240-99999.nc.gz
site 161240-99999 saved
downloading 161250-99999 data from https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_161250-99999.nc.gz
site 161250-99999 saved
downloading 161290-99999 data from https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_161290-99999.nc.gz
site 161290-99999 saved
downloading 161340-99999 data from https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_161340-99999.nc.gz

下载之后对压缩包进行解压并且删除。

# decompress .nc.gz -> .nc
folder_path = r'your_data_path'

for filename in os.listdir(folder_path):
    if filename.endswith('.nc.gz'):
        file_path = os.path.join(folder_path, filename)
        with gzip.open(file_path, 'rb'as gz_file:
            filename_nc = os.path.splitext(filename)[0# split filename and extension name (.gz), keep filename
            file_path_nc = os.path.join(folder_path, filename_nc)
            with open(file_path_nc, 'wb'as output_file:
                output_file.write(gz_file.read())
        print(f'{filename} decompressed')
        # del .gz 
        os.remove(file_path)
        print(f'{filename} deleted')
066040-99999.nc.gz decompressed
066040-99999.nc.gz deleted
066045-99999.nc.gz decompressed
066045-99999.nc.gz deleted
066050-99999.nc.gz decompressed
066050-99999.nc.gz deleted
...
...
...
161180-99999.nc.gz decompressed
161180-99999.nc.gz deleted
161190-99999.nc.gz decompressed
161190-99999.nc.gz deleted
161200-99999.nc.gz decompressed
161200-99999.nc.gz deleted
161220-99999.nc.gz decompressed
161220-99999.nc.gz deleted
161240-99999.nc.gz decompressed
161240-99999.nc.gz deleted
161250-99999.nc.gz decompressed
161250-99999.nc.gz deleted

完整代码

import pandas as pd
import os
import gzip
site = pd.read_csv('hadisd_station_info_v341_202408p.txt'
                   delim_whitespace=True, header=None
                   names=['id','latitude''longitude''altitude']) 

site_alps = site[(site['longitude'] >= 5) & (site['longitude'] <= 16) &
                 (site['latitude'] >= 44) & (site['latitude'] <= 47.5)]
print(site_alps)

# data saving folder
save_folder_path = r'your_data_path'
os.makedirs(save_folder_path, exist_ok=True)

# download target site data
for site_id in site_alps['id']:
    download_url = f'https://www.metoffice.gov.uk/hadobs/hadisd/v341_202408p/data/hadisd.3.4.1.202408p_19310101-20240901_{site_id}.nc.gz' 
    print(f'downloading {site_id} data from {download_url}')
    response = requests.get(download_url)
    response.raise_for_status() # fault report
    # save file
    # write/read in binary format
    download_file_path = os.path.join(save_folder_path,f'{site_id}.nc.gz')
    
    with open(download_file_path,'wb'as file:
        file.write(response.content)
    print(f'site {site_id} saved')

# decompress .nc.gz -> .nc
folder_path = r'your_data_path'

for filename in os.listdir(folder_path):
    if filename.endswith('.nc.gz'):
        file_path = os.path.join(folder_path, filename)
        with gzip.open(file_path, 'rb'as gz_file:
            filename_nc = os.path.splitext(filename)[0# split filename and extension name (.gz), keep filename
            file_path_nc = os.path.join(folder_path, filename_nc)
            with open(file_path_nc, 'wb'as output_file:
                output_file.write(gz_file.read())
        print(f'{filename} decompressed')
        # del .gz 
        os.remove(file_path)
        print(f'{filename} deleted')

最后需要注意的是:

代码中的hadisd_station_info_v341_202408p.txt以及download_url会随着HadISD的更新而改变,如有读者需要后续更新的txt以及url可在后台回复。

Reference

  • https://www.metoffice.gov.uk/hadobs/hadisd/index.html
  • https://hadisd.blogspot.com/

往期回顾

·投稿或转载请联系·
小编微信
长按可关注


气python风雨
主要发一些涉及大气科学的Python文章与个人学习备忘录
 最新文章