Scraping di dati da tabelle su più pagine Web in R (giocatori di football)

Sto lavorando a un progetto per la scuola in cui ho bisogno di raccogliere le statistiche sulla carriera per i singoli giocatori di football NCAA. I dati per ogni giocatore sono in questo formato.

http://www.sports-reference.com/cfb/players/ryan-aplin-1.html

Non riesco a trovare un aggregato di tutti i giocatori, quindi ho bisogno di andare pagina per pagina e tirare fuori la riga in basso di ogni tabella html che scorre punteggio e ricezione ecc.

Ogni giocatore è catagorizzato dal loro cognome con collegamenti ad ogni alfabeto che va qui.

http://www.sports-reference.com/cfb/players/

Ad esempio, ogni giocatore con il cognome A è trovato qui.

http://www.sports-reference.com/cfb/players/a-index.html

Questa è la mia prima volta che mi sto dedicando davvero allo scraping dei dati, quindi ho cercato di trovare domande simili con le risposte. La risposta più vicina che ho trovato è stata questa domanda

Credo che potrei usare qualcosa di molto simile dove cambio il numero di pagina con il nome del giocatore raccolto. Tuttavia, non sono sicuro di come cambiarlo per cercare il nome del giocatore invece del numero di pagina.

Samuel L. Ventura ha anche recentemente tenuto un discorso sul data scraping per i dati NFL che possono essere trovati qui .

MODIFICARE:

Ben è stato davvero d’aiuto e ha fornito un ottimo codice. La prima parte funziona davvero bene, tuttavia quando cerco di eseguire la seconda parte mi imbatto in questo.

> # unlist into a single character vector > links  # Go to each URL in the list and scrape all the data from the tables > # this will take some time... don't interrupt it! > all_tables  # Put player names in the list so we know who the data belong to > # extract names from the URLs to their stats page... > toMatch  player_names  # assign player names to list of tables > names(all_tables)  fix(inx_page) Error in edit(name, file, title, editor) : unexpected '<' occurred on line 1 use a command like x <- edit() to recover In addition: Warning message: In edit.default(name, file, title, editor = defaultEditor) : deparse may be incomplete 

Questo potrebbe essere un errore a causa della mancanza di memoria sufficiente (solo 4 GB sul computer attualmente in uso). Anche se non capisco l’errore

  > all_tables <- lapply(links, readHTMLTable, stringsAsFactors = FALSE) Error in UseMethod("xmlNamespaceDefinitions") : no applicable method for 'xmlNamespaceDefinitions' applied to an object of class "NULL" 

Guardando attraverso i miei altri set di dati, i miei giocatori torneranno davvero solo nel 2007. Se ci fosse un modo per attirare solo persone dal 2007 in poi, questo potrebbe aiutare a ridurre i dati. Se avessi una lista di persone i cui nomi volevo estrarre potrei semplicemente sostituire il lnk in

  links[[i]] <- paste0("http://www.sports-reference.com", lnk) 

con solo i giocatori di cui ho bisogno?

Ecco come puoi ottenere facilmente tutti i dati in tutte le tabelle su tutte le pagine dei giocatori …

Prima di tutto fai un elenco degli URL per tutte le pagine dei giocatori …

 require(RCurl); require(XML) n <- length(letters) # pre-allocate list to fill links <- vector("list", length = n) for(i in 1:n){ print(i) # keep track of what the function is up to # get all html on each page of the az index pages inx_page <- htmlParse(getURI(paste0("http://www.sports-reference.com/cfb/players/", letters[i], "-index.html"))) # scrape URLs for each player from each index page lnk <- unname(xpathSApply(inx_page, "//a/@href")) # skip first 63 and last 10 links as they are constant on each page lnk <- lnk[-c(1:63, (length(lnk)-10):length(lnk))] # only keep links that go to players (exclude schools) lnk <- lnk[grep("players", lnk)] # now we have a list of all the URLs to all the players on that index page # but the URLs are incomplete, so let's complete them so we can use them from # anywhere links[[i]] <- paste0("http://www.sports-reference.com", lnk) } # unlist into a single character vector links <- unlist(links) 

Ora abbiamo un vettore di circa 67.000 URL (sembra un sacco di giocatori, può essere giusto?), Quindi:

In secondo luogo, raschiare tutte le tabelle a ogni URL per ottenere i loro dati, in questo modo:

 # Go to each URL in the list and scrape all the data from the tables # this will take some time... don't interrupt it! # start edit1 here - just so you can see what's changed # pre-allocate list all_tables <- vector("list", length = (length(links))) for(i in 1:length(links)){ print(i) # error handling - skips to next URL if it gets an error result <- try( all_tables[[i]] <- readHTMLTable(links[i], stringsAsFactors = FALSE) ); if(class(result) == "try-error") next; } # end edit1 here # Put player names in the list so we know who the data belong to # extract names from the URLs to their stats page... toMatch <- c("http://www.sports-reference.com/cfb/players/", "-1.html") player_names <- unique (gsub(paste(toMatch,collapse="|"), "", links)) # assign player names to list of tables names(all_tables) <- player_names 

Il risultato è simile a questo (questo è solo un frammento dell'output):

 all_tables $`neli-aasa` $`neli-aasa`$defense Year School Conf Class Pos Solo Ast Tot Loss Sk Int Yds Avg TD PD FR Yds TD FF 1 *2007 Utah MWC FR DL 2 1 3 0.0 0.0 0 0 0 0 0 0 0 0 2 *2010 Utah MWC SR DL 4 4 8 2.5 1.5 0 0 0 1 0 0 0 0 $`neli-aasa`$kick_ret Year School Conf Class Pos Ret Yds Avg TD Ret Yds Avg TD 1 *2007 Utah MWC FR DL 0 0 0 0 0 0 2 *2010 Utah MWC SR DL 2 24 12.0 0 0 0 0 $`neli-aasa`$receiving Year School Conf Class Pos Rec Yds Avg TD Att Yds Avg TD Plays Yds Avg TD 1 *2007 Utah MWC FR DL 1 41 41.0 0 0 0 0 1 41 41.0 0 2 *2010 Utah MWC SR DL 0 0 0 0 0 0 0 0 0 

Infine, diciamo che vogliamo solo guardare i tavoli che passano ...

 # just show passing tables passing <- lapply(all_tables, function(i) i$passing) # but lots of NULL in here, and not a convenient format, so... passing <- do.call(rbind, passing) 

E finiamo con una cornice dati pronta per ulteriori analisi (anche solo un frammento) ...

  Year School Conf Class Pos Cmp Att Pct Yds Y/A AY/A TD Int Rate james-aaron 1978 Air Force Ind QB 28 56 50.0 316 5.6 3.6 1 3 92.6 jeff-aaron.1 2000 Alabama-Birmingham CUSA JR QB 100 182 54.9 1135 6.2 6.0 5 3 113.1 jeff-aaron.2 2001 Alabama-Birmingham CUSA SR QB 77 148 52.0 828 5.6 4.3 4 6 99.8