首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >使用 Python 查询 Sentinel-1 数据,绘制查询结果范围并下载数据

使用 Python 查询 Sentinel-1 数据,绘制查询结果范围并下载数据

作者头像
气象学家
发布2026-03-25 21:29:51
发布2026-03-25 21:29:51
290
举报
文章被收录于专栏:气象学家气象学家

本文主要介绍通过 Python 从哥白尼数据空间生态系统(https://dataspace.copernicus.eu/) 下载哨兵1(Sentinel-1)号 VV&VH 极化 IW_SLC__1S 产品数据。整体流程如下:

本例以查询和下载2025年9月1日至2025年12月31日洛阳市宜阳县 Sentinel-1 VV&VH 极化 IW_SLC__1S 数据为例。

1 申请一个 Copernicus 账号

申请地址:https://dataspace.copernicus.eu/

按步操作,不再赘述:

2 配置 Python 依赖

Python: 3.12

安装以下库(内置库或关联库已忽略):

gma: 2.2.0(下载:https://pypi.org/project/gma/) requests: 2.32.3 tqdm: 4.67.1

3 查询数据

本例使用的基础省、市、县三级行政区矢量数据来源于锐多宝

下载地址:https://www.shengshixian.com/。

注:查询数据不需要账号

代码语言:javascript
复制
from gma import io
import requests

xian = io.ReadVector('T2024年初县级.shp')

# 从县级里筛选出 宜阳县,也可以根据需求自行筛选或打开其他矢量文件
ly = xian.Select('"县级" = "宜阳县"')

## 获取筛选图层的范围,生成筛选范围 wkt 字符串
area_ft = ly.Extent().GetFeature()
ploygon = area_ft.ExportGeom()

## 配置查询参数
filters = ["Collection/Name eq 'SENTINEL-1'", # 数据集名称
           f"OData.CSC.Intersects(area=geography'SRID=4326;{ploygon}')",  # 查询范围,我们要找的宜阳县边界,必须为 WGS 84(EPSG:4326)坐标系
           "Attributes/OData.CSC.StringAttribute/any(att:att/Name eq 'productType' and att/OData.CSC.StringAttribute/Value eq 'IW_SLC__1S')", # 查询产品 IW_SLC__1S 
           "ContentDate/Start gt 2025-09-01T00:00:00.000Z", # 数据开始时间
           "ContentDate/End lt 2026-01-01T00:00:00.000Z", # 数据结束时间
          ]
query_res = requests.get("https://catalogue.dataspace.copernicus.eu/odata/v1/Products?"
                         f"$filter={' and '.join(filters)}&"
                         "$orderby=ContentDate/Start&"# 按开始时间排序
                         "$top=1000").json()['value']

query_res 为一个列表,包含每一景查询到的数据信息,每一景信息为一个字典,结果如下:

4 绘制查询结果范围

代码语言:javascript
复制
from gma.map import inres, plot
import numpy as np

## 读取省、市图层
shi = io.ReadVector('T2024年初地级.shp')
sheng = io.ReadVector('T2024年初省级.shp')

## 将影像范围 wkt 字符串转换为 gma 要素(Feature)
fts = [io.CreateFeature(d['Footprint'].split(';')[-1]) for d in query_res]

## 根据查询的得到的数据范围,设置一个绘图范围
bous = np.array([ft.Boundary for ft in fts])
extent = bous[:, 0].min() - 2, bous[:, 1].min() - 1, bous[:, 2].max() + 2, bous[:, 3].max() + 1

## 绘制查询结果范围
MapF = plot.MapFrame(BaseMapProj = 3857, Extent = extent)

### 添加所有查询结果
for ft in fts:
    mft = MapF.AddFeature(ft, FaceColor = 'lightgreen', alpha = 0.1)

### 添加省市县图层   
mly1 = MapF.AddLayer(xian, FaceColor = 'none', LineColor = 'lightgray', LineWidth = 0.1)
mly2 = MapF.AddLayer(shi, FaceColor = 'none', LineColor = 'darkgray', LineWidth = 0.2)
mly3 = MapF.AddLayer(sheng, FaceColor = 'none', LineColor = 'black', LineWidth = 0.3)

mly4 = MapF.AddLayer(ly, FaceColor = 'none', LineColor = 'blue', LineWidth = 0.3)

### 添加查询输入图层
mly4.AddLabel("宜阳县", Font = 'SimSun', FontSize = 5, FontColor = 'blue')

### 添加经纬网和地图框
lines = MapF.AddGridLines(LONRange = (100, 130, 2), LATRange = (26, 46, 2))
frame = MapF.SetFrame()

可见查询结果范围正常,均有包含宜阳县的区域。

5 下载数据

注:下载数据需要账号

代码语言:javascript
复制
## 根据用户账户获取 token
def get_access_token(username, password):
    token_https = 'https://identity.dataspace.copernicus.eu/auth/realms/CDSE/protocol/openid-connect/token'
    data = {"username":username,
            "password":password, 
            "grant_type":"password", 
            "client_id":"cdse-public"}
    
    r = requests.post(token_https, data = data)
    r.raise_for_status()
    return r.json()['access_token']

import tqdm

## 下载数据
### 下载地址的基础 url 模版
url = "https://download.dataspace.copernicus.eu/odata/v1/Products(%s)/$value"
out_path = r"D:\下载"# 文件保存路径
chunk_size = 8192# 下载时分块大小

for i, d in enumerate(query_res):

    Id = d["Id"]
    name = d["Name"]

    out_file = f"{out_path}\\{name[:-5]}.zip"
    if os.path.exists(out_file):
        print(f'跳过已存在的下载({i + 1}/{len(query_res)}):{out_file}')
        continue

    ## token会失效,每次获取一个避免失效(反正数据很大每一个数据也要下载很长时间)
    access_token = get_access_token("你的用户名", "你的密码")
    
    headers = {"Authorization": f"Bearer {access_token}"}
    session = requests.Session()
    session.headers.update(headers)
    
    data_url = url % Id
    response = session.get(data_url, stream=True)
    ##

    if response.status_code == 200:
        ## 创建进度条
        print(f'当前下载({i + 1}/{len(query_res)}):{out_file}')
        total_size = int(response.headers.get('content-length', 0)) # 数据总大小
        total = int(np.ceil(total_size / chunk_size)) # 分块数量
    
        with open(out_file, "wb") as file: # 分块下载
             for chunk in tqdm.tqdm(response.iter_content(chunk_size = chunk_size), total = total):
                 if chunk:
                     file.write(chunk)
    else:
        print(f"Error: {response.status_code}. {response.text}")

下载过程示例:

下载结果示例:

END

声明:欢迎转载、转发。气象学家公众号转载信息旨在传播交流,其内容由作者负责,不代表本号观点。文中部分图片来源于网络,如涉及内容、版权和其他问题,请联系小编处理。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-12-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 气象学家 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 申请一个 Copernicus 账号
  • 2 配置 Python 依赖
  • 3 查询数据
  • 4 绘制查询结果范围
  • 5 下载数据
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档