我曾多次尝试从我在其他用例中成功抓取的网站上抓取页面,但都失败了。在这种特殊情况下,除了错误之外,我似乎无法产生任何结果:
“UseMethod(“html_table”) 中的错误:没有适用于“html_table”的方法应用于“xml_missing”类的对象。”
总的来说,在 R 中进行网页抓取时,我一直很难找到正确的 css 选择器(或排序),而像 SelectorGadget 这样的工具几乎没有帮助。
请参阅下面我尝试过的几个代码块。感谢任何提出的解决方案。作为奖励,任何关于 R 网络抓取的最佳资源都会受到赞赏。
library(tidyverse)
library(rvest)
library(xml2)
url <- 'https://baseballsavant.mlb.com/leaderboard/percentile-rankings?type=batter&team='
hitting <- url %>%
read_html() %>%
html_node('#prLeaderboard div.table-savant') %>%
html_table()
url <- 'https://baseballsavant.mlb.com/leaderboard/percentile-rankings?type=batter&team='
hitting <- url %>%
read_html() %>%
html_node('#prLeaderboard div.table-savant') %>%
html_table()
url <- 'https://baseballsavant.mlb.com/leaderboard/percentile-rankings?type=batter&team='
hitting <- url %>%
read_html() %>%
html_element(xpath = "//div[@id='statcastHitting']/div[@class='table-savant']") %>%
html_table()
url <- 'https://baseballsavant.mlb.com/leaderboard/percentile-rankings?type=batter&team='
hitting <- url %>%
read_html() %>%
html_node("table") %>%
html_table()
问题是该表格不是作为 HTML 表格发送,而是在
<script>
标记内发送。您可以通过检查 read_html
的输出或页面源代码本身来看到这一点:
在您的浏览器中,此脚本将被执行并填充表格,但
rvest
不会执行此类操作。不过,它是可以评估JavaScript并提取该变量(另请参阅此处):
library(rvest)
library(stringi)
library(purrr)
library(V8)
library(xml2)
url <- 'https://baseballsavant.mlb.com/leaderboard/percentile-rankings?type=batter&team='
scripts <- url %>%
read_html() %>%
html_nodes(xpath=".//script")
## We're looking for the 'leaderboard_data' JavaScript var
varname <- "leaderboard_data"
## It's the 4th script on the page, not otherwise labelled
var <- scripts[[4]] %>%
html_text() %>%
stri_split_lines() %>%
flatten_chr() %>%
keep(stri_detect_regex, varname)
## Fire up the JavaScript parser
jsx <- v8()
jsx$eval(var)
want <- jsx$get("leaderboard_data")
## player_name team_name team_id year player_type ...
## 1 Austin Hedges Rangers 140 2023 batter
## 2 Zach Remillard White Sox 145 2023 batter
## 3 Alec Burleson Cardinals 138 2023 batter
## 4 Connor Wong Red Sox 111 2023 batter
## ...
然而,有一种更简单的方法来获取这些数据:网站提供直接的 CSV 下载。只需将
&csv=true
添加到 URL:
read.csv(paste0(url, "&csv=true"))
## player_name player_id year xwoba xba xslg ...
## 1 Austin Hedges 595978 2023 NA NA NA
## 2 Zach Remillard 621545 2023 NA NA NA
## 3 Alec Burleson 676475 2023 65 85 68
## 4 Connor Wong 657136 2023 4 4 14
## ...