【问题标题】:Extracting html table from a website in R从R中的网站中提取html表
【发布时间】:2017-05-20 16:13:43
【问题描述】:

您好,我正在尝试从premierleague 网站提取表格。

我使用的包是rvest包,我在初始阶段使用的代码如下:

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

我找不到可以提取 html_nodes for rvest 包的 html 标记。

我使用类似的方法从“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 吗?

【问题讨论】:

  • 您需要为此使用某种 API 或 RSelenium,因为页面是动态生成的。因此,很难使用与静态网站一起使用的库。
  • 我是 Rselenium 的新手。你能发布一个我可以遵循的示例脚本吗?

标签: r html-table rvest


【解决方案1】:

由于数据是使用 JavaScript 加载的,因此使用 rvest 获取 HTML 不会得到你想要的,但如果你在 RSelenium 中使用 PhantomJS 作为无头浏览器,它并不是那么复杂(按照 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 %&gt;% mutate_if(is.character, parse_number) 会做得很好。)箭头是图像,这就是为什么最后一列都是NA,但无论如何你都可以计算出来。

【讨论】:

  • 我收到一个错误“phantom() 中的错误:找不到 PhantomJS 二进制文件。”与ptm &lt;- phantom()。知道发生了什么吗?我已经下载了 phantomJS
  • 是的,你必须先安装它。在 Windows 上,webshot::install_phantomjs 将为您完成;在 macOS 上,homebrew 很棒,或者在任何系统上,你都可以install it manually
  • 是的,我在使用自制软件时遇到了问题,我将二进制文件添加到 /usr/local/bin/ 但没有任何改变。
  • 这很奇怪;它没有任何依赖关系,您不应该遇到/usr/local/bin 的 PATH 问题。它是如何失败的? phantomjs --version 在命令提示符下工作吗? RSelenium 有a comprehensive vignette,它可能会为您指明正确的方向。
  • @CyrusMohammadian 奇数。您可以通过 Selenium 服务器而不是其自己的 webdriver 模式来控制 PhantomJS(请参阅小插图的第二部分),也许。
【解决方案2】:

此解决方案使用 RSelenium 以及包 XML。它还假定您有一个可以正常使用firefoxRSelenium 安装。只需确保已将 firefox 启动脚本路径添加到您的 PATH

如果您使用的是OS X,则需要将/Applications/Firefox.app/Contents/MacOS/ 添加到您的PATH。或者,如果您使用的是 Ubuntu 机器,则可能是 /usr/lib/firefox/。一旦你确定这是有效的,你就可以继续使用以下内容:

# 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 列(与上周相比的变化)是一个空字符串向量。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 2021-01-04
    • 1970-01-01
    相关资源
    最近更新 更多