Веб-скрейпинг с петлей

Я пытаюсь очистить некоторый текст с веб-сайта, используя функцию цикла, но моя функция цикла не переходит к выбору следующего элемента в моем векторном списке. Рад любым полезным советам. Спасибо

library(rvest)
library(xml2)


ID <- c(1:2)
Land <- c('Afghanistan','Ägypten')
url <- c('afghanistan', 'aegypten') 
Text <- (NA)

data <- data.frame(ID, Land, Text)

for(i in url) {
  nam <- paste("https://www.reporter-ohne-grenzen.de", i, sep = "/")
  assign(nam, i)

  webpage <- read_html(paste0(nam, i))
  data$Text <- i <- webpage %>% html_nodes('div.text') %>% .[[1]] %>% html_text() 
}

Хм, не уверен, что ясно изложил свою проблему. Вот пример моего желаемого вывода данных.

library(rvest)
library(xml2)

ID <- c(1:2)
Land <- c('Afghanistan','Ägypten')
url <- c('afghanistan', 'aegypten') 
Text <- (NA)

data <- data.frame(ID, Land, Text)


afghanistan <- 'https://www.reporter-ohne-grenzen.de/afghanistan'
afghanistan <- read_html(afghanistan)
afghanistan <- html_nodes(afghanistan,'div.text')
afghanistan <- html_text(afghanistan)[[1]]

aegypten <- 'https://www.reporter-ohne-grenzen.de/aegypten'
aegypten <- read_html(aegypten)
aegypten <- html_nodes(aegypten,'div.text')
aegypten <- html_text(aegypten)[[1]]

# desired data output
data$Text <- c(afghanistan, aegypten)

Я не хочу повторять эти строки для 180 стран.

aegypten <- 'https://www.reporter-ohne-grenzen.de/aegypten'
aegypten <- read_html(aegypten)
aegypten <- html_nodes(aegypten,'div.text')
aegypten <- html_text(aegypten)[[1]]

Вот решение:

library(rvest)
library(xml2)

ID <- c(1:4) 
Land <- c('Afghanistan','Ägypten','Deutschland','Italien')
Url <- c('afghanistan', 'aegypten','deutschland','italien') 
Text <- NA

data <- data.frame(ID, Land, Text)
website <- 'https://www.reporter-ohne-grenzen.de'

for (i in ID) {
  country <- Url[i]

  html_url <- paste(website,country,sep='/')
  output <- read_html(html_url)
  output <- html_nodes(output,'div.text')
  output <- html_text(output)[[1]]

  data$Text[i] <- output
}

person co7000    schedule 18.11.2019    source источник
comment
Почему вы используете assign? Переменной nam должно быть достаточно для использования в read_html, зачем снова добавлять i. Я бы предложил использовать sapply или lapply, потому что тогда вы получаете результаты в списке, а затем можете просто удалить его из списка и создать из него data.frame.   -  person hannes101    schedule 18.11.2019


Ответы (2)


Несмотря на то, что циклы for могут быть очень удобными, вы обычно решаете итерации в R, создавая функции, которые затем можно повторять.

В этом примере мы можем поместить ваш цикл for в функцию, а затем использовать purrr и функцию map() или, в данном случае, дочернюю функцию map_character() внутри dplyr mutate() для сохранения текстового результата в столбце.

library(rvest)
#> Loading required package: xml2
library(xml2)
library(tidyverse)

ID <- c(1:2)
Land <- c('Afghanistan','Ägypten')
url <- c('afghanistan', 'aegypten') 
Text <- (NA)

data <- data.frame(ID, Land, url, Text)

read_country <- function(country_url){

nam <- paste0("https://www.reporter-ohne-grenzen.de/", country_url)

webpage <- read_html(paste0(nam))

webpage %>% html_nodes('div.text') %>% .[[1]] %>% html_text() 

}

data <- data %>% 
    mutate(Text = map_chr(url, read_country))

Создано 18 ноября 2019 г. с помощью пакета reprex (v0.3.0)

person FilipW    schedule 18.11.2019
comment
А, я этого не знал. Просто подумал, что это облегчает чтение того, что возвращает функция. На самом деле это работает (я использую пакет reprex), поскольку названия стран можно использовать в URL-адресе, а затем перенаправлять на правильный URL-адрес, например, reporter-ohne-grenzen.de/Ägypten становится reporter-ohne-grenzen.de/aegypten. Но я изменил его так, чтобы он был более явным. - person FilipW; 18.11.2019

Используя функции purrr вместе с rvest, мы можем сделать

library(purrr)
library(rvest)

data$Text <- map(paste0("https://www.reporter-ohne-grenzen.de/", url),
             ~.x %>% 
                read_html %>% 
                html_nodes('div.text') %>%
                html_text %>% .[[1]]) %>% flatten_chr()

данные

ID <- c(1:2)
Land <- c('Afghanistan','Ägypten')
url <- c('afghanistan', 'aegypten') 
Text <- (NA)
data <- data.frame(ID, Land, Text)
person Ronak Shah    schedule 19.11.2019