python批量下载modis数据(可筛选日期、范围、数据类型)

找了一圈下modis数据的,有的不能空间筛选有的不能下初级产品(也可能没找到),不甚满意,自己搞了个

23年2月3日更新,原文章里获取所有a标签的地址这一步可以替换为更新章节里直接通过接口获取了。

更新

感谢同事在LAADS的网站成功找到产品影像查询的api接口,省了之前解析页面啥的麻烦。
这里以一个查询接口为例
https://ladsweb.modaps.eosdis.nasa.gov/api/v1/files/product=MOD021KM&collection=61&dateRanges=2023-01-20…2023-02-03&areaOfInterest=x73.62y53.54,x134.76y20.23&dayCoverage=true&dnboundCoverage=true
在这里插入图片描述
location里选的中国,体现在areaOfInterest的参数值改了四次请求了四次。。。
再看下返回结果
在这里插入图片描述
该有的基本都有了,看到那个明晃晃的fileURL了吧,加上前缀和token就能下载了。具体方法根据下面的脚本自己改改吧。

更新+1

同事还找到个接口,可以获取缩略图
在这里插入图片描述

地址是
https://ladsweb.modaps.eosdis.nasa.gov/api/v1/imageFiles
post请求,参数是上面files接口获取的产品对象的key
在这里插入图片描述

返回的是缩略图相关的信息,很容易拼出来,而且不需要token
在这里插入图片描述
上图左侧图片的地址为:
https://ladsweb.modaps.eosdis.nasa.gov/archive/allData/61/MOBRGB/2023/020/MOBRGB.A2023020.0205.061.2023020165303.jpg
就是
前缀(https://ladsweb.modaps.eosdis.nasa.gov/)+接口返回的信息里的URL(/archive/allData/61/MOBRGB/2023/020)+返回信息里的FileName(MOBRGB.A2023020.0530.061.2023020164537.jpg)

0 前言

  • 用到的主要依赖是selenium,下载网站是https://ladsweb.modaps.eosdis.nasa.gov,环境是anaconda,python 3.9.12
  • 因为涉及html解析,若该网站结构变了,可能就得修改
  • 网站的#Online Archive里可以实现产品和日期筛选,但是不知道怎么进行空间筛选 ,如果可以的话能省很多事

1 安装selenium

需要的主要依赖是selenium,这个库用来模拟浏览器操作。该库的介绍见
https://blog.csdn.net/benzhujie1245com/article/details/117089767
除了库本身,使用它还需要

  1. 电脑安装了浏览器
  2. 安装对应的WebDriver

浏览器我用的chrome,以此为例。WebDriver的下载地址是
http://chromedriver.storage.googleapis.com/index.html
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

将下载的压缩包解压,exe文件找个地方放好就行了

2 注册账号获取token

地址是
https://urs.earthdata.nasa.gov/users/new
注册之后在搜索页右上角可以看token
在这里插入图片描述
在这里插入图片描述

3 下载脚本

import os
import shutil
import sys
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time

USERAGENT = 'tis/download.py_1.0--' + sys.version.replace('\n', '').replace('\r', '')


def geturl(url, out):
    """
    根据url下载文件
    :param url: 地址
    :param out: 存储路径
    :return:
    """
    headers = {'user-agent': USERAGENT, 'Authorization': 'Bearer ' + token}

    import ssl
    CTX = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)

    from urllib.request import urlopen, Request
    fh = urlopen(Request(url, headers=headers), context=CTX)
    shutil.copyfileobj(fh, out)


def init(url, chrome_driver):
    """
    初始化页面解析
    :param url: 网页地址
    :param chrome_driver: 浏览器驱动地址
    """
    chrome_options = webdriver.ChromeOptions()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')

    browser = webdriver.Chrome(executable_path=chrome_driver, chrome_options=chrome_options)
    # 设置隐式等待时间,等待页面完整加载,最长等待 60s
    browser.implicitly_wait(60)
    browser.get(url)

    try:
        # 等待下载标签加载,最长60s
        elements = WebDriverWait(browser, 60).until(
            EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "#tab4FilesTable a")))
        wait_a_list(0, len(elements), browser)
    finally:
        browser.quit()


def wait_a_list(times, len_a_list, browser):
    """
    递归等待下载标签全部加载
    :param times: 循环累计次数
    :param len_a_list: 下载标签长度
    :param browser: browser
    """

    # 强制等待 2s 后再执行下一步
    time.sleep(2)
    elements = browser.find_elements(By.CSS_SELECTOR, "#tab4FilesTable a")

    if len(elements) == len_a_list:
        times += 1
        if times == 5:
            print('等待5次,长度不变,输出最终')
            for my_elem in elements:
                url = my_elem.get_attribute("href")

                file_name = url.split('/')[-1]
                path = os.path.join(save_dir, file_name)

                if not os.path.exists(path):
                    print('downloading: ', path)
                    with open(path, 'w+b') as fh:
                        geturl(url, fh)
                else:
                    print('skipping: ', path)

        else:

            print('长度不变,循环次数:' + str(times))
            wait_a_list(times, len_a_list, browser)
    else:
        print('长度重置,现在长度:' + str(len(elements)))
        wait_a_list(0, len(elements), browser)


if __name__ == '__main__':
    # token https://ladsweb.modaps.eosdis.nasa.gov/ 注册后获取
    # 如果不设置token,下下来的会是一个让你登录的html页面。。
    token = '你的token'
    # 存储路径
    save_dir = './dataDirectModis'
    # 下载地址
    _url = 'https://ladsweb.modaps.eosdis.nasa.gov/search/order/4/MOD021KM--61/2023-01-17..2023-01-18/DB/Country:CHN'
    # selenium的chromedriver驱动地址
    _chrome_driver = 'D:/Program Files/chromedriver.exe'

    init(_url, _chrome_driver)

4 脚本解释

4.1 下载地址

下载地址是按照LAADS网站一步步查询拼出来的
在这里插入图片描述
筛选主要分四步,这里简单介绍。如果你一步步筛选到第四步,你会发现之前的筛选项都体现在了url里。

  1. 产品
    就上图那些,左边是分类,右边是具体的产品,可多选

  2. 时间
    在这里插入图片描述
    都很明了,不多说了

  3. 空间
    在这里插入图片描述

  4. 文件
    根据上述选择列出的所有文件。手动下载的话,这里就可以选择然后进入第五步了。
    在这里插入图片描述

再看一下代码里这一段

# 下载地址
    _url = 'https://ladsweb.modaps.eosdis.nasa.gov/search/order/4/MOD021KM--61/2023-01-17..2023-01-18/DB/Country:CHN'

明显看出刚才的选项都体现在了url里。拿页面上的url来看
在这里插入图片描述
大家可以在第三步换不同的空间筛选种类试试。矩形的话就是两个坐标,国家的话就是国家代码。

4.2 页面解析

进行到第四步,出现的表格就已经可以直接下载了
在这里插入图片描述
写个脚本,读出表格,点击下载,岂不轻轻松松
然而问题是,页面加载本身就不快,然后表格是页面元素渲染完成后才出现的,而且数据也不是全部加载好再渲染而是一条一条出现,一个处理不好就会下不全。

  1. 先等待页面加载
    selenium的几种等待见官网文档介绍
    https://selenium-python.readthedocs.io/waits.html

        # 设置隐式等待时间,等待页面完整加载,最长等待 60s
        browser.implicitly_wait(60)
    
  2. 然后等待表格第一行下载标签出现

            # 等待下载标签加载,最长60s
            elements = WebDriverWait(browser, 60).until(
                EC.visibility_of_all_elements_located((By.CSS_SELECTOR, "#tab4FilesTable a")))
    
  3. 递归判断所有行加载完
    主要就是代码里的wait_a_list函数,作用是等待2秒后再获取一遍列表下载标签,若和上一次不同,则清空循环次数再来一次,若相同,带着循环次数递归,直到连续五次没有新增行,执行下载
    在这里插入图片描述

4.3 根据url下载文件

在这里插入图片描述
这部分,遍历所有获取到的< a >标签,读取href属性(即文件下载地址),分割出文件名,和存储路径一起构建文件地址,若文件存在就跳过,文件不存在就通过geturl函数写入数据。

geturl函数是根据官网脚本大力删改之后的(完整版见该文章),因为我不需要各种判断和异常抛出,我的环境自己有数。token,USERAGENT都是在这一步放入请求头里的,urlopen的context参数也是,上述几个地方简易保持原样不要改,搞不好就会下下来一个20k的垃圾文件=_=

最后

如果运行过程中遇到什么奇怪错误,可以先自行百度。我记得好像碰到过啥小问题,搜了一下降低了某个库的版本就好了。这种依赖相关的问题每个人环境不一样,碰到的也不同,问我也没用。

参考
https://blog.csdn.net/NingAnMe/article/details/103461808
https://ladsweb.modaps.eosdis.nasa.gov/search/
https://selenium-python.readthedocs.io/api.html

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值