2009-09-08 3 views
129

Как очистить таблицы html с помощью пакета XML?Скремблирование html-таблиц в R-кадров данных с использованием пакета XML

Возьмите, к примеру, эту страницу в Википедии на Brazilian soccer team. Я хотел бы прочитать его в R и получить «список всех матчей, проведенных Бразилией против команды FIFA признанных команд» в качестве data.frame. Как я могу это сделать?

+9

Чтобы решить выбор селекторов xpath, выберите selectorgadget.com/ - это потрясающе – hadley

ответ

122

... или короче попробовать:

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

отборные таблица является самым длинным на странице

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

Справка readHTMLTable также предоставляет пример чтения таблицы обычного текста из элемента HTML PRE с использованием htmlParse(), getNodeSet(), textConnection() и read.table() –

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

Edited добавить:

Пример вывода

     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

Для всех, кому посчастливилось найти это сообщение, этот скрипт, скорее всего, не будет выполняться, если пользователь не добавит свою информацию «Пользователь-агент», как описано в этом другом полезном сообщении: http://stackoverflow.com/questions/9056705/setting-an-informative-user-agent-string-in-geturl – Rguy

23

Другой вариант использования 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 

Производит этот результат

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

Отличный вызов при использовании xpath. Незначительная точка: вы можете немного упростить аргумент пути, изменив // */на //, например. "// table [@ class = 'wikitable sortable']/tr/th" –

+0

Я получаю сообщение об ошибке "Сценарии должны использовать информативную строку User-Agent с контактной информацией, или они могут быть заблокированы IP без уведомления". [2] «Есть ли способ обойти это для реализации этого метода? – pssguy

+2

опции (RCurlOptions = list (useragent =" zzzz ")). См. Также http://www.omegahat.org/RCurl/FAQ.html раздел" Runtime "для других альтернатив и обсуждения. – learnr

14

rvest вдоль с xml2 - еще один популярный пакет для разбора htm l веб-страниц.

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) 

Синтаксис проще в использовании, чем пакет XML и для большинства веб-страницы или код XML обеспечивает все потребности варианты Ones.

+0

Read_html дает me, файл ошибки: «///Users/grieb/Auswertungen/tetyana-snp-2016/data/snp-nexus/15/SNP%20Annotation%20Tool.html» не существует в текущем рабочем каталоге ('/ Users/Grieb/Auswertungen/Тетяна-SNP-2016/код ")«. – scs