在 R 中下载之前验证来自网站的数据

Validate data from website before downloading in R

我有一堆天气数据文件要下载,但是网站 url 有的和没有的混合在一起。我在 R 中使用 download.file 函数下载文本文件,工作正常,但我也下载了很多空文本文件,因为所有 url 都是有效的,即使如果没有数据。

例如,这个url提供了很好的数据。

http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST&YEAR=2021&MONTH=12&FROM=3000&TO=3000&STNM=72645

但是这个没有。

http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST&YEAR=1970&MONTH=12&FROM=3000&TO=3000&STNM=72645

有没有办法在下载前检查文本文件中是否包含有效数据?我在 RCurl 包中寻找了一些东西,但没有看到我需要的东西。谢谢。

您可以在下载前使用httr::HEAD确定数据大小。请注意,这可以节省 you 下载的“痛苦”;如果服务器端有任何成本,即使您不下载它也会感到查询痛苦。 (这两个好像够快的,应该不是问题吧。)

# good data
res1 <- httr::HEAD("http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST&YEAR=2021&MONTH=12&FROM=3000&TO=3000&STNM=72645")
httr::headers(res1)$`content-length`
# [1] "9435"

# no data
res2 <- httr::HEAD("http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST&YEAR=1970&MONTH=12&FROM=3000&TO=3000&STNM=72645")
httr::headers(res2)$`content-length`
# NULL

如果 API 提供了估计大小(或至少存在数据)的功能,那么远程端使用它而不是使用这种技术可能更好。例如:假设 API 调用需要 20 秒 SQL 查询。调用 HEAD 需要 20 秒,就像调用 GET 一样,唯一的区别是您不会获取数据。如果您看到您将获取数据,然后随后调用 httr::GET(.),那么您将再等待 20 秒(除非远程端正在缓存查询)。

或者,他们可能有一种启发式方法来查找数据的存在,也许只是一个简单的 yes/no,只需要几秒钟。在这种情况下,在调用 20 秒的完整查询调用之前进行 3 秒的“是否存在数据”API 调用会“更好”。

底线:如果 API 有“数据大小”估算器,请使用它,否则 HEAD 应该可以正常工作。

作为 HEAD 的替代方案,仅 GET 数据,检查内容长度,仅在找到时保存到文件:

res1 <- httr::GET("http://weather.uwyo.edu/cgi-bin/sounding?region=naconf&TYPE=TEXT%3ALIST&YEAR=2021&MONTH=12&FROM=3000&TO=3000&STNM=72645")
stuff <- as.character(httr::content(res1))
if (!is.null(httr::headers(res1)$`content-length`)) {
  writeLines(stuff, "somefile.html")
}
# or do something else with the results, in-memory