Я делаю некоторые базовые веб-скрейпинги с помощью RVest и получаю результаты для возврата, однако данные не совпадают друг с другом. Это означает, что я получаю элементы, но они не в порядке с сайта, поэтому 2 элемента данных, которые я очищаю, не могут быть объединены в data.frame.
library(rvest)
library(tidyverse)
base_url<- "https://www.uchealth.com/providers"
loc <- read_html(base_url) %>%
html_nodes('[class=locations]') %>%
html_text()
dept <- read_html(base_url) %>%
html_nodes('[class=department last]') %>%
html_text()
Я ожидал, что смогу создать фрейм данных:
Location Department
Какие-либо предложения? Мне было интересно, есть ли индекс, который будет хранить эти элементы вместе, но я ничего не видел.
Обновлено: я тоже пробовал это, и мне не повезло. Кажется, что местоположение получает ошибочное начальное значение:
scraping <- function(
base_url = "https://www.uchealth.com/providers"
)
{
loc <- read_html(base_url) %>%
html_nodes('[class=locations]') %>%
html_text()
dept <- read_html(base_url) %>%
html_nodes('[class=specialties]') %>%
html_text()
data.frame(
loc = ifelse(length(loc)==0, NA, loc),
dept = ifelse(length(dept)==0, NA, loc),
stringsAsFactors=F
)
}
этот [stackoverflow.com/questions/33250826/… кажется похожим на то, что я пытаюсь сделать. Я редактировал выше, но не повезло
Небольшой совет: будьте добры к веб-сайтам, не копируя одну и ту же страницу более одного раза. Вместо этого назначьте свой вывод read_html переменной, а затем извлеките данные из этой переменной.





Проблема, с которой вы столкнулись, заключается в том, что не каждый дочерний узел присутствует во всех родительских узлах. Лучший способ справиться с такими ситуациями — собрать все родительские узлы в список/вектор, а затем извлечь нужную информацию из каждого родителя с помощью функции html_node. html_node всегда будет возвращать 1 результат для каждого узла, даже если это NA.
library(rvest)
#read the page just onece
base_url<- "https://www.uchealth.com/providers"
page <- read_html(base_url)
#parse out the parent node for each parent
providers<-page %>% html_nodes('ul[id=providerlist]') %>% html_children()
#parse out the requested information from each child.
dept<-providers %>% html_node("[class ^= 'department']") %>% html_text()
location<-providers %>%html_node('[class=locations]') %>% html_text()
Длина провайдеров, отдела и местоположения должна быть одинаковой.
Я раньше не видел ^ в [class ^= 'department']. Что оно делает?
@gersht, ^ означает, что начинается с. Таким образом, class ^= 'department' означает класс, который начинается с «отдела», у меня возникают проблемы с пониманием пробелов в именах атрибутов или классов.
Это решение сработало именно так, как я ожидал. Спасибо за ваше время!
Один, гораздо более сложный вариант, состоит в том, чтобы сначала превратить все доступные данные в каждом узле .searchresult в фрейм данных, а затем сложить их с помощью dplyr::bind_rows. Я думаю, что это выходит за рамки ваших основных требований, но по-прежнему отвечает на ваш вопрос окольным путем и может быть полезно для более общего случая:
library(rvest)
library(tidyverse)
base_url<- "https://www.uchealth.com/providers"
html <- read_html(base_url)
# Extract `.searchresult` nodes.
res_list <- html %>%
html_nodes(".searchresult") %>%
unclass()
# Turn each node into a dataframe.
df_list <- res_list %>%
map(~ {html_nodes(., ".propertylist li") %>%
html_text(T) %>%
str_split(":", 2) %>%
map(~ str_trim(.) %>% cbind() %>% as_tibble()) %>%
bind_cols() %>%
set_names(.[1,]) %>%
.[-1,]
})
# Stack the dataframes, add the person names, and reorder the columns.
ucdf <- bind_rows(df_list) %>%
mutate(Name = map_chr(res_list, ~ html_node(., "h4") %>% html_text(T))) %>%
select(Name, 1:(ncol(.)-1))
Что возвращает:
# A tibble: 1,137 x 5
Name Title Locations Specialties Department
<chr> <chr> <chr> <chr> <chr>
1 Adrian Abre… Assistant Professor of Med… UC Health Physicians Office South (West Chest… nephrology Internal Medicine
2 Bassam G. A… Associate Professor of Cli… University of Cincinnati Medical Center: (513… nephrology, organ trans… Internal Medicine
3 Brian Adams… Professor, Director of Res… UC Health Physicians Office (Clifton - Piedmo… dermatology Dermatology
4 Opeolu M. A… Associate Professor of Eme… University of Cincinnati Medical Center: (513… emergency medicine, neu… Emergency Medicine
5 Caleb Adler… Professor in the Departmen… UC Health Psychiatry (Stetson Building): (513… psychiatrypsychology, m… Psychiatry & Beha…
6 John Adler,… Assistant Professor of Obs… UC Health Women's Center: (513) 475-8248, UC … gynecology, robotic sur… OB/GYN
7 Steven S. A… Assistant Professor UC Health Physicians Office (Clifton - Piedmo… orthopaedics, spine sur… Orthopaedics & Sp…
8 Surabhi Aga… Assistant Professor of Med… Hoxworth Center: (513) 475-8524, UC Health Ph… rheumatology, connectiv… Internal Medicine
9 Saad S. Ahm… Assistant Professor of Med… Hoxworth Center: (513) 584-7217 cardiovascular disease,… Internal Medicine
10 Syed Ahmad,… Professor of Surgery; Dire… UC Health Barrett Cancer Center: (513) 584-89… surgical oncology, canc… Surgery
# … with 1,127 more rows
Спасибо, это тоже похоже на жизнеспособное решение
@Brad_J рад, что это помогает. Хороший способ сказать спасибо на SO - это проголосовать, даже если вы не принимаете ответ. Другие видят голоса чаще, чем комментарии, и это дает им понять, что кто-то нашел ответ полезным.
не уверен, что понимаю ваш вопрос, но, может быть, stackoverflow.com/questions/41708685/…