Перебирая список веб-страниц с помощью rvest follow_link - PullRequest
0 голосов
/ 06 декабря 2018

Я пытаюсь создать календарь правительственных релизов: https://www.gov.uk/government/statistics и использовать функцию rvest follow_link, чтобы перейти к каждой ссылке на публикацию и почистить текст со следующей страницы.У меня это работает для каждой отдельной страницы результатов (40 публикаций отображаются на странице), но я не могу заставить цикл работать так, чтобы я мог запустить код для всех перечисленных публикаций.

Это кодСначала я запускаю, чтобы получить список публикаций (только с первых 10 страниц результатов):

#Loading the rvest package
library('rvest')
library('dplyr')
library('tm')

#######PUBLISHED RELEASES################

###function to add number after 'page=' in url to loop over all pages of published releases results (only 40 publications per page)
###check the site and see how many pages you want to scrape, to cover months of interest
##titles of publications - creates a list
publishedtitles <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
                 function(url_base){
                   url_base %>% read_html() %>% 
                     html_nodes('h3 a') %>% 
                     html_text()
                 })


##Dates of publications
publisheddates <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
                 function(url_base){
                   url_base %>% read_html() %>% 
                     html_nodes('.public_timestamp') %>% 
                     html_text()
                 })
##Organisations
publishedorgs <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
                function(url_base){
                  url_base %>% read_html() %>% 
                    html_nodes('.organisations') %>% 
                    html_text()
                })
##Links to publications
publishedpartial_links <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
               function(url_base){
                 url_base %>% read_html() %>% 
                   html_nodes('h3 a') %>% 
                   html_attr('href') 
               })

#Check all lists are the same length - if not, have to deal with missings before next step
# length(publishedtitles)
# length(publisheddates)
# length(publishedorgs)
# length(publishedpartial_links)
#str(publishedorgs)

#Combining all the lists to form a data frame
published <-data.frame(Title = unlist(publishedtitles), Date = unlist(publisheddates), Organisation = unlist(publishedorgs), PartLinks = unlist(publishedpartial_links))

#adding prefix to partial links, to turn into full URLs
published$Links = paste("https://www.gov.uk", published$PartLinks, sep="")
#Drop partial links column
keeps <- c("Title", "Date", "Organisation", "Links")
published <- published[keeps]

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

session1 <- html_session("https://www.gov.uk/government/statistics?page=1")
list1 <- list()
for(i in published$Title[1:40]){
  nextpage1 <- session1 %>% follow_link(i) %>% read_html()
  list1[[i]]<- nextpage1 %>%
    html_nodes(".grid-row") %>% html_text()
  df1 <- data.frame(text=list1)
  df1 <-as.data.frame(t(df1))
}

Таким образом, приведенное выше необходимо изменить page = 1 в html_session, а также публикацию $ Title [1:40] - я борюсь с созданием функции или цикла, который включает обе переменные.

Я думаю, что я мог бы сделать это, используя lapply:

df <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
                          function(url_base){
                              for(i in published$Title[1:40]){
                                nextpage1 <- url_base %>% follow_link(i) %>% read_html()
                                list1[[i]]<- nextpage1 %>%
                                  html_nodes(".grid-row") %>% html_text()
                              }
                          }
)

Но я получаю ошибку

Error in follow_link(., i) : is.session(x) is not TRUE

Я также пробовал другие методы зацикливанияи превращая его в функцию, но не хотел делать этот пост слишком длинным!

Заранее благодарен за любые предложения и рекомендации:)

1 Ответ

0 голосов
/ 06 декабря 2018

Похоже, вам просто нужно начать сеанс внутри функции lapply.В последнем фрагменте кода url_base - это просто текстовая строка с базовым URL.Хотелось бы что-то вроде этой работы:

df <- lapply(paste0('https://www.gov.uk/government/statistics?page=', 1:10),
                        function(url_base){
                            for(i in published$Title[1:40]){
                                tmpSession <- html_session(url_base)
                                nextpage1 <- tmpSession %>% follow_link(i) %>% read_html()
                                list1[[i]]<- nextpage1 %>%
                                html_nodes(".grid-row") %>% html_text()
                            }
                        }
)

Чтобы изменить published$Title[1:40] для каждой итерации функции lapply, вы могли бы создать объект, который содержит нижнюю и верхнюю границы индексов:

lowers <- cumsum(c(1, rep(40, 9)))
uppers <- cumsum(rep(40, 10))

Затем вы могли бы включить тех, кто в вызове lapply

df <- lapply(1:10, function(j){
    url_base <- paste0('https://www.gov.uk/government/statistics?page=', j)
    for(i in published$Title[lowers[j]:uppers[j]]){
        tmpSession <- html_session(url_base)
        nextpage1 <- tmpSession %>% follow_link(i) %>% read_html()
        list1[[i]]<- nextpage1 %>%
        html_nodes(".grid-row") %>% html_text()
    }
}
)

Не уверен, что это то, что вы хотите или нет, я мог бы неправильно понять, что должно бытьменяется.

...