如何在 R 中检查有效的 API 调用? RCurl 和 httr 目前没有帮助

How to check a valid API call in R? RCurl and httr not helping at the moment

我想从 UN COMTRADE 导入 JSON 数据。所以,我写了一个有效国家和年份的列表,然后我 运行 一个工作正常的循环,除非某个年份不包含某个国家的数据。

鉴于此,我想测试我的 API 调用是否有效,所以我这样写:

library(RCurl)

# this is an actual valid API call    
string = "http://comtrade.un.org/api/get?max=50000&type=C&freq=A&px=S2&ps=2010&r=4&p=all&rg=2&cc=AG4&fmt=json"

url.exists(string, useragent="curl/7.47.0 RCurl/1.95-4.8")

但是,即使对于可以在互联网浏览器上显示为 JSON 文本的有效国家代码和年份,R 输出也会显示

url.exists(string, useragent="curl/7.47.0 RCurl/1.95-4.8")
[1] FALSE

httr

library(httr)
!http_error(string)

我得到了[1] FALSE

我该如何修复假阴性结果?

我在url.exists()取了个高峰,然后写了这个更简单的版本

> g = basicTextGatherer()
> x = curlPerform(url=string, headerfunction=g$update, nobody=TRUE)
> g$value()
[1] "HTTP/1.1 302 Moved Temporarily\r\nLocation: https://comtrade.un.org/api/get?max=50000&type=C&freq=A&px=S2&ps=2010&r=4&p=all&rg=2&cc=AG4&fmt=json\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nDate: Thu, 23 Feb 2017 23:09:13 GMT\r\nAge: 0\r\nConnection: close\r\nVia: 1.1 localhost.localdomain\r\n\r\n"

http: url 被重定向到 https:,所以我尝试了

> string = sub("http", "https", string)
> g = basicTextGatherer()
> x = curlPerform(url=string, headerfunction=g$update, nobody=TRUE)
> g$value()
[1] "HTTP/1.1 405 Method Not Allowed\r\nCache-Control: no-cache\r\nPragma: no-cache\r\nAllow: GET\r\nContent-Length: 73\r\nContent-Type: application/json; charset=utf-8\r\nExpires: -1\r\nServer: Microsoft-IIS/7.5\r\nX-AspNet-Version: 4.0.30319\r\nX-Powered-By: ASP.NET\r\nDate: Thu, 23 Feb 2017 23:11:02 GMT\r\n\r\n"

不支持 curl 选项 nobody 隐含的 'HEAD' 方法。这也是 httr::http_error() 失败的原因——因为它正在执行 HEAD 请求。不支持HEAD请求是服务器端的决定,所以用户端什么也做不了。

您也可以尝试只获取一个字节(例如,RCurl::getURL(string, followlocation=TRUE, range="0-1")),但这也可能不受支持(并且不适用于此查询——整个查询响应是 returned).

所以我可以测试文件是否确实存在的唯一方法是检索它。我会使用 httr::GET(),也许像

tryCatch({
    response <- httr::GET(string)
    stop_for_status(response)
    ## ...
}, http_error=function(e) {
    ## log error or otherwise recover
})

无论如何,这可能是一个更有效的解决方案。如果查询成功,先检查再执行查询需要两次网络调用,而不进行检查只进行一次网络调用。如果查询失败,那么在这两种方法下都只需要一次网络调用,并且 return 值同样紧凑。所以我们节省了最常见场景下由网络调用引起的延迟。