Перебирайте слои URL с помощью R и очищайте данные - PullRequest
0 голосов
/ 25 февраля 2019

Я работаю над школьным проектом, который предполагает использование R для очистки атрибутов игрока от https://www.baseball -reference.com и построения фрейма данных с ними.На сайте все игроки перечислены в алфавитном порядке, и я написал код, который создает URL для каждой буквы ниже:

# every baseball player is identified by their last name, using all the 
letters allows me to build urls with the letters
ltrs <- letters

# create an empty container for the urls
url_container <- c()

# this is the base url I append letters to
url = "https://www.baseball-reference.com/players/"

# use a for loop to create the urls
for(i in 1:length(ltrs)){
  url_start = paste(url, ltrs[i], "/", sep = '')
  url_container = c(url_container, url_start)
}

# print the container to make sure the urls are correctly constructed
url_container

# This Outputs: [1] <https://www.baseball-reference.com/players/a/> 
  <https://www.baseball-reference.com/players/b/> etc.

На каждой странице также есть определенное количество игроков, которые я могу взять.с помощью следующего кода, который выводит список URL-адресов игроков.

player_quantity <- c()

for(i in 1:length(url_container)){
  raw = read_html(url_container[i])
  player_count <- raw %>%
  # this is where the player count lives
  html_nodes(.,xpath="//*[@id='all_players_']/div[1]/h2") %>%
  # cast the value as an integer (it will define how many tags we go through)
  html_text(.)
  player_quantity <- c(player_quantity, player_count)
}

player_quantity <- as.numeric(gsub("([0-9]+).*$", "\\1", player_quantity))
player_quantity

# Outputs this: 
[1]  593 1847 1504  945  352  691 1056 1395   58  505  706  885 2015  337  360  925   49 1065 1894  637
[21]   60  269 1075    0  113   93

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

XPath для игроков выглядят так: "// * [@ id =" div_players_«] / p [1] / a» и вот код, который я написал / скопировал с Чтение таблицы с веб-страницы https с использованием readHTMLTable , но пока он выполняется, похоже, ничего не возвращаети я не уверен почему.

mainweb="https://www.baseball-reference.com/players/"

urls = read_html("https://www.baseball-reference.com/players/a/") %>%
html_nodes("#active a") %>%
html_attrs()

teamdata=c()
j=1
for(i in urls){
  bball <- html(paste(mainweb, i, sep=""))
  teamdata[j]= bball %>%
  html_nodes(paste0("#", gsub("/teams/([A-Z]+)/$","\\1", urls[j], perl=TRUE))) 
  %>%
  html_table()
  j=j+1
}

Любая помощь или идеи будут обязательно оценены!

1 Ответ

0 голосов
/ 25 февраля 2019

Следующее должно привести вас к тому, что у вас будут все имена и связанные с ними ссылки.Оттуда вы сможете зацикливать или отображать ссылки и применять обработку и / или html_table извлечение:

library(tidyverse)
library(rvest)

base_url <- "https://www.baseball-reference.com"

# Only doing this for the first four letters, just change to letters[1:26]
links_by_letter <- paste0(base_url, "/players/", letters[1:4])

# Create a function that returns the links for a given letter
get_links_for_letter <- function(url) {
  # Using httr::RETRY in case we are burdening the server
  link_elements <- read_html(httr::RETRY("GET", url)) %>%
    html_nodes("#div_players_ a")

  links <- link_elements %>%
    html_attr("href") %>%
    paste0(base_url, .) %>%
    set_names(., nm = link_elements %>% html_text)

  return(links)
}

# Make 'safe' version that throws an NA in case we do not get anything back.
safe_get_links_for_letter <- possibly(~ get_links_for_letter(.x), otherwise = NA)

results <- 
  links_by_letter %>%
  map(~ safe_get_links_for_letter(.)) %>%
  map_df(enframe)

head(results)
# # A tibble: 6 x 2
#   name          value                                                       
#   <chr>         <chr>                                                       
# 1 David Aardsma https://www.baseball-reference.com/players/a/aardsda01.shtml
# 2 Hank Aaron    https://www.baseball-reference.com/players/a/aaronha01.shtml
# 3 Tommie Aaron  https://www.baseball-reference.com/players/a/aaronto01.shtml
# 4 Don Aase      https://www.baseball-reference.com/players/a/aasedo01.shtml 
# 5 Andy Abad     https://www.baseball-reference.com/players/a/abadan01.shtml 
# 6 Fernando Abad https://www.baseball-reference.com/players/a/abadfe01.shtml 

tail(results)

# # A tibble: 6 x 2
#   name             value                                                       
#   <chr>            <chr>                                                       
# 1 Radhames Dykhoff https://www.baseball-reference.com/players/d/dykhora01.shtml
# 2 Allan Dykstra    https://www.baseball-reference.com/players/d/dykstal01.shtml
# 3 Lenny Dykstra    https://www.baseball-reference.com/players/d/dykstle01.shtml
# 4 John Dyler       https://www.baseball-reference.com/players/d/dylerjo01.shtml
# 5 Jarrod Dyson     https://www.baseball-reference.com/players/d/dysonja01.shtml
# 6 Sam Dyson        https://www.baseball-reference.com/players/d/dysonsa01.shtml
...