ArcGIS 页面中动态加载的 ZIP 文件批量下载完整教程

发布时间 - 2026-02-02 00:00:00    点击率:

本文详解如何正确抓取 arcgis 共享页面中通过 api 动态生成的 .zip 下载链接,并实现稳定批量下载,解决 beautifulsoup 无法解析 javascript 渲染内容的常见问题。

ArcGIS Online 页面(如 arcgis.com/home/item.html)通常不直接在 HTML 源码中硬编码下载链接,而是通过前端 JavaScript 调用 REST API 异步加载数据(例如要素服务、附件或元数据中的 URL 字段)。因此,使用 requests + BeautifulSoup 直接解析初始 HTML 将无法获取真实 ZIP 链接——这正是你遇到“打印 links 为空”和“无文件下载”的根本原因:目标链接根本不存在于静态 HTML 中,而是在后续 AJAX 请求返回的 JSON 数据里。

要成功下载,必须逆向分析页面的数据加载逻辑。以你提供的链接为例,其 ZIP 文件实际存储在 Azure Blob(如 dasc.blob.core.windows.net)中,URL 保存在 ArcGIS F

eature Service 的属性字段(如 "ContoursURL")中。正确路径是:

  1. 提取 item ID → 2. 调用 ArcGIS Sharing API 获取组织 ID → 3. 构造 FeatureServer 查询 URL → 4. 请求 JSON 数据并提取 ContoursURL 字段 → 5. 过滤并下载 .zip 文件

以下是可直接运行的增强版下载脚本,已整合错误处理、进度提示、目录自动创建与文件名安全处理:

import os
import re
import requests
from urllib.parse import urlparse, unquote

def extract_item_id(url):
    """从 ArcGIS item URL 中安全提取 ID"""
    match = re.search(r"id=([a-f0-9]{32})", url)
    if not match:
        raise ValueError("Invalid ArcGIS item URL: missing or malformed 'id' parameter")
    return match.group(1)

def download_zip_files(base_url, download_dir="downloads", max_files=100):
    os.makedirs(download_dir, exist_ok=True)

    # Step 1: Get item ID
    item_id = extract_item_id(base_url)
    print(f"✅ Extracted item ID: {item_id}")

    # Step 2: Get orgId via Sharing REST API
    api_url = f"https://www.arcgis.com/sharing/rest/content/items/{item_id}?f=json"
    try:
        resp = requests.get(api_url, timeout=10)
        resp.raise_for_status()
        data = resp.json()
        org_id = data["orgId"]
        print(f"✅ Retrieved orgId: {org_id}")
    except Exception as e:
        raise RuntimeError(f"Failed to fetch orgId: {e}")

    # Step 3: Query Feature Server for ZIP URLs
    feature_url = f"https://services1.arcgis.com/{org_id}/arcgis/rest/services/Statewide_Contours/FeatureServer/0/query"
    params = {
        "f": "json",
        "where": "1=1",
        "returnGeometry": "false",
        "outFields": "ContoursURL",
        "resultRecordCount": str(max_files),
        "orderByFields": "FID ASC"
    }

    try:
        resp = requests.get(feature_url, params=params, timeout=15)
        resp.raise_for_status()
        data = resp.json()

        if "features" not in data or not data["features"]:
            print("⚠️  No features found. Check service URL or permissions.")
            return

        zip_urls = []
        for feat in data["features"]:
            url = feat["attributes"].get("ContoursURL")
            if url and url.lower().endswith(".zip"):
                zip_urls.append(url)

        print(f"? Found {len(zip_urls)} ZIP URLs")

        # Step 4: Download each ZIP
        for i, url in enumerate(zip_urls, 1):
            try:
                # Safe filename from URL (handle encoded chars & paths)
                parsed = urlparse(url)
                filename = os.path.basename(unquote(parsed.path))
                filepath = os.path.join(download_dir, filename)

                print(f"[{i}/{len(zip_urls)}] Downloading {filename}...")
                with requests.get(url, stream=True, timeout=60) as r:
                    r.raise_for_status()
                    with open(filepath, "wb") as f:
                        for chunk in r.iter_content(chunk_size=8192):
                            f.write(chunk)
                print(f"✅ Saved to {filepath}")
            except Exception as e:
                print(f"❌ Failed to download {url}: {e}")

    except Exception as e:
        raise RuntimeError(f"Failed to query feature service: {e}")

# 使用示例(替换为你的真实 URL)
if __name__ == "__main__":
    ARC_URL = "https://www.arcgis.com/home/item.html?id=a5248eb6412648ec8cbd46838adb86e9#data"
    download_zip_files(ARC_URL, download_dir="ks_contours_zips")

? 关键注意事项:

  • 不要修改 download_dir 为含空格路径(如 "C: My Drive"):Windows 路径中空格需转义或使用原始字符串,更推荐使用绝对路径如 r"C:\Users\Name\Downloads\zips" 或相对路径 "./downloads"。
  • 网络权限与 CORS 无关:该方案绕过浏览器限制,直接调用公开 REST API,但需确保目标服务未启用 IP 白名单或令牌认证(本例为公开数据,无需 token)。
  • 稳定性增强:脚本加入 timeout、raise_for_status() 和 stream=True,避免大文件内存溢出及请求挂起。
  • 扩展性提示:若字段名非 "ContoursURL",请先 print(data['features'][0]['attributes']) 查看实际键名;若服务层级不同(如 FeatureServer/1),需调整 URL 路径。

通过理解 ArcGIS 的数据分发机制并转向 API 交互式抓取,你将彻底摆脱“BeautifulSoup 找不到链接”的困境,实现健壮、可维护的批量下载流程。


# javascript  # java  # html  # js  # 前端  # json  # ajax  # windows  # 编码  # 浏览器  # app  # ai  # beautifulsoup  # print  # Token  # 字符串  # 异步  # arcgis  # azure  # 下载链接  # 加载  # 找不到  # 令牌  # 推荐使用  # 请先  # 不存在  # 为例  # 你将  # 可直接 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel Eloquent:优雅地将关联模型字段扁平化到主模型中  想要更高端的建设网站,这些原则一定要坚持!  Laravel如何使用Guzzle调用外部接口_Laravel发起HTTP请求与JSON数据解析【详解】  郑州企业网站制作公司,郑州招聘网站有哪些?  node.js报错:Cannot find module 'ejs'的解决办法  如何续费美橙建站之星域名及服务?  中国移动官方网站首页入口 中国移动官网网页登录  Laravel如何自定义错误页面(404, 500)?(代码示例)  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  小视频制作网站有哪些,有什么看国内小视频的网站,求推荐?  如何快速生成凡客建站的专业级图册?  详解Android中Activity的四大启动模式实验简述  Python3.6正式版新特性预览  如何快速查询域名建站关键信息?  如何有效防御Web建站篡改攻击?  JS中对数组元素进行增删改移的方法总结  Windows10电脑怎么设置虚拟光驱_Win10右键装载ISO镜像文件  浅谈Javascript中的Label语句  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  新三国志曹操传主线渭水交兵攻略  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  如何快速辨别茅台真假?关键步骤解析  高性能网站服务器配置指南:安全稳定与高效建站核心方案  Bootstrap整体框架之JavaScript插件架构  常州企业网站制作公司,全国继续教育网怎么登录?  JS碰撞运动实现方法详解  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  Laravel如何使用.env文件管理环境变量?(最佳实践)  Edge浏览器怎么启用睡眠标签页_节省电脑内存占用优化技巧  详解免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)  Laravel如何使用Blade组件和插槽?(Component代码示例)  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  济南网站建设制作公司,室内设计网站一般都有哪些功能?  制作企业网站建设方案,怎样建设一个公司网站?  Angular 表单中正确绑定输入值以确保提交与验证正常工作  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  python中快速进行多个字符替换的方法小结  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  香港服务器部署网站为何提示未备案?  如何用狗爹虚拟主机快速搭建网站?  如何快速搭建高效可靠的建站解决方案?  如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?  Thinkphp 中 distinct 的用法解析  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?  Laravel如何实现API资源集合?(Resource Collection教程)  进行网站优化必须要坚持的四大原则