Как я могу использовать цикл для очистки данных веб-сайта для нескольких веб-страниц в R?

Я хотел бы применить цикл для очистки данных с нескольких веб-страниц в R. Я могу очистить данные для одной веб-страницы, однако, когда я пытаюсь использовать цикл для нескольких страниц, я получаю неприятную ошибку. Я потратил часы на возню, но безрезультатно. Любая помощь будет принята с благодарностью!!!

Это работает:

###########################
# GET COUNTRY DATA
###########################

library("rvest")

site <- paste("http://www.countryreports.org/country/","Norway",".htm", sep="")
site <- html(site)

stats<-
    data.frame(names =site %>% html_nodes(xpath="//*/td[1]") %>% html_text() ,
         facts =site %>% html_nodes(xpath="//*/td[2]") %>% html_text() ,
         stringsAsFactors=FALSE)

stats$country <- "Norway"
stats$names   <- gsub('[\r\n\t]', '', stats$names)
stats$facts   <- gsub('[\r\n\t]', '', stats$facts)
View(stats)

Однако, когда я пытаюсь написать это в цикле, я получаю сообщение об ошибке

###########################
# ATTEMPT IN A LOOP
###########################

country<-c("Norway","Sweden","Finland","France","Greece","Italy","Spain")

for(i in country){

site <- paste("http://www.countryreports.org/country/",country,".htm", sep="")
site <- html(site)

stats<-
data.frame(names =site %>% html_nodes(xpath="//*/td[1]") %>% html_text() ,
         facts =site %>% html_nodes(xpath="//*/td[2]") %>% html_text() ,
       stringsAsFactors=FALSE)

stats$country <- country
stats$names   <- gsub('[\r\n\t]', '', stats$names)
stats$facts   <- gsub('[\r\n\t]', '', stats$facts)

stats<-rbind(stats,stats)
stats<-stats[!duplicated(stats),]
}

Ошибка:

Error: length(url) == 1 is not TRUE
In addition: Warning message:
In if (grepl("^http", x)) { :
  the condition has length > 1 and only the first element will be used

person Chris L    schedule 08.01.2015    source источник
comment
Здесь тот же результат. Я попробовал этот код и получил такое же сообщение об ошибке даже в не-цикле, который работал! › length(сайт) [1] 7 › stopifnot(длина(сайт) == 1) Ошибка: длина(сайт) == 1 неверно   -  person lawyeR    schedule 08.01.2015
comment
В этой строке: site <- paste("http://www.countryreports.org/country/",country,".htm", sep="") вы используете country, что в циклической версии является вектором символов со всеми вашими странами. Вы, вероятно, хотите i, который является одним из элементов вектора вашей страны.   -  person zelite    schedule 08.01.2015
comment
zelite - это сделало меня намного ближе - спасибо.   -  person Chris L    schedule 09.01.2015
comment
Спасибо вам обоим за помощь. Я добавлю окончательный рабочий код для справки - надеюсь, это кому-то поможет!   -  person Chris L    schedule 09.01.2015


Ответы (3)


Окончательный рабочий код:

###########################
# THIS WORKS!!!!
###########################

country<-c("Norway","Sweden","Finland","France","Greece","Italy","Spain")

for(i in country){

site <- paste("http://www.countryreports.org/country/",i,".htm", sep="")
site <- html(site)

stats<-
data.frame(names =site %>% html_nodes(xpath="//*/td[1]") %>% html_text() ,
     facts =site %>% html_nodes(xpath="//*/td[2]") %>% html_text() ,
       stringsAsFactors=FALSE)

stats$nm <- i
stats$names   <- gsub('[\r\n\t]', '', stats$names)
stats$facts   <- gsub('[\r\n\t]', '', stats$facts)
#stats<-stats[!duplicated(stats),]
all<-rbind(all,stats)

}
 View(all)
person Chris L    schedule 09.01.2015
comment
Это действительно работает для вас? Стремясь сделать то же самое, запустил ваш код и получил следующую ошибку: Ошибка в rep(xi, length.out = nvar): попытка реплицировать объект типа «встроенный». Вы инициировали все где-то раньше? - person Z_D; 24.05.2015

Просто инициализируйте пустой кадр данных перед циклом. Я решил эту проблему, и следующий код отлично работает для меня.

country<-c("Norway","Sweden","Finland","France","Greece","Italy","Spain")
df <- data.frame(names = character(0),facts = character(0),nm = character(0))

for(i in country){

  site <- paste("http://www.countryreports.org/country/",i,".htm", sep="")
  site <- html(site)

  stats<-
    data.frame(names =site %>% html_nodes(xpath="//*/td[1]") %>% html_text() ,
               facts =site %>% html_nodes(xpath="//*/td[2]") %>% html_text() ,
               stringsAsFactors=FALSE)

  stats$nm <- i
  stats$names   <- gsub('[\r\n\t]', '', stats$names)
  stats$facts   <- gsub('[\r\n\t]', '', stats$facts)
  #stats<-stats[!duplicated(stats),]
  #all<-rbind(all,stats)
  df <- rbind(df, stats)
  #all <- merge(Output,stats)

}
View(df)
person Premal    schedule 08.01.2018

Это то, что я сделал. Это не лучшее решение, но выход вы получите. Кроме того, это только обходной путь. Я не рекомендую вам записывать вывод таблицы в файл во время выполнения цикла. Ну вот. После того, как выходные данные сгенерированы из stats,

output<-rbind(stats,i)

а затем напишите таблицу,

write.table(output, file = "D:\\Documents\\HTML\\Test of loop.csv", row.names = FALSE, append = TRUE, sep = ",")

#then close the loop
}

Удачи

person SKD    schedule 20.09.2016