使用 splashr 进行 Web 抓取时出现许多错误,包括 execute_lua(splash_obj, call_function) 中的错误:网关超时 (HTTP 504)

Many Errors when Web-Scraping with splashr including Error in execute_lua(splash_obj, call_function) : Gateway Timeout (HTTP 504)

我正在尝试使用 splashr 来抓取动态网页,这对我来说一直是个问题。在我抓取 get_box_score() 期间,我要么得到错误

Error in execute_lua(splash_obj, call_function) : 
Gateway Timeout (HTTP 504).

Error in UseMethod("html_table") : 
no applicable method for 'html_table' applied to 
an object of class "xml_missing"

老实说,一旦我 "fix" 犯了一个错误,我就会犯另一个错误。我不知道这些是否相关,或者我的代码是否只是遇到了很多不同的无关错误。知道我该如何解决这些问题吗?这是我的代码:

library(tidyverse)
library(splashr)
library(rvest)

url <- "https://www.uscho.com/scoreboard/michigan/mens-hockey/"  

# Everything should be fine for a while
get_data <- function(myurl) {

  link_data <- myurl %>%
    read_html() %>%
    html_nodes("td:nth-child(13) a") %>%
    html_attr("href") %>%
    str_c("https://www.uscho.com", .) %>%
    as_tibble() %>%
    set_names("url")

  game_type <- myurl %>%
    read_html() %>%
    html_nodes("td:nth-child(12)") %>%
    html_text() %>%
    as_tibble() %>%
    set_names("game_type") %>%
    filter(game_type != "Type")

  as_tibble(data.frame(link_data, game_type))

}

link_list <- get_data(url)

urls <- link_list %>%
  filter(game_type != "EX") %>%
  pull(url)

# Here's where the fun starts
get_box_score <- function(my_url) {

  progress_bar$tick()$print()
  Sys.sleep(15)
  splash_container <- start_splash()
  on.exit(stop_splash(splash_container))
  Sys.sleep(10)

  mydata <- splash_local %>%
    splash_response_body(TRUE) %>%
    splash_user_agent(ua_win10_chrome) %>%
    splash_go(my_url) %>%
    splash_wait(runif(1, 5, 10)) %>%
    splash_html() %>%
    html_node("#boxgoals") %>%
    html_table(fill = TRUE) %>%
    as_tibble()

  return(mydata)
}

progress_bar <- link_list %>%
  filter(game_type != "EX") %>%
  tally() %>%
  progress_estimated(min_time = 0)

mydata <- pmap_df(list(urls), get_box_score)

您的代码没有任何问题。 504是服务器端错误;服务器无法及时处理请求。

但是您仍然可以通过调整代码来修复它;您可以尝试以下方法:

  • 放慢你的请求,使用Sys.sleep()在每个请求之间暂停,如果你请求太快,服务器可能无法处理它,可能会认为你像一个机器人并禁止你。结果,您将收到 504 错误。

  • 使用 try()tryCatch() 函数来跳过错误并防止它们破坏您的循环。也可以编写代码,在请求失败时自动尝试再次请求。