如何在rvest中设置超时时间

10
简单问题:这段代码 x <- read_html(url) 卡住并且读取页面的时间无限延长。我不知道如何处理它,例如通过设置一些响应的最大时间来处理。我可以使用 try、catch 或者其他方式进行重试。但是它卡住了,什么都没有发生。有人知道如何处理吗?
页面没有问题,有时会出现这种情况,并且手动重试时可以正常工作。

可能是Comatose web crawler in R (w/ rvest)的重复问题。 - Kim
1个回答

14
你可以在httr包的GET函数中包装read_html
例如,如果你的原始代码是:
library(rvest)
library(dplyr)

my_url <- "https://dev59.com/1FYM5IYBdhLWcg3whAeH
x <- my_url %>% read_html(.)

那么你可以用以下内容替换它

library(httr)

# Allow 10 seconds
my_url %>% GET(., timeout(10)) %>% read_html

# Allow 30 seconds
my_url %>% GET(., timeout(30)) %>% read_html

例子

为了测试,尝试设置一个极短的超时时间(例如,一百分之一秒)。

# Allow an unreasonably short amount of time so the request errors rather than hangs indefinitely

my_url %>% GET(., timeout(0.01)) %>% read_html

# Error in curl::curl_fetch_memory(url, handle = handle) : 
#   Timeout was reached: Resolving timed out after 10 milliseconds

你可以在这里找到更多示例。

在循环中使用它(例如,“超时后跳过到下一个”)

尝试运行此代码。它假设您有要访问的网址数量(在本例中为3个),其中第二个网址将在提供html之前延迟3秒 - 这是测试您正在寻找的功能的绝佳方法。 我们将超时设置为2秒,因此我们知道它将失败。tryCatch()函数将仅执行其作为第二个参数放入的任何代码; 在本例中,它将仅将“已超时!”分配给列表元素。


my_urls <- c("https://dev59.com/1FYM5IYBdhLWcg3whAeH,
             "http://httpbin.org/delay/3", # This url will delay 3 seconds
             "http://httpbin.org/delay/1") 

x <- list()

# Set timeout for 2 seconds (so second url will fail)
for (i in 1:length(my_urls)) {

  print(paste0("Scraping url number ", i))

  tryCatch(x[[i]] <- my_urls[i] %>% GET(., timeout(2)) %>% read_html,
           error = function(e) { x[[i]] <<- "Timed out!" } )
  
}

现在我们检查输出 - 第一个和第三个站点返回了内容,第二个超时了

# > x
# [[1]]
# {xml_document}
# <html itemscope="" itemtype="http://schema.org/QAPage" class="html__responsive">
#   [1] <head>\n<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n<title>r - how to set timeout ...
# [2] <body class="question-page unified-theme">\r\n    <div id="notify-container"></div>\r\n    <div id="custom ...
# 
# [[2]]
# [1] "Timed out!"
# 
# [[3]]
# {xml_document}
# <html>
# [1] <body><p>{\n  "args": {}, \n  "data": "", \n  "files": {}, \n  "form": {}, \n  "headers": {\n    "Accept": ...


显然,您可以将超时值设置为任何您想要的值。根据使用情况,30-60秒可能是合理的。


这个很好用,但是对于我来说代码在超时时停止了,而且没有跳过它。 - d3hero23
@d3hero23 这是预期的行为,因为当 GET() 超时时,它本质上是一个错误。为确保您的代码继续运行,请将 GET() 包装在 tryCatch() 中。您可以使用上面答案中的示例:tryCatch(x[[i]] <- my_urls[i] %>% GET(., timeout(2)) %>% read_html, error = function(e) { x[[i]] <<- "超时!" } ) - stevec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接