Quét các bảng html vào các khung dữ liệu R bằng gói XML


153

Làm cách nào để quét các bảng html bằng gói XML?

Lấy ví dụ, trang wikipedia này về đội bóng đá Brazil . Tôi muốn đọc nó trong R và lấy bảng "danh sách tất cả các trận đấu mà Brazil đã thi đấu với các đội được FIFA công nhận" dưới dạng data.frame. Tôi có thể làm cái này như thế nào?


11
Để tìm ra các công cụ chọn xpath, hãy xem selectorgadget.com/ - thật tuyệt vời
hadley

Câu trả lời:


144

Hãy thử hoặc ngắn hơn:

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]))

cái bàn được chọn là cái dài nhất trên trang

tables[[which.max(n.rows)]]

Trợ giúp readHTMLTable cũng cung cấp một ví dụ về việc đọc bảng văn bản đơn giản từ phần tử HTML PRE bằng cách sử dụng htmlPude (), getNodeSet (), textConnection () và 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)

Chỉnh sửa để thêm:

Sản lượng mẫu

                     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%
    ...

7
Đối với bất kỳ ai khác may mắn tìm thấy bài đăng này, tập lệnh này có thể sẽ không được thực thi trừ khi người dùng thêm thông tin "Tác nhân người dùng" của họ, như được mô tả trong bài đăng hữu ích khác này: stackoverflow.com/questions/9056705/
Thẻ

26

Một tùy chọn khác sử dụng 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

Tạo ra kết quả này

> 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%

Cuộc gọi tuyệt vời trên xpath. Điểm nhỏ: bạn có thể đơn giản hóa một chút đối số đường dẫn bằng cách thay đổi // * / thành //, ví dụ: "// bảng [@ class = 'wikitable sortable'] / tr / th"
Richie Cotton

Tôi gặp lỗi "Tập lệnh nên sử dụng chuỗi Tác nhân người dùng thông tin có thông tin liên hệ hoặc chúng có thể bị chặn IP mà không cần thông báo trước." [2] "Có cách nào để thực hiện phương pháp này không?
pssguy

2
tùy chọn (RCurlOptions = list (useragent = "zzzz")). Xem thêm omegahat.org/RCurl/FAQ.html phần "Thời gian chạy" để biết các lựa chọn và thảo luận khác.
học

25

Các rvestcùng với xml2là một gói phổ biến cho các phân tích trang 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)

Cú pháp dễ sử dụng hơn xmlgói và đối với hầu hết các trang web, gói cung cấp tất cả các tùy chọn cần.


Read_html cung cấp cho tôi lỗi "'tệp: ///Users/grieb/Auswertungen/tetyana-snp-2016/data/snp-nexus/15/SNP%20Annotation%20Tool.html' không tồn tại trong thư mục làm việc hiện tại (' / Người dùng / grieb / Auswertungen / tetyana-snp-2016 / code '). "
scs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.