Webscraping на нескольких страницах в R - PullRequest
0 голосов
/ 05 июля 2018

Я хотел бы настроить цикл для автоматизации некоторых веб-скрепок на нескольких страницах. Пока что это код, который у меня есть для одной итерации:

s <- html_session("https://www.hcdn.gob.ar/proyectos/resultados-buscador.html?")
s <- s %>% jump_to("?pagina=5") %>% read_html()
new <- s %>% html_nodes('div.dp-metadata span') %>% html_text()
type.2 <- s %>% html_nodes('h4') %>% html_text()
title <- s %>% html_nodes('div.dp-texto') %>% html_text()



new <- gsub("Iniciado en: ", "", new)
new <- gsub("Fecha: ", "", new)
new <- gsub("Expediente Diputados:", "", new)
new <- gsub("Expediente Senado:", "", new)
new<- new [-c(3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79)]
chamber <- new[c(1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58)]
billnum <- new[c(2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59)]
fecha <- new[c(3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60)]


new2 <- data.frame(chamber, billnum, fecha, title, type.2)

Часть, которая должна измениться - это число после "pagina =". Однако я попытался создать следующий упрощенный цикл, и он только что выдал ошибку:

new4 <- data.frame(matrix(nrow=40, ncol=2))
colnames(new4) <- c("title", "type")

for (i in 1:2) {
s <- html_session("https://www.hcdn.gob.ar/proyectos/resultados-buscador.html?")
s <- s %>% jump_to("?pagina=", i) %>% read_html()
type.2 <- s %>% html_nodes('h4') %>% html_text()
title <- s %>% html_nodes('div.dp-texto') %>% html_text()



new4[i, 1] <- title
new4[i, 2] <- type.2

}

Опять же, этот упрощенный цикл, который очищает только две из пяти необходимых мне функций, не работает и возвращает ошибку: Ошибка в f (init, x [[i]])): is.request (y) не TRUE. Я предполагаю, что что-то не так с запуском команд html_session () и jump_to () в цикле. Я хотел бы знать, как автоматизировать это в цикле, чтобы избежать ручной очистки нескольких тысяч страниц.

Я даже пытался создать вектор с использованием lapply, но я не очень уверен в своем кодировании функций, и все шаблоны, которые я видел, были простыми командами read_html (), и я не совсем уверен, как включит в функцию команды html_session () и jump_to ().

1 Ответ

0 голосов
/ 05 июля 2018

Ты почти понял. Основная проблема в вашем коде - jump_to("?pagina=", i) ... Это должно быть jump_to(paste0("?pagina=", i)). Вот полное решение:

library(rvest)
#> Loading required package: xml2

sesh <- html_session("https://www.hcdn.gob.ar/proyectos/resultados-buscador.html?")

scrape_one_page <- function(sesh, i) {
  one_page <- sesh %>% jump_to(paste0("?pagina=", i)) %>% read_html()
  new <- one_page %>% html_nodes('div.dp-metadata span') %>% html_text()
  type.2 <- one_page %>% html_nodes('h4') %>% html_text()
  title <- one_page %>% html_nodes('div.dp-texto') %>% html_text()

  new <- gsub("Iniciado en: ", "", new)
  new <- gsub("Fecha: ", "", new)
  new <- gsub("Expediente Diputados:", "", new)
  new <- gsub("Expediente Senado:", "", new)
  new <- new [-c(3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79)]
  chamber <- new[c(1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52, 55, 58)]
  billnum <- new[c(2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59)]
  fecha <- new[c(3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60)]

  data.frame(chamber, billnum, fecha, title, type.2, stringsAsFactors = F)
}

# This call to lapply basically says:
# ...For each element in 1:5 (i.e., 1, 2, 3, 4, 5):
#   ...call scrape_one_page() with the first argument being equal to one of those elements and with the argument `sesh` equal to `sesh`
# ... then put the results in a list

# so it basically results in: 
# outs <- list(
#  scrap_one_page(1, sesh),
#  scrap_one_page(2, sesh),
#  scrap_one_page(3, sesh),
#  scrap_one_page(4, sesh),
#  scrap_one_page(5, sesh)
# )
outs <- lapply(1:5, scrape_one_page, sesh = sesh)

# then here with do.call(rbind) we combine the list of data frames into a single data frame 
df <- do.call(rbind, outs)

# and finally print the first few rows of the data frame
head(df)
#>     chamber      billnum      fecha
#> 1 Diputados  3967-D-2018 29/06/2018
#> 2 Diputados  3966-D-2018 29/06/2018
#> 3 Diputados  3965-D-2018 29/06/2018
#> 4 Diputados  3964-D-2018 29/06/2018
#> 5 Diputados  3963-D-2018 29/06/2018
#> 6 Diputados  3962-D-2018 29/06/2018
#>                                                                                                                                     title
#> 1 SOLICITAR AL PODER EJECUTIVO DISPONGA LAS MEDIDAS NECESARIAS PARA ASEGURAR LA CONTINUIDAD DEL CICLO LECTIVO EN LA PROVINCIA DEL CHUBUT.
#> 2                                                         EXPRESAR REPUDIO POR LA POLITICA INMIGRATORIA DE LOS ESTADOS UNIDOS DE AMERICA.
#> 3                  EXPRESAR REPUDIO POR EL FRAUDE COMETIDO EL 23 DE JUNIO 2018 EN LA "FEDERACION UNIVERSITARIA DE BUENOS AIRES - FUBA -".
#> 4                         EXPRESAR REPUDIO POR LA REPRESION DE FUERZAS POLICIALES Y DE SEGURIDAD, CONTRA LOS TRABAJADORES DE CRESTA ROJA.
#> 5                          PROHIBENSE LOS DESPIDOS DE LA AGENCIA DE NOTICIAS ESTATAL TELAM S.E. POR EL TERMINO DE 24 MESES PRORROGABLES. 
#> 6              DECLARESE LA SEMANA QUE CONTIENE EL 26 DE JUNIO DE CADA AÑO COMO "SEMANA NACIONAL DE LA PREVENCION DEL CONSUMO DE DROGAS".
#>                   type.2
#> 1 PROYECTO DE RESOLUCIÓN
#> 2 PROYECTO DE RESOLUCIÓN
#> 3 PROYECTO DE RESOLUCIÓN
#> 4 PROYECTO DE RESOLUCIÓN
#> 5        PROYECTO DE LEY
#> 6        PROYECTO DE LEY
...