【问题标题】:Error in open.connection(x, "rb") : HTTP error 500 when using map_dfopen.connection(x, "rb") 中的错误:使用 map_df 时出现 HTTP 错误 500
【发布时间】:2019-08-08 16:17:59
【问题描述】:

我在尝试抓取新闻网站时收到错误消息。我查了一下,网站第32页坏了。我想跳过错误并继续抓取其余的网址。

我尝试了 TryCatch 函数来避免链接断开,但由于我对 R 很陌生,所以我不知道如何正确编写代码。我应该用那个函数包装 read_html 吗?如果有,怎么做?

url_silla <- 'https://lasillavacia.com/buscar/farc?page=%d'

map_df(0:573, function(i) {

  pagina <- read_html(sprintf(url_silla, i, '%s', '%s', '%s', '%s'))
  print(i)

  data.frame(titles = html_text(html_nodes(pagina,".col-sm-12 h3")),
             date = html_text(html_nodes(pagina, ".date.col-sm-3")),
             category = html_text(html_nodes(pagina, ".category.col-sm-9")),
             tags = html_text(html_nodes(pagina, ".tags.col-sm-12")),
             link = paste0("https://www.lasillavacia.com",str_trim(html_attr(html_nodes(pagina, "h3 a"), "href"))),
            stringsAsFactors=FALSE)
}) -> noticias_silla

这是错误。非常感谢您的帮助!

[1] 31
Error in open.connection(x, "rb") : HTTP error 500.
Called from: open.connection(x, "rb")

【问题讨论】:

标签: r web-scraping try-catch rvest


【解决方案1】:

您可以将tryCatch 构建到一个函数中,然后将该函数传递给map_dfr。将其设置为在发生错误时返回NULL,这不会破坏map_dfr 创建数据框。

我建议首先尝试使用map,这样您就可以调查一些索引如何返回您想要的数据框,而另一些则返回NULL。无论哪种情况,finally 参数都会打印索引。

library(dplyr)
library(purrr)
library(rvest)

url_silla <- 'https://lasillavacia.com/buscar/farc?page=%d'

read_page <- function(i) {
  tryCatch(
    {
      pagina <- read_html(sprintf(url_silla, i, '%s'))
      data.frame(titles = html_text(html_nodes(pagina,".col-sm-12 h3")),
                 date = html_text(html_nodes(pagina, ".date.col-sm-3")),
                 category = html_text(html_nodes(pagina, ".category.col-sm-9")),
                 tags = html_text(html_nodes(pagina, ".tags.col-sm-12")),
                 link = paste0("https://www.lasillavacia.com", trimws(html_attr(html_nodes(pagina, "h3 a"), "href"))),
                 stringsAsFactors=FALSE)
    },
    error = function(cond) return(NULL),
    finally = print(i)
  )
}

noticias <- map_dfr(30:33, read_page)
#> [1] 30
#> [1] 31
#> [1] 32
#> [1] 33

【讨论】:

    【解决方案2】:

    你可以使用purrr::possibly:

    url_silla <- 'https://lasillavacia.com/buscar/farc?page=%d'
    
    library(tidyverse)
    library(rvest)
    
    map_df(0:573, possibly(~{
    
        pagina <- read_html(sprintf(url_silla, .x, '%s', '%s', '%s', '%s'))
    
        print(.x)
    
        data.frame(titles = html_text(html_nodes(pagina,".col-sm-12 h3")),
                   date = html_text(html_nodes(pagina, ".date.col-sm-3")),
                   category = html_text(html_nodes(pagina, ".category.col-sm-9")),
                   tags = html_text(html_nodes(pagina, ".tags.col-sm-12")),
                   link = paste0("https://www.lasillavacia.com",str_trim(html_attr(html_nodes(pagina, "h3 a"), "href"))),
                   stringsAsFactors=FALSE)
    
    }, NULL)) -> noticias_silla
    

    【讨论】:

      【解决方案3】:

      下面的代码只处理第 31、32 和 33 页。

      我不会使用map_* 来解决问题,我相信这可能会使事情变得比实际情况更困难。我将使用标准的for 循环,因为没有理由不这样做。

      library(rvest)
      library(stringr)
      library(tidyverse)
      
      url_silla <- 'https://lasillavacia.com/buscar/farc?page=%d'
      
      pages <- 31:33
      noticias_silla <- vector("list", length = length(pages))
      
      for(i in pages){
        p <- sprintf(url_silla, i, '%s', '%s', '%s', '%s')
        pagina <- tryCatch(read_html(p),
                           error = function(e) e)
        print(i)
        if(inherits(pagina, "error")){
          noticias_silla[[i - pages[1] + 1]] <- list(page_num = i, page = p)
        }else{
          noticias_silla[[i - pages[1] + 1]] <- data.frame(titles = html_text(html_nodes(pagina,".col-sm-12 h3")),
                                                 date = html_text(html_nodes(pagina, ".date.col-sm-3")),
                                                 category = html_text(html_nodes(pagina, ".category.col-sm-9")),
                                                 tags = html_text(html_nodes(pagina, ".tags.col-sm-12")),
                                                 link = paste0("https://www.lasillavacia.com",str_trim(html_attr(html_nodes(pagina, "h3 a"), "href"))),
                                                 stringsAsFactors=FALSE)
        }
      }
      
      lapply(noticias_silla, class)    noticias_silla[[1]]
      noticias_silla[[2]]
      
      #[[1]]
      #[1] "data.frame"
      #
      #[[2]]
      #[1] "list"
      #
      #[[3]]
      #[1] "data.frame"    noticias_silla[[1]]
      noticias_silla[[2]]
      

      请注意,第二个列表成员是"list",而不是"data.frame"。这是发生错误的地方。

      noticias_silla[[2]]
      #$page_num
      #[1] 32
      #
      #$page
      #[1] "https://lasillavacia.com/buscar/farc?page=32"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-19
        • 2020-10-18
        • 1970-01-01
        • 1970-01-01
        • 2021-10-31
        • 2018-05-27
        • 2023-01-07
        相关资源
        最近更新 更多