使用sentinelsat包和IDM批量下载offline的sentinel数据

目录

1.问题描述
2.下载思路
3.源码
4.结果

建了一个QQ群,大家可以在里边聊聊水色遥感数据下载和数据处理方面的事情:1087024529

1.问题描述

Sentinel数据(包括1,2,3)是质量较好的开源遥感数据。当利用Sentinel数据做时间序列问题时,就会出现一个问题:欧空局(ESA)考虑数据可用容量,采取了将Sentinel数据从在线存档中删除,但在长期存档中可用的功能。当我们遇见长期存档的数据时,在检索框中会出现一个offline标示。你可以去激活它,然后下载(激活后需要等待一段时间)。一个用户在半个小时内只能申请激活一幅影像(从offline变为online)。关于这个问题可以参考官方的介绍:https://scihub.copernicus.eu/userguide/LongTermArchive
在这里插入图片描述
现在,就出现一个问题,如果我需要的offline数据较多,我该如何方便的进行下载呢?接下来,就介绍如何使用sentinelsat包和IDM批量下载offline的sentinel数据。

2.下载思路

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.之后就是让程序重复完成上述步骤。

3.源码

在程序运行之前,因为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)

4.结果

下面是程序运行的结果截图:
如果加入IDM中的下载任务的文件名出现"$value",不用担心,之后它会自动变成数据的文件名。
使用sentinelsat包和IDM批量下载offline的sentinel数据_第1张图片
开心下载吧!

你可能感兴趣的:(python,idm)