You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让R循环遇502错误时重试下载Google Earth KMZ文件

解决方案

核心优化点

  • 增加错误捕获与重试机制:用tryCatch包裹易失败的HTTP请求操作,遇到502等错误时自动重试,直到成功
  • 替换不稳定的browseURL:改用httr::GET直接下载文件,避免依赖浏览器,同时能更精准控制请求和错误处理
  • 移除固定等待时间:根据下载状态动态判断,而非固定Sys.sleep(10)
  • 简化文件命名逻辑:直接指定下载路径和文件名,无需读取下载文件夹快照

修改后的完整代码

首先需要安装并加载httr包(比原生readLines更适合HTTP请求处理):

loadandinstall <- function(mypkg) {
  if (!is.element(mypkg, installed.packages()[,1])){
    install.packages(mypkg, repos="http://cran.r-project.org")
  }
  library(mypkg, character.only=TRUE)
}

# 加载所需包,新增httr用于稳定HTTP请求
loadandinstall("stringr")
loadandinstall("rvest")
loadandinstall("XML")
loadandinstall("maptools")
loadandinstall("rgeos")
loadandinstall("rgdal")
loadandinstall("foreign")
loadandinstall("raster")
loadandinstall("sp")
loadandinstall("parallel")
loadandinstall("snow")
loadandinstall("httr")

# 读取CSV数据(优化:只读取一次,避免重复IO)
data <- read.csv(str_c(basedir,"AllPlantingLocationData_WebsiteSource_2019.csv"),
                 header=TRUE, colClasses=rep("character", 3))
urlstring <- data[,1]
gurls <- data[,2]
names <- data[,3]

# 定义重试函数:用于包裹易失败的操作
retry_on_error <- function(expr, max_tries = Inf, wait_seconds = 5) {
  tries <- 0
  repeat {
    tries <- tries + 1
    result <- tryCatch({
      expr
      TRUE  # 操作成功返回TRUE
    }, error = function(e) {
      # 打印错误信息和重试次数
      cat(sprintf("请求失败(第%d次重试):%s\n", tries, e$message))
      Sys.sleep(wait_seconds)
      FALSE # 失败返回FALSE
    })
    if (result || tries >= max_tries) break
  }
}

# 循环处理每个URL
for(i in 1:length(urlstring)){
  cat(sprintf("开始处理第%d个URL:%s\n", i, urlstring[i]))
  
  # 1. 获取网页源码(带重试)
  success <- retry_on_error({
    # 用httr::GET替代readLines,更稳定的HTTP请求
    response <- GET(urlstring[i])
    stop_for_status(response) # 自动检查HTTP状态码,非200则抛出错误
    t <- as.list(content(response, "text", encoding = "UTF-8"))
    t <- str_split(t, "\n")[[1]] # 按行分割成列表,模拟原readLines行为
  })
  
  if(!success) {
    cat(sprintf("第%d个URL多次重试仍失败,跳过(可后续手动处理)\n", i))
    next
  }
  
  # 2. 提取Google Maps URL(原逻辑保留)
  m <- unlist(t[which(!is.na(str_locate(t,"<iframe src=")[,1]))])
  gurl <- unlist(strsplit(substring(str_c(m),14,nchar(m))," "))[1]
  gurl <- substring(gurl,1,nchar(gurl)-1)
  gurls[i] <- str_c(gsub("embed","kml",gurl))
  
  # 3. 下载KMZ文件(带重试,直接指定路径)
  download_path <- file.path("/Users/badiskhiari/Downloads", paste0(names[i], ".kmz"))
  success <- retry_on_error({
    response <- GET(gurls[i], write_disk(download_path, overwrite = TRUE))
    stop_for_status(response)
  })
  
  if(success) {
    print(str_c("URL ",i," 下载完成!!"))
  } else {
    cat(sprintf("第%d个URL的KMZ文件多次重试仍下载失败\n", i))
  }
}

关键代码解释

  1. retry_on_error函数:封装了重试逻辑,传入要执行的表达式,失败后等待指定时间重试,直到成功或达到最大次数(这里设为无限,可根据需求调整max_tries)
  2. httr::GET替代原生方法:
    • 能自动处理HTTP状态码,stop_for_status会在状态码非200(如502)时抛出错误,触发重试
    • write_disk直接将响应内容写入指定文件,无需依赖浏览器和下载文件夹快照
  3. 单次CSV读取:原代码重复读取3次CSV,优化为只读一次,提升效率
  4. 错误日志输出:每次失败都会打印错误信息和重试次数,方便排查问题

额外建议

  • 可以调整wait_seconds参数,比如失败后等待时间逐渐增加(如5秒→10秒→15秒),避免频繁请求给服务器造成压力
  • 如果部分URL确实无法访问,可记录这些URL到单独文件,后续手动处理
  • 考虑加入并行处理(原代码加载了parallel和snow),但需注意不要同时发起过多请求导致被服务器封禁

内容的提问来源于stack exchange,提问作者badiskhiari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:07:18