curl::curl_fetch_memory(url, handle = handle) 中的错误:无法解析主机:

Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host:

提问人:user2165379 提问时间:8/13/2023 更新时间:8/13/2023 访问量:525

问:

在某些情况下,我的 R 代码(见下文)会生成以下错误:

[1] "2023-08-12 16:47:37.463"
Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host: api.abc.com
Request failed [ERROR]. Retrying in 1.3 seconds...
Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host: api.abc.com
Request failed [ERROR]. Retrying in 1 seconds...
Error in curl::curl_fetch_memory(url, handle = handle):
Could not resolve host: api.abc.com

api.abc.com 不是我使用的原始 API。 我使用了一个商业 API,它注意到我的服务器在上面的特定时刻没有关闭。在某些情况下,当服务器关闭时,它会返回 http-code 503。

我有两个问题:

  1. 这些错误的原因可能是什么?
  2. 在出现这些错误的情况下,如何使下面的脚本继续运行?目前,在这些错误消息之后,它会中断。我没想到会这样,因为我在我的代码中使用了 .RETRYGET

我的代码每 10 秒使用调度程序调用一次(请参阅代码末尾)。在此示例代码中,我使用了一个免费的 API (universities.hipolabs.com) 作为示例。tclTaskSchedule

library(httr) # accessing API's'
library(jsonlite) # JSON parsing
library(dplyr)
library(readr)
library(purrr)
library(tidyr)
library(stringr)
library(tibble)
library(tcltk2)
library(lubridate)

run_api_once <- function() {
  
  mydatalist <- list() #create an empty list
  
  my_next_page_with_number <- "http://universities.hipolabs.com/search?country=United+States"

    mydata1 <- RETRY("GET", my_next_page_with_number)
    
    if(mydata1$status_code != 200){
      print(mydata1$status_code)
      http_responses <<- append(http_responses, paste(mydata1$status_code, Sys.time()))
      has_more_pages <- FALSE
      
    } else {
      
      rawdata <- rawToChar(mydata1$content)
      mydata2 <- fromJSON(rawdata, flatten = FALSE, simplifyVector = FALSE)
      
      mydata <- mydata2
      
      mydatalist <- c(mydatalist, mydata)
    }
  
  
    y <- Sys.time()
    y <- format(y, "%Y-%m-%d %H:%M")
    print(y)
    
  users <- tibble(user = mydatalist)
  myvar <<- users %>% unnest_wider(user) 

return(myvar)
  
}


# call function every 10 seconds:
tclTaskSchedule(10000, run_api_once(), id = "run_api_once", redo = TRUE)

# end session:
tclTaskDelete(NULL)

我想这是无关紧要的,尽管为了完整起见:我使用 Plumber 将 myvar 的内容流式传输到我电脑上的本地服务器。请参阅下面的代码:

# stream df myvar to local api at port 8405:
library(plumber)
pr("D:/plumber_universities2test.R") %>%
# pr("C:/plumber_universities2test.R") %>%
  pr_run(port=8405)

它调用此脚本:

library(plumber)
library(dplyr)

#* @param symbol Ticker symbol (just to input something in the function)
#* @get /return
#* @serializer json list(na="string")

universities_data <- function(symbol) {
  data <- myvar
  data 
}

多谢!

r curl httr rcurl tcltk

评论


答:

1赞 JBGruber 8/13/2023 #1

要回答您的问题,请执行以下操作:

  1. 有几个可能的原因:您没有连接到互联网;你的防火墙挡住了路,阻止了你;或者您正在向无效的 URL 发出请求。如果没有看到您发出请求的实际 URL,我无法确定,但我猜第三个选项是最有可能的。您应该检查在粘贴特定 URL 时是否犯了错误。例如,代替httr"google.comsearch""google.com/search"
  2. 之所以没有按照您预期的方式运行,是因为这不是服务器返回的 HTTP 错误状态,但您的请求根本无法执行。为了演示这种差异,让我们看一下一个简单的函数的行为,该函数向一个 URL 发出请求,该 URL 会自动返回一个 HTTP 错误,而这个 URL 根本不存在:RETRY
library(httr)

test_fun <- function(u) {
  RETRY("GET", u, times = 2)
  print("still running")
}

# response contains error
test_fun("https://httpbin.org/status/429")
#> Request failed [429]. Retrying in 1 seconds...
#> [1] "still running"

# no repsonse since there is no server at `test.coms`
test_fun("test.coms")
#> Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host: test.coms
#> Request failed [ERROR]. Retrying in 1 seconds...
#> Error in curl::curl_fetch_memory(url, handle = handle): Could not resolve host: test.coms

创建于 2023-08-13 with reprex v2.0.2

如您所见,第一个示例仍然执行函数的剩余代码,而第二个示例则因错误而停止。我建议仔细检查为什么请求没有到达服务器,如果您确定没有更好的方法,您可以绕行:tryRETRY

mydata1 <- try(RETRY("GET", my_next_page_with_number))
if (is(mydata1, "try-error")) mydata1 <- list(status_code = 404)
if(mydata1$status_code != 200){
  # your code ...
}

但在我看来,这种行为是正确的,因为它不仅仅是忽略代码或互联网配置中可能存在的错误(不是服务器端问题)。RETRY

评论

0赞 user2165379 8/14/2023
@JBGruber ,非常感谢您的广泛回答!在发布我现在意识到的问题之前,我应该自己测试更多。我将检查我的 URL 中是否有错误的可能性,然后回来。
0赞 user2165379 8/14/2023
@JBGruber ,我的代码中来自 API 的 URL 是硬编码的,只是我在 URL 中添加了分页。我测试了错误的页码,这不会给出错误。尽管其他程序继续运行,但可能会丢失互联网连接。是否有可能来自 API 的服务器过载以至于它没有给出任何响应,从而导致错误?无论如何,您的解决方案运行完美!我对此感到非常满意,它解决了我的问题。特别是因为这个问题并不经常发生,尽管当它发生时,我的代码挂起。多谢!