1.问题描述
2.下载思路
3.源码
4.结果
建了一个QQ群,大家可以在里边聊聊水色遥感数据下载和数据处理方面的事情:1087024529
Sentinel数据(包括1,2,3)是质量较好的开源遥感数据。当利用Sentinel数据做时间序列问题时,就会出现一个问题:欧空局(ESA)考虑数据可用容量,采取了将Sentinel数据从在线存档中删除,但在长期存档中可用的功能。当我们遇见长期存档的数据时,在检索框中会出现一个offline标示。你可以去激活它,然后下载(激活后需要等待一段时间)。一个用户在半个小时内只能申请激活一幅影像(从offline变为online)。关于这个问题可以参考官方的介绍:https://scihub.copernicus.eu/userguide/LongTermArchive
现在,就出现一个问题,如果我需要的offline数据较多,我该如何方便的进行下载呢?接下来,就介绍如何使用sentinelsat包和IDM批量下载offline的sentinel数据。
ESA提供了一个很好的Python库,叫做:sentinelsat。使用这个库可以检索和下载sentinel数据。如果是online数据,使用download函数就可以直接下载;如果是offline数据,download函数会对该数据进行激活。其中sentinelsat的帮助文档提供了一个下载offline数据的事例:https://sentinelsat.readthedocs.io/en/latest/。本博客并没有采取帮助文档里的方法,而是利用sentinelsat+IDM(Internet Download Manager)的方式进行下载。
你当然要先安装好IDM和sentinelsat
IDM下载链接:http://www.internetdownloadmanager.com/
sentinelsat安装方法:pip install sentinelsat
主要的下载思路如下:
2.1.首先获取到需要下载的数据的链接和ID号。可以参考博客:使用Python快速获取哥白尼数据开放访问中心购物车里的数据下载链接
2.2.设置循环,利用sentinelsat库的get_product_odata()函数,判断列表中的第一个数据是online数据还是offline数据;
get_product_odata() 函数返回一个字典,里边包括了所查询数据的信息,如文件名,是否为online,数据覆盖范围等
2.3.如果是online数据,那就将数据链接添加到IDM的下载列表中,并进行下一次循环。如何利用python调用IDM可以参考博客:Python调用IDM批量下载GOCI数据
2.4.如果是offline数据,那就使用download()函数对数据进行激活。并把该数据从列表的第一个位置删除,放在列表的最后一个位置。
2.5.在等待数据激活的时候,当然不能白白浪费时间。因为需要下载的数据,存在已经被别人激活的现象(如果你需要的数据有很多,可以请朋友用他的下载账号帮助你,对offline的数据进行激活)。所以需要对列表里的数据进行检查,是否还存在online数据,如果有的话,那就加入IDM进行下载。下载的数据,要在数据列表里将该数据的链接删除。
2.6.之后就是让程序重复完成上述步骤。
在程序运行之前,因为ESA对一个用户同时下载数据的数量有限制,因此需要设置一下IDM,设置步骤见:使用IDM批量下载Sentinel(哨兵)卫星数据
值得注意的时,通过命令行调用IDM的时候,只会把下载任务加入到主要下载队列(该问题我询问了IDM团队,他们说未来可能会优化该功能,使用命令行能将下载任务添加到指定的下载队列),所以要设置主要下载队列同时下载数据的数量。
下边就是主要的代码:
from subprocess import call
from sentinelsat import SentinelAPI
from datetime import date
import time
import xlrd
from tqdm import tqdm
IDM = "IDMan.exe" #你电脑中IDM的位置
DownPath='F:/Sentinel_offline/' #数据要下载的地址
api = SentinelAPI('ESA账号的账户名', '账号密码', 'https://scihub.copernicus.eu/dhus')
#用于读取数据的HTTP链接到列表中
filepath='HTTPandID.xlsx'
workbook = xlrd.open_workbook(filepath)
sheet1 = workbook.sheet_by_name('HTTP')
linklist=sheet1.col_values(0)
#开始下载
print('开始任务:..................')
n=0
while linklist:
print('---------------------------------------------------')
n=n+1
print('\n')
print('第'+str(n)+'次循环'+'\n\n')
id=linklist[0].split('\'')[1]
link=linklist[0]
product_info=api.get_product_odata(id)
print('检查当列表里的第一个数据:')
print('数据ID为:'+id)
print('数据文件名为:'+product_info['title']+'\n')
if product_info['Online']:
print(product_info['title']+'为:online产品')
print('加入IDM下载: '+link)
call([IDM, '/d',link, '/p',DownPath,'/n','/a'])
linklist.remove(link)
call([IDM,'/s'])
else:
print(product_info['title']+'为:offline产品')
print('去激活它')
api.trigger_offline_retrieval(id) #去激活它
print('检查任务列表里是否存在online产品: .........')
#等待激活成功的时候,检查现在的列表里还有没有online产品
#如果有online的产品那就下载
#首先检查列表中是否需要下载的数据
if len(linklist)>1:
#记录列表里可以下载的链接,并在最后把它们删除
ilist=[]
#开始寻找列表剩下的元素是否有online产品
for i in range(1,len(linklist)):
id2=linklist[i].split('\'')[1]
link2=linklist[i]
product_info2=api.get_product_odata(id2)
if product_info2['Online']:
print(product_info2['title']+'为在线产品')
print('ID号为:'+id2)
print('加入IDM下载: '+link2)
print('--------------------------------------------')
call([IDM, '/d',link2, '/p',DownPath,'/n','/a'])
#在列表中加入需要删除产品的HTTP链接信息
#直接在linklist中删除会linklist的长度会发生改变,最终造成i的值超过linklist的长度
ilist.append(link2)
else:
continue
#把已经下载的数据的链接给删除掉
if len(ilist)>0:
call([IDM,'/s'])
for il in ilist:
linklist.remove(il)
print('本轮次检查结束,开始等到40分钟')
#将该激活的产品删除,再加入到最后
linklist.remove(link)
linklist.append(link)
#两次激活offline数据的间隔要大于30分钟
for i in tqdm(range(int(1200)),ncols=100):
time.sleep(2)
下面是程序运行的结果截图:
如果加入IDM中的下载任务的文件名出现"$value",不用担心,之后它会自动变成数据的文件名。
开心下载吧!