动机
Google earth engine 虽然解决了很多数据下载的问题,使数据的下载和处理变的快捷,但是如果想深入了解任何卫星的数据及信息,我个人感觉还是需要下载下来看一看。不为别的,就当涨涨眼界,如果博士毕业,连Sentinel、Modis等基本原始数据都没用过、处理过,有点丢人。尤其是如果公司或者研究所需要完全独立的做一个数据生产的系统,要求数据的实时性,那就不能嫁接Google earth engine的基功能了。我个人认为多涉猎还是非常有必要的。写此博客,留做笔记。 以此为出发点,并依据相关项目及老师的需求,写了此代码,基于 sentinelsat 的Sentinel-2数据下载。解决了 LongTermArchive 下载的问题。提示:以下是本篇文章正文内容,案例可供参考
正文
参考了很多网上的帖子,包括 知乎 和 CSDN,一直没找到解决 LongTermArchive 半个小时访问一次的问题,代码跑着跑着就断了,很头疼。
最终,仔细研读 sentinelsat 官方文档 https://sentinelsat.readthedocs.io/en/latest/api_overview.html#opensearch-example
,明白了怎么回事,然后在官方示例上进行了修改。完成了任务。
还有人在帖子中 'https://apihub.copernicus.eu/apihub'
写成了 'https://scihub.copernicus.eu/apihub/'
,不知道是不是两个网站都可以,但是我的后者是下载不下来的。
代码里面都有注释,不明白的自己看。再有问题,就可以直接联系我了。尤其是我希望能有会 CESM或者CLM的小伙伴帮帮我。
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
@version: Anaconda
@author: LeYongkang
@contact: 1363989042@qq.com
@software: PyCharm
@file: Sentinel_Download
@time: 2021/9/04 0020 下午 9:23
参考文档:http://www.acgeospatial.co.uk/sentinelsat_demo/
"""
from sentinelsat import SentinelAPI, read_geojson, geojson_to_wkt
from datetime import date
import time
import datetime
import os
def download_sentinel_data(user_name,password,website,foot_print,start_date,end_date,platformname,max_cloud):
print("进入函数")
download_dir = "./sentinel-2"
# 判断下载文件夹在不在,如果不在,自动建立子目录
if not os.path.exists(download_dir):
os.makedirs(download_dir)
api = SentinelAPI(user_name,password,website)
products = api.query(
foot_print,
date=(start_date, end_date),
platformname=platformname, # 可选: Sentinel-1,Sentinel-2,Sentinel-3,Sentinel-5 Precursor
producttype = 'S2MSI2A', # Sentinel-2 可选: S2MSI2A,S2MSI1C, S2MS2Ap
cloudcoverpercentage = (0, max_cloud)
)
print(len(products))
while True:
for product in products:
product_info = api.get_product_odata(product)
# print(product_info)
# 获取文件 id ,通过 id 号下载文件
product_id = product_info['id']
# 获取文件 title,title + .zip 为完整的文件名
product_title = product_info['title']
print("{}".format(product_id))
print("{}".format(product_title))
product_info = api.get_product_odata(product_id)
is_online = product_info['Online']
# 判断是否在线
if is_online: # 如果在线,执行
print('编号为 {} 的产品在线。'.format(product_id))
if not os.path.isfile(download_dir + os.sep + product_title + ".zip"): # 单账号的时候使用
print('本地无 {}.zip 的完整文件。'.format(product_title))
# if not os.path.isfile( download_dir + os.sep + product_title + ".zip.incomplete" ): # 双账号的时候
# print('本地无 {}.zip.incomplete 的未完成文件。开始下载'.format(product_title))
# 注意:上次下载一半,下次重启代码,循环到上次下载的文件时,会继续下载(接着.zip.incomplete继续下载)
api.download(product_id,directory_path= download_dir)
else: # 如果不在线,需要触发一次,然后跳过,(出发后,会在半小时后转化为在线)等待后续再下载
print('编号为 {} 的产品不在线。'.format(product_id))
if not os.path.isfile(download_dir + os.sep + product_title + ".zip"): # 单账号的时候使用
print('本地无 {}.zip 的完整文件,尝试触发 LongTermArchive 库'.format(product_title))
try: # 尝试触发
api.download(product_info['id'], directory_path= download_dir)
api.trigger_offline_retrieval(product_id)
break # if successful, move past
except Exception as e:
print("[ERROR] Request failed.. sleeping for 31 mins before retrying (current time: {})".format(
datetime.datetime.now()))
# time.sleep(60 * 31)
# 离线的 每 30 min 才能提交一次请求
time.sleep(60 * 31)
if __name__ == '__main__':
# 有时候单个账号访问次数多了,会限制访问,大约办个小时后解禁;限制访问的时候,可以使用另一个账号
# user_name="username"
# password = "password"
user_name="username"
password = "password"
website = 'https://apihub.copernicus.eu/apihub'
# map.geojson 限制了下载数据的范围
# 来 https://geojson.io/#map=2/20.0/0.0 网站,自己画个区域就行;然后 copy 到 map.geojson里面就可以
foot_print = geojson_to_wkt(read_geojson(r'./map.geojson'))
start_date = '20210813'
end_date = date(2021, 9, 13) # 这样的 2021-09-13 格式
print(end_date)
# 下载的数据类型
platformname = 'Sentinel-2'
# 控制云量最大值
max_cloud = 30
# print("test")
download_sentinel_data(user_name, password, website, foot_print, start_date, end_date, platformname,max_cloud)
结语
慢慢积累,不知不觉我的博客已经18个了,这个时第19个。