使用http::GET下载卫星数据文件不完整的技术求助
解决R中使用httr::GET下载卫星数据文件过小的问题
问题原因分析
你下载得到的11KB文件大概率是网站返回的错误页面、重定向提示或未授权响应,而非实际卫星数据。这类科研数据站点通常会对请求做验证:
- 拦截非浏览器标识的程序请求(默认httr的请求头会被识别为非浏览器)
- 认证后需要维持会话状态才能获取真实资源
- 部分资源需通过重定向跳转才能拿到实际文件
解决方案
1. 先排查小文件的实际内容
先读取已下载的小文件,确认具体错误信息:
readLines(out.names[1])
常见错误可能是"未授权"、"请使用浏览器访问"或重定向地址提示。
2. 模拟浏览器请求头(核心解决方法)
添加User-Agent参数模拟浏览器请求,这是解决这类问题最常用的手段:
library(httr) the.files <- c( "https://oceandata.sci.gsfc.nasa.gov/cgi/getfile/AQUA_MODIS.20230101.L3m.DAY.CHL.chlor_a.4km.nc", "https://oceandata.sci.gsfc.nasa.gov/cgi/getfile/AQUA_MODIS.20230102.L3m.DAY.CHL.chlor_a.4km.nc" ) out.dir <- "~/Desktop/TEMP" out.names <- file.path(out.dir, basename(the.files)) # 用file.path处理路径更稳妥 # 模拟Mac系统Chrome浏览器的请求标识 ua <- user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 15_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") # 循环下载,添加浏览器标识、明确开启重定向跟随 for(i in seq_along(the.files)) { response <- GET( url = the.files[i], authenticate("jonthayn", "TempPassword7?"), ua, write_disk(out.names[i], overwrite = TRUE), timeout(600), follow_redirects = TRUE ) # 检查响应状态,及时发现下载失败 if(http_status(response)$category != "Success") { warning(sprintf("下载文件%s失败,状态码:%s", the.files[i], status_code(response))) } }
3. 用会话保持认证状态
如果站点需要维持会话才能持续下载,用handle创建持久连接,避免重复认证:
# 创建会话句柄 my_handle <- handle("https://oceandata.sci.gsfc.nasa.gov") # 先完成认证 GET("/", authenticate("jonthayn", "TempPassword7?"), handle = my_handle) # 复用同一个会话句柄下载所有文件 for(i in seq_along(the.files)) { response <- GET( url = the.files[i], ua, write_disk(out.names[i], overwrite = TRUE), timeout(600), handle = my_handle ) if(http_status(response)$category != "Success") { warning(sprintf("下载文件%s失败,状态码:%s", the.files[i], status_code(response))) } }
4. 批量下载优化(可选)
用purrr包实现更简洁的批量下载,同时添加错误捕获:
library(purrr) download_file <- function(url, out_path, username, password) { ua <- user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 15_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36") response <- GET( url = url, authenticate(username, password), ua, write_disk(out_path, overwrite = TRUE), timeout(600), follow_redirects = TRUE ) if(http_status(response)$category != "Success") { return(list(url = url, status = status_code(response), success = FALSE)) } else { return(list(url = url, size = file.size(out_path), success = TRUE)) } } # 批量执行下载 results <- map2(the.files, out.names, ~download_file(.x, .y, "jonthayn", "TempPassword7?")) # 查看所有下载结果 print(results)
额外注意事项
- 批量下载时建议添加
Sys.sleep(1)控制频率,避免触发站点的反爬限制 - 下载后用
file.size(out.names[i])检查文件大小,确认是否符合13MB左右的预期 - 确保账号权限正常(手动能下载则权限没问题,程序请求只是需要适配站点验证规则)
内容的提问来源于stack exchange,提问作者Jonathan Thayn
相关产品推荐
相关产品推荐

