首页 > 解决方案 > 如何从 download.file 请求中捕获 HTTP 错误代码?

问题描述

此代码尝试下载不存在的页面:

url <- "https://en.wikipedia.org/asdfasdfasdf"
status_code <- download.file(url, destfile = "output.html", method = "libcurl")

这将返回 404 错误:

trying URL 'https://en.wikipedia.org/asdfasdfasdf'
Error in download.file(url, destfile = "output.html", method = "libcurl") : 
  cannot open URL 'https://en.wikipedia.org/asdfasdfasdf'
In addition: Warning message:
In download.file(url, destfile = "output.html", method = "libcurl") :
  cannot open URL 'https://en.wikipedia.org/asdfasdfasdf': HTTP status was '404 Not Found'

code变量仍然包含 0,即使文档download.file声明返回值是:

一个(不可见的)整数代码,0 表示成功,非零表示失败。对于“wget”和“curl”方法,这是外部程序返回的状态码。“内部”方法可以返回 1,但在大多数情况下会抛出错误。

curl如果我使用或wget作为下载方法,结果是一样的。我在这里想念什么?warnings()是调用和解析输出的唯一选择吗?

我已经看到有关 using的其他问题download.file,但没有一个(我能找到)实际检索 HTTP 状态代码。

标签: rhttpcurlwget

解决方案


可能最好的选择是直接使用 cURL 库,而不是通过download.file不暴露 cURL 全部功能的包装器。我们可以做到这一点,例如,使用 RCurl 包(尽管其他包如 httr 或系统调用也可以实现相同的功能)。直接使用 cURL 将允许您访问 cURL 信息,包括响应代码。例如:

library(RCurl)
curl = getCurlHandle()
x = getURL("https://en.wikipedia.org/asdfasdfasdf", curl = curl)
write(x, 'output.html')
getCurlInfo(curl)$response.code
# [1] 404

尽管上面的第一个选项更简洁,但如果您真的想download.file改用,一种可能的方法是使用捕获警告withCallingHandlers

try(withCallingHandlers( 
  download.file(url, destfile = "output.html", method = "libcurl"),
  warning = function(w) {
    my.warning <<- sub(".+HTTP status was ", "", w)
    }),
  silent = TRUE)

cat(my.warning)
'404 Not Found'

推荐阅读