Извлечение html-таблицы с веб-сайта в R

Привет, я пытаюсь извлечь таблицу с веб-сайта premierleague.

Я использую пакет rvest, а код, который я использую на начальном этапе, выглядит следующим образом:

library(rvest)
library(magrittr)
premierleague <- read_html("https://fantasy.premierleague.com/a/entry/767830/history")
premierleague %>% html_nodes("ism-table")

Я не смог найти HTML-тег, с помощью которого можно было бы извлечь пакет html_nodes for rvest.

Я использовал аналогичный подход для извлечения данных из «http://admissions.calpoly.edu/prospective/profile.html", и я смог извлечь данные. Код, который я использовал для calpoly, выглядит следующим образом:

library(rvest)
library(magrittr)
CPadmissions <- read_html("http://admissions.calpoly.edu/prospective/profile.html")

CPadmissions %>% html_nodes("table") %>%
  .[[1]] %>%
  html_table()

Получил приведенный выше код с YouTube по этой ссылке: https://www.youtube.com/watch?v=gSbuwYdNYLM&ab_channel=EvanO%27Brien

Любая помощь в получении данных с fantasy.premierleague.com приветствуется. Нужно ли использовать какой-то API?


person Jd Baba    schedule 05.01.2017    source источник


Ответы (2)


Поскольку данные загружаются с помощью JavaScript, захват HTML с помощью rvest не даст вам того, что вы хотите, но если вы используете PhantomJS в качестве безголового браузера в RSelenium, это не так уж сложно (по стандартам RSelenium):

library(RSelenium)
library(rvest)

# initialize browser and driver with RSelenium
ptm <- phantom()
rd <- remoteDriver(browserName = 'phantomjs')
rd$open()

# grab source for page
rd$navigate('https://fantasy.premierleague.com/a/entry/767830/history')
html <- rd$getPageSource()[[1]]

# clean up
rd$close()
ptm$stop()

# parse with rvest
df <- html %>% read_html() %>% 
    html_node('#ismr-event-history table.ism-table') %>% 
    html_table() %>% 
    setNames(gsub('\\S+\\s+(\\S+)', '\\1', names(.))) %>%    # clean column names
    setNames(gsub('\\s', '_', names(.)))

str(df)
## 'data.frame':    20 obs. of  10 variables:
##  $ Gameweek                : chr  "GW1" "GW2" "GW3" "GW4" ...
##  $ Gameweek_Points         : int  34 47 53 51 66 66 65 63 48 90 ...
##  $ Points_Bench            : int  1 6 9 7 14 2 9 3 8 2 ...
##  $ Gameweek_Rank           : chr  "2,406,373" "2,659,789" "541,258" "905,524" ...
##  $ Transfers_Made          : int  0 0 2 0 3 2 2 0 2 0 ...
##  $ Transfers_Cost          : int  0 0 0 0 4 4 4 0 0 0 ...
##  $ Overall_Points          : chr  "34" "81" "134" "185" ...
##  $ Overall_Rank            : chr  "2,406,373" "2,448,674" "1,914,025" "1,461,665" ...
##  $ Value                   : chr  "£100.0" "£100.0" "£99.9" "£100.0" ...
##  $ Change_Previous_Gameweek: logi  NA NA NA NA NA NA ...

Как всегда, требуется дополнительная очистка, но в целом он в довольно хорошем состоянии без особых усилий. (Если вы используете tidyverse, df %>% mutate_if(is.character, parse_number) вполне подойдет.) Стрелки — это изображения, поэтому в последнем столбце все NA, но вы все равно можете их вычислить.

person alistaire    schedule 06.01.2017
comment
Я получил сообщение об ошибке Ошибка в phantom(): двоичный файл PhantomJS не найден. с ptm <- phantom(). Любая идея, что происходит? Я скачал phantomJS - person Cyrus Mohammadian; 06.01.2017
comment
Да, сначала нужно установить. В Windows webshot::install_phantomjs сделает это за вас; в macOS прекрасно работает домашнее пиво, а в любой системе вы можете использовать установить вручную. - person alistaire; 06.01.2017
comment
Да, у меня проблемы с доморощенным пивом, и я добавил двоичный файл в /usr/local/bin/, но ничего не изменилось. - person Cyrus Mohammadian; 06.01.2017
comment
Это странно; у него нет никаких зависимостей, и у вас не должно быть проблем с PATH с /usr/local/bin. Как это не удается? Работает ли phantomjs --version в командной строке? В RSelenium есть обширная виньетка, которая может указать вы в правильном направлении. - person alistaire; 06.01.2017
comment
Да, в терминале показывает, что работает (версия 2.1.1). Я установил phantomJS с помощью npm и теперь получаю новую ошибку: [ОШИБКА - 2017-01-06T01:42:36.152Z] GhostDriver - main.fail - {строка: 85, sourceURL: phantomjs://code/main.js, stack:global code@phantomjs://code/main.js:85:56} phantomjs://platform/console++.js:263 с ошибкой - person Cyrus Mohammadian; 06.01.2017
comment
Ой! Вы пытаетесь запустить все сразу (не построчно)? RSelenium управляет реальным браузером, а браузерам требуется время, чтобы что-то сделать, поэтому, если вы помещаете его в скрипт, вам может потребоваться вставить Sys.sleep(5) после заданий, которые занимают некоторое время. Иногда помогает повторный запуск, но весь процесс немного менее детерминирован, чем обычный код R. - person alistaire; 06.01.2017
comment
Спасибо за помощь. Я запускал его построчно, но запуск в целом дает тот же набор ошибок. - person Cyrus Mohammadian; 06.01.2017
comment
Я создал сообщение по теме: stackoverflow.com/questions /41497898/ - person Cyrus Mohammadian; 06.01.2017
comment
@алистер +1 . Большое спасибо за публикацию ответа. Однако, когда я загрузил phantomjs, как мне установить этот файл exe или мне нужно сослаться на этот phantomjs.exe из R. Мне не хватает этой простой процедуры. - person Jd Baba; 06.01.2017
comment
@CyrusMohammadian Странно. Возможно, вы могли бы управлять PhantomJS через сервер Selenium вместо его собственного режима веб-драйвера (см. второй раздел виньетки). - person alistaire; 06.01.2017
comment
@Jdbaba Я не в Windows, но это просто должно быть где-то, где RSelenium может его найти. Если он не может (надеюсь, он скажет вам об этом) и исправление переменных среды слишком сложно, phantom имеет параметр pjs_cmd, вы можете передать путь к исполняемому файлу. - person alistaire; 06.01.2017

В этом решении используется RSelenium вместе с пакетом XML. Также предполагается, что у вас есть работающая установка RSelenium, которая может правильно работать с firefox. Просто убедитесь, что путь начального сценария firefox добавлен к вашему PATH.

Если вы используете OS X, вам нужно будет добавить /Applications/Firefox.app/Contents/MacOS/ к вашему PATH. Или, если вы работаете на машине с Ubuntu, скорее всего, это /usr/lib/firefox/. Как только вы убедитесь, что это работает, вы можете перейти к R со следующим:

# Install RSelenium and XML for R
#install.packages("RSelenium")
#install.packages("XML")

# Import packages
library(RSelenium)
library(XML)

# Check and start servers for Selenium
checkForServer()
startServer()

# Use firefox as a browser and a port that's not used
remote_driver <- remoteDriver(browserName="firefox", port=4444)
remote_driver$open(silent=T)

# Use RSelenium to browse the site
epl_link <- "https://fantasy.premierleague.com/a/entry/767830/history"
remote_driver$navigate(epl_link)
elem <- remote_driver$findElement(using="class", value="ism-table")

# Get the HTML source
elemtxt <- elem$getElementAttribute("outerHTML")

# Use the XML package to work with the HTML source
elem_html <- htmlTreeParse(elemtxt, useInternalNodes = T, asText = TRUE)

# Convert the table into a dataframe
games_table <- readHTMLTable(elem_html, header = T, stringsAsFactors = FALSE)[[1]]

# Change the column names into something legible
names(games_table) <- unlist(lapply(strsplit(names(games_table), split = "\\n\\s+"), function(x) x[2]))
names(games_table) <- gsub("£", "Value", gsub("#", "CPW", gsub("Â","",names(games_table))))

# Convert the fields into numeric values
games_table <- transform(games_table, GR = as.numeric(gsub(",","",GR)),
                    OP = as.numeric(gsub(",","",OP)),
                    OR = as.numeric(gsub(",","",OR)),
                    Value = as.numeric(gsub("£","",Value)))

Это должно дать:

 GW   GP PB GR     TM TC    OP   OR    Value CPW
 GW1  34 1  2406373 0  0    34 2406373 100.0    
 GW2  47 6  2659789 0  0    81 2448674 100.0    
 GW3  53 9   541258 2  0   134 1914025  99.9    
 GW4  51 7   905524 0  0   185 1461665 100.0    
 GW5  66 14  379438 3  4   247  958889 100.1    
 GW6  66 2   303704 2  4   309  510376  99.9    
 GW7  65 9   138792 2  4   370  232474  99.8    
 GW8  63 3   108363 0  0   433   87967 100.4    
 GW9  48 8  1114609 2  0   481   75385 100.9    
 GW10 90 2    71210 0  0   571   27716 101.1    
 GW11 71 2   421706 3  4   638   16083 100.9    
 GW12 35 9  2798661 2  4   669   31820 101.2    
 GW13 41 8  2738535 1  0   710   53487 101.1    
 GW14 82 15  308725 0  0   792   29436 100.2    
 GW15 55 9  1048808 2  4   843   29399 100.6    
 GW16 49 8  1801549 0  0   892   35142 100.7    
 GW17 48 4  2116706 2  0   940   40857 100.7    
 GW18 42 2  3315031 0  0   982   78136 100.8    
 GW19 41 9  2600618 0  0  1023   99048 100.6    
 GW20 53 0  1644385 0  0  1076  113148 100.8

Обратите внимание, что столбец CPW (изменение по сравнению с предыдущей неделей) представляет собой вектор пустых строк.

Надеюсь, это поможет.

person Abdou    schedule 06.01.2017