Очистка ссылок в столбцах df с помощью rvest

#r #web-scraping #rvest

Вопрос:

У меня есть фрейм данных, в одном из столбцов которого содержатся ссылки на веб-страницы, которые я хочу очистить с помощью rvest. Я хотел бы загрузить некоторые ссылки, сохранить их в другой колонке и загрузить с них некоторые тексты. Я пытался сделать это с помощью lapply , но я добрался Error in UseMethod("xml_find_all") : no applicable method for 'xml_find_all' applied to an object of class "function" до второго шага. Возможно, проблема может заключаться в том, что первые ссылки сохраняются в виде списка. Вы знаете, как я могу это решить?

Это мой MWE (в моем полном наборе данных у меня около 5000 ссылок, должен ли я использовать Sys.sleep и как?)

 library(rvest)

df <- structure(list(numeroAtto = c("2855", "2854", "327", "240", "82"
), testo = c("http://dati.camera.it/ocd/versioneTestoAtto.rdf/vta18_leg.18.pdl.camera.2855.18PDL0127540", 
             "http://dati.camera.it/ocd/versioneTestoAtto.rdf/vta18_leg.18.pdl.camera.327.18PDL0003550",
             "http://dati.camera.it/ocd/versioneTestoAtto.rdf/vta18_leg.18.pdl.camera.327.18PDL0003550", 
             "http://dati.camera.it/ocd/versioneTestoAtto.rdf/vta18_leg.18.pdl.camera.240.18PDL0007740", 
             "http://dati.camera.it/ocd/versioneTestoAtto.rdf/vta18_leg.18.pdl.camera.82.18PDL0001750"
)), row.names = c(NA, 5L), class = "data.frame")

df$links_text <- lapply(df$testo, function(x) {
  page <- read_html(x)
  links <- html_nodes(page, '.value:nth-child(8) .fixed') %>%
    html_text(trim = T)
})

df$text <- lapply(df$links_text, function(x) {
  page1 <- read_html(x)
  links1 <- html_nodes(page, 'p') %>%
    html_text(trim = T)
})
 

Ответ №1:

Вы хотите links1 <- html_nodes(page, 'p') сослаться page1 , а не page .

[В противном случае (поскольку page в среде функций нет объекта, он пытается применить html_nodes к функции utils page ]

С точки зрения Sys_sleep , это довольно необязательно. Проверьте html-код страницы и посмотрите, есть ли в коде или пользовательском соглашении что-либо, запрещающее очистку. Если это так, то более любезное обращение к серверу может повысить ваши шансы на то, что вас не заблокируют!

Вы можете просто включить Sys.sleep(n) в свою функцию, где вы создаете df$text . n зависит от вас, мне повезло с 1-3 секундами, но это становится довольно медленным/долгим!

Комментарии:

1. Большое спасибо за вашу помощь! Я только что понял, что первый lapply возвращает список. В результате после второго lapply я получаю текст, который объединяет тексты, содержащиеся на всех веб-страницах. У вас есть какие-нибудь предложения?

Ответ №2:

Вы можете сделать это в одной sapply команде и использовать tryCatch для обработки ошибок.

 library(rvest)

df$text  <- sapply(df$testo, function(x) {
  tryCatch({
    x %>%
      read_html() %>%
      html_nodes('.value:nth-child(8) .fixed') %>%
      html_text(trim = T) %>%
      read_html %>%
      html_nodes('p') %>%
      html_text(trim = T) %>%
      toString()
  }, error = function(e) NA)
})
 

Комментарии:

1. Чем вам очень нравится, это работает! однако, когда я использую его для своего полного набора данных, я получаю Error: Document is empty . Может быть, какие-то ссылки не работают? Есть ли способ это исправить?

2. Да, вы можете использовать tryCatch , см. Обновленный ответ @Edoardo