Memotong tabel html ke dalam bingkai data R menggunakan paket XML

153

Bagaimana cara mengikis tabel html menggunakan paket XML?

Ambil, misalnya, halaman wikipedia ini tentang tim sepak bola Brasil . Saya ingin membacanya di R dan mendapatkan tabel "daftar semua pertandingan yang dimainkan Brasil melawan tim yang diakui FIFA" sebagai data.frame. Bagaimana saya bisa melakukan ini?

Eduardo Leoni
sumber
11
Untuk bekerja di luar pemilih xpath, periksa selectorgadget.com/ - itu mengagumkan
hadley

Jawaban:

144

... atau coba yang lebih singkat:

library(XML)
library(RCurl)
library(rlist)
theurl <- getURL("https://en.wikipedia.org/wiki/Brazil_national_football_team",.opts = list(ssl.verifypeer = FALSE) )
tables <- readHTMLTable(theurl)
tables <- list.clean(tables, fun = is.null, recursive = FALSE)
n.rows <- unlist(lapply(tables, function(t) dim(t)[1]))

meja yang dipilih adalah yang terpanjang di halaman

tables[[which.max(n.rows)]]
Jim G.
sumber
Bantuan readHTMLTable juga memberikan contoh membaca tabel teks biasa dari elemen HTML PRE menggunakan htmlParse (), getNodeSet (), textConnection () dan read.table ()
Dave X
48
library(RCurl)
library(XML)

# Download page using RCurl
# You may need to set proxy details, etc.,  in the call to getURL
theurl <- "http://en.wikipedia.org/wiki/Brazil_national_football_team"
webpage <- getURL(theurl)
# Process escape characters
webpage <- readLines(tc <- textConnection(webpage)); close(tc)

# Parse the html tree, ignoring errors on the page
pagetree <- htmlTreeParse(webpage, error=function(...){})

# Navigate your way through the tree. It may be possible to do this more efficiently using getNodeSet
body <- pagetree$children$html$children$body 
divbodyContent <- body$children$div$children[[1]]$children$div$children[[4]]
tables <- divbodyContent$children[names(divbodyContent)=="table"]

#In this case, the required table is the only one with class "wikitable sortable"  
tableclasses <- sapply(tables, function(x) x$attributes["class"])
thetable  <- tables[which(tableclasses=="wikitable sortable")]$table

#Get columns headers
headers <- thetable$children[[1]]$children
columnnames <- unname(sapply(headers, function(x) x$children$text$value))

# Get rows from table
content <- c()
for(i in 2:length(thetable$children))
{
   tablerow <- thetable$children[[i]]$children
   opponent <- tablerow[[1]]$children[[2]]$children$text$value
   others <- unname(sapply(tablerow[-1], function(x) x$children$text$value)) 
   content <- rbind(content, c(opponent, others))
}

# Convert to data frame
colnames(content) <- columnnames
as.data.frame(content)

Diedit untuk menambahkan:

Output sampel

                     Opponent Played Won Drawn Lost Goals for Goals against  % Won
    1               Argentina     94  36    24   34       148           150  38.3%
    2                Paraguay     72  44    17   11       160            61  61.1%
    3                 Uruguay     72  33    19   20       127            93  45.8%
    ...
Richie Cotton
sumber
7
Bagi siapa pun yang cukup beruntung untuk menemukan posting ini, skrip ini kemungkinan tidak akan dijalankan kecuali pengguna menambahkan informasi "User-Agent" mereka, seperti yang dijelaskan dalam posting bermanfaat lainnya: stackoverflow.com/questions/9056705/…
Rguy
26

Opsi lain menggunakan Xpath.

library(RCurl)
library(XML)

theurl <- "http://en.wikipedia.org/wiki/Brazil_national_football_team"
webpage <- getURL(theurl)
webpage <- readLines(tc <- textConnection(webpage)); close(tc)

pagetree <- htmlTreeParse(webpage, error=function(...){}, useInternalNodes = TRUE)

# Extract table header and contents
tablehead <- xpathSApply(pagetree, "//*/table[@class='wikitable sortable']/tr/th", xmlValue)
results <- xpathSApply(pagetree, "//*/table[@class='wikitable sortable']/tr/td", xmlValue)

# Convert character vector to dataframe
content <- as.data.frame(matrix(results, ncol = 8, byrow = TRUE))

# Clean up the results
content[,1] <- gsub(" ", "", content[,1])
tablehead <- gsub(" ", "", tablehead)
names(content) <- tablehead

Menghasilkan hasil ini

> head(content)
   Opponent Played Won Drawn Lost Goals for Goals against % Won
1 Argentina     94  36    24   34       148           150 38.3%
2  Paraguay     72  44    17   11       160            61 61.1%
3   Uruguay     72  33    19   20       127            93 45.8%
4     Chile     64  45    12    7       147            53 70.3%
5      Peru     39  27     9    3        83            27 69.2%
6    Mexico     36  21     6    9        69            34 58.3%
belajar
sumber
Panggilan luar biasa untuk menggunakan xpath. Minor point: Anda dapat sedikit menyederhanakan argumen path dengan mengubah // * / menjadi //, mis. "// table [@ class = 'wikitable sortable'] / tr / th"
Richie Cotton
Saya mendapatkan kesalahan "Skrip harus menggunakan string Agen-Pengguna informatif dengan informasi kontak, atau mereka mungkin diblokir IP tanpa pemberitahuan." [2] "Apakah ada cara untuk menerapkan metode ini?
pssguy
2
opsi (RCurlOptions = daftar (useragent = "zzzz")). Lihat juga omegahat.org/RCurl/FAQ.html bagian "Runtime" untuk alternatif dan diskusi lainnya.
belajar
25

Paket rvestbersama xml2adalah paket populer lainnya untuk mem-parsing halaman web html.

library(rvest)
theurl <- "http://en.wikipedia.org/wiki/Brazil_national_football_team"
file<-read_html(theurl)
tables<-html_nodes(file, "table")
table1 <- html_table(tables[4], fill = TRUE)

Sintaks lebih mudah digunakan daripada xmlpaket dan untuk sebagian besar halaman web paket menyediakan semua opsi yang dibutuhkan.

Dave2e
sumber
Read_html memberi saya file kesalahan "': ///Users/grieb/Auswertungen/tetyana-snp-2016/data/snp-nexus/15/SNP%20Annotation%20Tool.html' tidak ada di direktori kerja saat ini (' / Pengguna / grieb / Auswertungen / tetyana-snp-2016 / kode '). "
scs