Я новичок в веб-очистке в R и испытываю трудности с циклическим веб-очисткой для создания нескольких уникальных фреймов данных.
Из базового URL-адреса я использую map_df
для извлечения 335 уникальных URL-адресов из двадцати вариантов на базовом URL.
# Common basic URL for multiple pages
url_base <- "url_page=%d"
# Function to pull the specific profile URLs part of a common-named series of URLs
map_df(1:20, function(i) {
pg <- read_html(sprintf(url_base, i))
urls <- pg %>%
rvest::html_nodes('body') %>%
xml2::xml_find_all("//h3[contains(@class, 'heading-large block-tighter')]") %>%
html_node("a") %>%
html_attr("href") %>%
as.data.frame() %>%
rename(url_link = '.')
}) -> url_df # Generates a 335 observation data frame.
urls <- pull(url_df, url_link) # Each URL is unique in composition and length
В отличие от базового URL, в 335 извлеченных URL отсутствует одинаковая длина или шаблон.
Я создаю функцию, которая, как мне известно, работает на один URL, который извлекает три разных фрагмента веб-страницы. Первый кусок представляет собой одну текстовую строку. Второй кусок - это 180 уникальных текстовых строк. Третий кусок - это 180 уникальных текстовых / цифровых символов. Данные не организованы в виде таблицы на веб-странице.
# Including function that is wrapped up in a `for` loop below
# Extract Data Function ####
extract_data <- function(x) {
# Read the web page
rankprofile <- read_html(x) # Single URL from larger URL dataframe
# Find the data rows in the profile page
# Extract University/Program Name
univ_name <- rankprofile %>%
rvest::html_nodes('body') %>%
xml2::xml_find_all("//h1[contains(@class, 'hero-heading flex-media-heading')]") %>%
rvest::html_text() # Extracts 1 text string per page
# Extract the table categories
category <- rankprofile %>%
rvest::html_nodes('body') %>%
xml2::xml_find_all("//div[contains(@id, 'ddb-field')]") %>%
xml2::xml_find_all("//span[contains(@class, 'text-coal flex-medium-8')]") %>%
rvest::html_text() # Extracts 180 unique text strings per page
# Extract the table values
value <- rankprofile %>%
rvest::html_nodes('body') %>%
xml2::xml_find_all("//div[contains(@id, 'ddb-field')]") %>%
xml2::xml_find_all("//span[contains(@class, 'text-strong flex-medium-4 medium-end')]") %>%
rvest::html_text() # Extracts 180 unique stings or numberics per page
# Remove white space and make the extracts into data frames
# Also, name columns
university_name <- univ_name %>%
str_squish() %>%
as.data.frame()
university_name <- university_name %>%
rename(Value = '.') %>%
mutate(Category = "University Name") %>%
select(Category, Value)
cat_df <- category %>%
str_squish() %>%
as.data.frame() %>%
rename(Category = '.')
val_df <- value %>%
str_squish() %>%
as.data.frame() %>%
rename(Value = '.')
# Bind Category and Value columns
# Bind Univeristy Name row to Category & Value
rank_df <- bind_cols(cat_df, val_df) %>%
bind_rows(university_name)
return(rank_df)
}
И вот здесь я столкнулся с проблемой. Я пытаюсь поместить список из 355 URL-адресов в for
l oop, но он возвращает один фрейм данных rank_df
# Attempting a loop for each unique URL in the `url` object
# but the loop returns a single `rank_df` dataframe instead of 335 dataframes
for (i in 1:335) {
x <- urls[i]
extract_rankings(x)
}
Как мне написать последний шаг, чтобы вернуть 355 уникальных данных кадры на основе функции extract_rankings()
?