恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Esri 2020全球土地覆盖数据下载全攻略:分幅规则、工具原理与避坑指南
首页
资讯中心
/
Esri 2020全球土地覆盖数据下载全攻略:分幅规则、工具原理与避坑指南
Esri 2020全球土地覆盖数据下载全攻略:分幅规则、工具原理与避坑指南
发布时间:2026/10/2 19:15:52
1. 从 Esri 2020 全球土地覆盖数据说起它到底是什么先交代一个背景Esri 在 2020 年发布了一版10米分辨率全球土地覆盖数据这几乎是目前公开可下载的、全球尺度下分辨率最高的一套地表分类产品。所谓“土地覆盖”Land Cover简单理解就是地球表面那一层“穿的衣服”——是森林、草地、农田、水体还是水泥建筑、裸地、冰雪。这套数据把全球地表分成了 10 个大类用 10 米像素一格一格地标注出来。可能有人会问10 米分辨率是什么概念Landsat 卫星影像通常是 30 米分辨率Sentinel-2 影像最高到 10 米。Esri 这套数据就是基于 Sentinel-2 影像做出来的所以它天然继承了 10 米的空间粒度。相比过去常用的 300 米分辨率如 ESA 的 CCI-LC或 500 米分辨率如 MODIS 土地覆盖产品Esri 这版数据能把一条乡间道路的宽度、一片小水塘的形状、一个村庄的房顶边界都隐约表达出来。对于区域尺度的规划、生态评估、农业监测、自然地理分析来说这个精度带来的信息量提升是跨越式的。不过光知道数据存在还不够真正的痛点是怎么把它弄到本地。这套数据全球分幅、每个文件动辄几十 MB 到几百 MB如果不知道下载规则很容易被文件列表、路径规则、波段格式绕晕。这篇文章想做的就是把 Esri 2020 10m 全球土地覆盖数据的下载思路、文件组织规律、常见坑位和处理建议一次说透给接下来要做分析的同学铺一条能直接走的路。这套数据对内行是分析利器对外行可能就是一个“听起来很厉害的东西”。所以我会先从数据组成和下载机制讲起再逐步深入到底层文件规律、预处理技巧和实际踩坑经验尽量让零基础的人也能顺藤摸瓜把数据拿到手。2. Land Cover Downloader 下载器原理为什么不能靠“打开网页另存为”搞定2.1 数据下载的本质不是一张图而是分幅瓦片集合很多人第一次接触 Esri 全球土地覆盖数据时脑海里想的是一张大图放在网页上点一下就能下载整个 tif。但实际不是这样。全球 10 米分辨率的影像如果拼成一张完整栅格数据量会膨胀到 TB 级别。单机直接下载整块数据既不现实也没必要。Esri 的解决方案是把全球按规则网格切分成若干分幅tile每幅是一个独立的 GeoTIFF 文件通过一个公开的元数据清单对外提供访问地址。用户需要根据自己关心的区域范围挑出对应的分幅逐个下载。Land Cover Downloader 这类工具做的事情本质上就是把这个“挑分幅”的过程自动化给它一个研究区范围shp 或 GeoJSON它从全局网格索引里筛出相交的分幅编号再拼接出每个文件的下载链接批量拉取到本地。2.2 下载器的三种技术路线ArcGIS 工具、Python 脚本、直接拼 URL目前获取 Esri 2020 土地覆盖数据主要有三条路第一条路Esri 官方提供的 ArcGIS Pro 工具。这是最省事的方式。在 ArcGIS Pro 里打开 Catalog找到 Land Cover Downloader 工具输入一个范围工具会自动计算所需瓦片并下载还能顺便做镶嵌和裁剪。缺点是依赖商业软件授权而且在大范围下载时ArcGIS 的脚本执行进度提示有时不太友好中途断了不容易续传。第二条路自己写 Python 脚本。这个做法最灵活。利用 Esri 公开的文件清单一个包含全球所有分幅文件名和下载路径的 CSV / 文本清单结合 geopy 或 pyproj 做范围判断再用 requests / urllib 批量下载。脚本写好后可以重复使用也能控制断点续传、并发数、日志记录适合下载量大、需要稳定复现的场景。第三条路直接拼 URL 下载。如果你只需要一两幅数据其实根本不需要下载器。只要知道分幅的命名规则就能直接构造出下载链接用浏览器或命令行工具下载。这个规则我在下一节详细展开。从我的实际经验看下载几十幅以内的数据第三条路加 Python requests 循环就能解决下载一个省级行政区动辄几百上千幅则最好用第二条路加上多线程和断点续传逻辑否则等着急人。2.3 为什么很多人下载失败范围判断坐标系和文件清单不匹配有一个坑值得单独拎出来说Esri 全球土地覆盖瓦片的索引网格基于Web Mercator 网格EPSG:3857或者特定的地理网格组织而很多人的研究区 shp 是WGS84 经纬度EPSG:4326。如果脚本里直接用经纬度范围去匹配分幅编号大概率会漏掉边界上的瓦片或者匹配到错误的分幅。下载器的核心逻辑里第一步几乎总是“把研究区边界转换到目标网格坐标系下再求相交关系”。手动拼 URL 的时候也一定要先搞清楚目标区域对应的行列号落在哪个经纬度区间不能拿本地的投影坐标系坐标直接去套。另外Esri 官方在 2021 年后对数据托管服务做过一轮调整早期的部分链接已经失效。现在网上流传的不少博客里的 URL 模板是旧的照着下载会得到 404 或空文件。最稳妥的做法是去 Esri Living Atlas 或者官方发布页面找到当前版本的文件清单再基于这个清单去批量下载。3. 全局文件命名规则与分幅编号规律看懂路径才能精准定位3.1 文件命名规则拆解Esri 2020 土地覆盖数据的下载链接里文件名并不是随意取的它遵循一套严格的行列编号逻辑。官方文件清单里会出现类似这样的路径结构landcover_2020_10m_epsg4326/10m/landcover_2020_10m_epsg4326_N30E110.tif拆开来看landcover_2020_10m_epsg4326表示数据主题、年份、分辨率、坐标系。这里的 epsg4326 说明文件本身是 WGS84 经纬度坐标的 GeoTIFF。N30E110这是分幅编号含义是覆盖范围从北纬 30 度到下一个网格边界、东经 110 度到下一个网格边界。换句话说N 后面的数字是分幅左下角的纬度起始值E 后面是经度起始值。具体到经纬度跨度不同数据版本可能不太一样。Esri 2020 版常见的分幅是20度 x 20度的网格也就是说N30E110这幅图覆盖的是北纬 30°-50°、东经 110°-130° 的范围。在赤道附近20 度经度跨度的实际地表宽度约 2000 多公里在高纬度地区同样经度跨度对应的地表宽度会明显缩小所以每个分幅的数据量在大陆区域相对均匀但在极区会有文件大小差异。如果你要下载中国大部分地区关注的编号大致会落在N00E070到N50E140这个区间。具体要看你的范围边界不能一刀切。3.2 利用文件清单批量筛选官方发布页通常会提供一个包含全部分幅文件信息的索引文件。这个索引可能是 CSV、TXT或者是 ArcGIS 的 JSON 元数据。重点字段有分幅名称如N30E110最小经度、最大经度、最小纬度、最大纬度文件大小下载 URL假设你要下载黄河流域的范围可以先读取研究区 shp 的边界算出外包矩形然后跟索引里的每个分幅外包矩形做相交判断。相交的方式不复杂就是判断两个矩形是否有重叠min_lon max_lon_region and max_lon min_lon_region这条判断对经度要做 360 度环绕处理的特殊区域需要小心但在大部分业务场景里直接用上述逻辑就够了。判断完之后把命中的分幅 URL 列表输出到 txt再用下载脚本逐个拉取。这样做的好处是范围变化时只需重新跑一遍筛选脚本不用手动改下载清单。3.3 一个具体例子下载中国东部某区域假设研究区大致是东经 115°-122°、北纬 30°-36°。按照 20 度网格切分会命中以下几幅N20E100覆盖北纬 20-40、东经 100-120N20E120覆盖北纬 20-40、东经 120-140N40E100覆盖北纬 40-60、东经 100-120N40E120覆盖北纬 40-60、东经 120-140注意N40E100和N40E120这两幅在高纬度区域可能只覆盖目标范围的一小部分但为了后续拼接不漏缝隙必须一并下载。很多人在这一步自作聪明只下载中心分幅结果镶嵌时发现研究区边缘缺一块得重新回头补文件非常耽误时间。如果目标区域正好跨越经度 180 度线比如太平洋岛屿分幅编号会出现N00E170、N00E-179之类的边界情况筛选脚本里要额外处理负经度和跨日期变更线逻辑。这个我后面在避坑章节再细讲。4. 实操下载流程从研究区准备到批量拉取的完整链路4.1 步骤一准备研究区范围文件不论用哪种下载方式先准备一个范围文件是必须的。推荐用 GeoJSON 或 Shapefile坐标系用 WGS84 经纬度。如果你手里的范围是投影坐标系比如 CGCS2000 / 3-degree Gauss-Kruger zone 35建议先用gdaltransform或者 QGIS 里的“导出 - 另存为”转成 EPSG:4326。这里有个细节如果你的研究区是县级、乡镇级小范围其实直接下载范围外包矩形对应的分幅再裁剪即可。但如果是省级大范围镶嵌出来的文件会非常大建议按“分幅下载 - 按分幅裁剪 - 再镶嵌”的顺序处理而不是“先镶嵌全部 - 再裁剪”。原因是 10 米分辨率影像一景可能几个 GB全部镶嵌再裁剪对内存的压力极大。4.2 步骤二确定需要下载的分幅编号编写一个简单脚本读取索引文件做矩形相交判断。下面是一个很简化的 Python 示例import json # 假设索引文件是 JSON里面每个元素有 bbox 和 url 字段 with open(esri_landcover_index.json, r) as f: index json.load(f) # 研究区外包矩形WGS84 region_bbox [115.0, 30.0, 122.0, 36.0] # min_lon, min_lat, max_lon, max_lat selected [] for item in index: tile_bbox item[bbox] # [min_lon, min_lat, max_lon, max_lat] min_lon max(region_bbox[0], tile_bbox[0]) min_lat max(region_bbox[1], tile_bbox[1]) max_lon min(region_bbox[2], tile_bbox[2]) max_lat min(region_bbox[3], tile_bbox[3]) if min_lon max_lon and min_lat max_lat: selected.append(item[url]) with open(download_urls.txt, w) as f: f.write(\n.join(selected)) print(f需要下载的分幅数量: {len(selected)})这段代码没有用任何 GIS 库只做矩形相交判断足够应付大多数场景。如果你需要更精确的相交判断比如研究区是不规则多边形而矩形边角覆盖了大量无关区域可以用 shapely 的box和Polygon.intersects方法原理是一样的。4.3 步骤三并发下载与断点续传得到 URL 列表后不建议用 requests 裸循环一个个下那样速度慢且容易中断。我常用的是aria2c加多线程下载或者 Python 的concurrent.futures requests 分片下载。命令行最简单的方式aria2c -i download_urls.txt -d ./landcover_tiles --max-connection-per-server4 --split4 --continuetrue --auto-file-renamingfalse--continuetrue是关键它能保证某个文件下载到一半断网后重新执行命令会从断点继续而不是从头再来。这在大数据量下载时能救命。如果是用 Python 脚本下载建议加上重试机制。遥感和土地覆盖分幅文件放在对象存储上偶发 503、超时很常见。一个简单的重试装饰器如下import time import requests def download_with_retry(url, save_path, retries3): for i in range(retries): try: r requests.get(url, streamTrue, timeout60) r.raise_for_status() with open(save_path, wb) as f: for chunk in r.iter_content(chunk_size8192): f.write(chunk) return True except Exception as e: print(f下载失败: {url}, 重试 {i1}/{retries}, 错误: {e}) time.sleep(2 ** i) return False4.4 步骤四校验文件完整性下载完成后别急着进入分析阶段。检查每个 GeoTIFF 是否能正常打开、是否与索引里记录的文件大小一致是非常必要的环节。尤其在网络不稳定的情况下文件下载到 99% 时断掉但状态码 200 的情况也是有的。快速校验方式gdalinfo /path/to/tile.tif | grep -E Size is|Coordinate System或者用 Python 的 rasterio 打开检查import rasterio with rasterio.open(landcover_2020_10m_N30E110.tif) as src: print(src.width, src.height, src.crs, src.dtypes)如果文件损坏rasterio 打开时会直接报错这时重新下载对应分幅即可。5. 预处理与常用分析思路拿到数据之后该怎么做5.1 镶嵌、裁剪和重投影下载得到的是分幅数据做区域分析前通常需要三件套镶嵌、裁剪、重投影。镶嵌常用gdal_merge.py或gdalbuildvrtgdalbuildvrt -resolution highest -r nearest -srcnodata 0 -vrt landcover.vrt $(cat tile_list.txt) -overwrite gdal_translate -projwin 115 36 122 30 -co COMPRESSLZW landcover.vrt landcover_studyarea.tif其中-projwin的坐标顺序是min_lon max_lat max_lon min_lat很多人容易搞反导致输出是一张上下颠倒或空的图。用gdal_translate直接裁剪时不需要先做全局镶嵌VRT 文件可以认为是一个虚拟镶嵌它不实际复制像素只在读取时才动态拼接速度很快内存占用也小。重投影不一定需要因为数据本身是 WGS84 经纬度。但如果你的分析涉及面积统计、距离计算建议投影到适合研究区的等积投影或 UTM 分区。面积统计用 WGS84 经纬度直接算会带来较大误差这点在后续矢量化和统计时尤其明显。5.2 类别编码与数值含义Esri 2020 土地覆盖数据采用的分类体系一共 10 类像素值从 1 到 10具体如下类别编号含义典型示例1水体海洋、河流、湖泊、水库2树木常绿/落叶阔叶林、针叶林3草地天然草地、草甸4被淹植被湿地、沼泽、红树林5农作物耕地、水田、旱地6灌木/灌丛矮灌木丛、灌草丛7建筑/建成区房屋、道路、城镇、工业区8裸地沙地、戈壁、裸岩9雪/冰冰川、永久积雪10云/空值等云遮挡、无效检测在实际分析前建议先对研究区做一次类别分布直方图用来发现数据覆盖异常。比如某个不该有大面积云的区域出现了大量类别 10那就要考虑是否下载到了质量较差的分幅或者该区域原数据本身就存在云污染。5.3 三种常用分析思路从拿到数据到产出价值常见分析方向有这么几类方向一土地覆盖分类统计。统计各类别面积及占比做区域结构分析。注意在投影坐标系下统计且不同类别像素大小在不同纬度会因投影变形产生差异必须用投影后的真面积。方向二土地覆盖变化检测。如果你想对比 Esri 2020 数据和 2010 年前后的 GlobeLand30 数据由于分类体系不完全一致需要先重分类对齐再比较否则直接做变化检测会产生大量系统性误差。方向三生态指标计算。比如计算一个区域的森林覆盖率、不透水表面比例、湿地比例等。这类指标通常直接从分类结果做窗口统计或地块聚合即可得到。这些都是后续分析的内容不是本文重点但既然千辛万苦把数据下载下来多少要知道下一步能做什么免得停在“数据在手却无从下手”的状态。6. 最容易踩的五个坑与排查思路绕开这些比会下载更重要6.1 坑一文件清单版本和下载脚本不匹配网上关于 Esri 土地覆盖下载的代码很多但很多是 2021 年甚至更早写的。Esri 在此期间更新过数据托管路径部分文件名前缀变了比如早期的ESA_10m_landcover字样和现在的landcover_2020_10m_epsg4326字样并不一致。如果你拿着旧脚本直接替换 URL 里的域名可能仍然失败因为路径层级也变了。排查思路不要依赖任何固定 URL 模板直接去 Esri 官方发布页下载最新的索引文件用索引里的 URL 作为唯一事实来源。6.2 坑二下载时忽略范围相交的边界瓦片我在前面已经提过这个问题。再来一个具体案例研究区是北京市经纬度跨约东经 115.4°-117.5°、北纬 39.4°-41.6°。按照网格边界这个范围会落在N20E100、N20E120、N40E100、N40E120四幅里但你实际真正需要的内容可能只占N20E120和N40E120的一小角。如果脚本只筛选“中心点落在范围内”的瓦片很可能漏掉N40E100那一幅导致后续镶嵌时无法覆盖西北角。解决办法用外包矩形相交判断而不是用中心点判断。宁可多下载一两幅也不要漏。6.3 坑三跨经度 180 度线的范围处理这算是一个进阶坑。如果研究区跨越 180 度经度比如包含斐济等太平洋岛国的范围经度范围可能表示为177°E ~ -178°W也就是外包矩形从左到右跨越了 180 度线。如果直接按常规最大最小值判断程序会认为最小经度是 -178最大经度是 177导致完全没有相交。排查思路如果max_lon min_lon说明研究区跨零点需要拆分判断或把经度统一转成 0-360 度制再判断。 Esri 分幅编号里也会出现E-179之类的负值表示处理起来比较烦建议单独写一套分支逻辑。6.4 坑四GDAL 读取时碰到 NoData 值导致的异常像素土地覆盖数据经过压缩和地理处理某些分幅边缘会出现 NoData 或 0 值。镶嵌时如果未正确设置-srcnodata这些值会被当作真实类别 0 参与后续统计而类别 0 在本分类体系里并不存在最终统计结果会出现一个莫名其妙的神秘类别。排查思路在镶嵌和计算直方图之前先检查每个分幅的 NoData 元数据gdalinfo tile.tif | grep -i nodata统一设置-srcnodata 0或者将其标记为 NoData避免污染统计结果。6.5 坑五大面积云/阴影遮挡导致分类质量假象Esri 的土地覆盖数据虽然是 2020 年产品但某些区域受 Sentinel-2 云覆盖影响部分类别值可能不准确。这类问题不会在下载环节暴露但会在你后续建模时变成隐藏的噪声来源。一个务实的排查方法下载后先用 QGIS 或 ArcGIS 随机抽查几个典型地物点对照同期的高分影像判断分类是否合理。比如某个区域在影像上明显是林地但土地覆盖数据里显示为草地说明该瓦片可能存在分类错误或者混合像元问题需要在分析中标注为低置信区域。7. 下载工具对比与进阶建议选对路子省一半时间7.1 工具对比我把常用方案放在一起做个对比方便你按自己条件选择方式优点缺点适用场景ArcGIS Pro Land Cover Downloader操作简单有界面自动镶嵌需要商业授权定制能力弱个人或小团队快速使用Python 脚本手动下载灵活可复用支持断点续传需要自己写代码和排错有一定开发能力、需频繁下载aria2c 命令行速度快并发强支持续传需要文件清单和一定命令行基础大批量下载首选直接浏览器下载不用额外依赖只适合几个文件效率极低验证一次、只下少量数据从我个人的偏好来说主力方案永远是 Python 筛选 URL aria2c 多线程下载。Python 负责“选哪些文件”aria2c 负责“高速拉到本地”两者配合非常顺手。7.2 高级进阶断点续传和内存缓存的搭配如果你下载的分幅数量超过 1000 个建议在脚本里加入“已下载列表记录”机制。每次下载前检查文件是否已存在且大小符合预期避免重复下载浪费流量。伪代码思路import os expected_sizes {url: size for url, size in size_map.items()} done_file downloaded.txt downloaded set() if os.path.exists(done_file): with open(done_file) as f: downloaded set(line.strip() for line in f) for url in selected_urls: file_name url.split(/)[-1] if file_name in downloaded and os.path.exists(file_name): if os.path.getsize(file_name) expected_sizes[url]: continue download_with_retry(url, file_name) with open(done_file, a) as f: f.write(file_name \n)这套逻辑跑起来中途关了重开只会补下没完成的文件非常省心。7.3 数据更新的应对思路Esri 每年可能推出新版本土地覆盖数据下载器的工作逻辑基本不变变的只是索引清单和 URL 前缀。所以更推荐把“下载器”写成一个通用工具把索引文件路径作为参数传进去而不是把 URL 硬编码在脚本里。这样到了 2021、2022、2024 版本发布时你只需要换一份索引脚本继续沿用几秒钟就能切换到新数据。8. 个人实操体会下载整省数据的全过程复盘最后分享一次我下载一个省份全部瓦片的经历算是给上面的内容做个综合印证。当时要下载四川省全境的 Esri 2020 土地覆盖数据范围跨度约东经 97°-109°、北纬 26°-35°。按 20 度网格判断理论上只要下载N20E80、N20E100、N40E80、N40E100四幅即可覆盖全省但实际因为网格边界和行政区边界的错位我又额外增加了一幅N20E120总共五幅才保证如果后续要扩展周边缓冲区不会出缝隙。五幅 GeoTIFF 加起来接近 12 GB家里网络上传下载速度 50 Mbps跑了大概 40 分钟。下载过程中出现了一次 503、一次单文件校验失败分别靠重试机制和重新下载单独文件解决。拿到数据后我先是建 VRT然后用研究区矢量范围做精确裁剪。因为四川西部高山区有大量裸地和雪盖分类统计结果里类别 8、9 的占比比想象中高后来对照影像确认是真实地表状态数据本身没有问题。唯一遗憾是部分川西地区有云的像素被标成了类别 10占比大概 2% 左右做面积统计时需要做插值或标记处理。整个过程验证了一个判断Esri 2020 10m 土地覆盖数据在精度和实用性上确实能顶到大区域分析的需求但数据获取和预处理的整洁度直接决定了后续分析的可靠程度。下载器不是花架子真正考验人的是对文件组织规律、坐标系逻辑和异常情况的处理能力。如果现在的你正准备下载这套数据我的建议很简单先花半小时把索引文件的结构吃透再写一个几十行的筛选脚本然后用 aria2c 多线程拉取。第一次跑通后你会觉得整个流程异常顺畅后面无论是换区域还是换年份都只是换一份索引的事。