在 R 中的高尔夫网站上抓取排行榜 table

Scraping leaderboard table on golf website in R

PGA 巡回赛的网站有一个 leaderboard page 页面,我正在尝试抓取网站上的主要 table 项目。

library(dplyr)
leaderboard_table <- xml2::read_html('https://www.pgatour.com/leaderboard.html') %>% 
  html_nodes('table') %>% 
  html_table()

然而,它没有拉 tables,而是 returns 这个奇怪的输出...

其他页面,如 schedule page 抓取正常,没有任何问题,请参见下文。这只是我遇到问题的排行榜页面。

schedule_url <- 'https://www.pgatour.com/tournaments/schedule.html'
schedule_table <- xml2::read_html(schedule_url) %>% html_nodes('table.table-styled') %>% html_table()
schedule_df <- schedule_table[[1]]
# this works fine

赏金前编辑: 下面的回答是一个有用的开始,但是有一个问题。 JSON 文件名根据轮次(/r/003 表示第 3 轮)更改,并且可能还基于高尔夫锦标赛的其他​​方面。目前我在元素选项卡中看到了这个:

...但是,使用排行榜 url link 到 .json 文件 https://lbdata.pgatour.com/2021/r/005/leaderboard.json 没有帮助...相反,我在使用时收到此错误jsonlite::fromJson

那么两个问题:

  1. 是否可以将此 .JSON 文件读入 R? (也许它以某种方式受到保护)?也许只是我这边的一个问题,还是我在这里遗漏了 R 中的其他内容?

  2. 鉴于 URL 发生变化,我如何在 R 中动态获取 URL 值?如果我能以某种方式获取所有 global.leaderboardConfig 对象,那就太好了,因为这样我就可以访问 leaderboardUrl.

谢谢!!

此页面使用 javascript 呈现页面,您查找的数据存储为 JSON 文件。使用浏览器中的开发人员工具并查看“网络”选项卡,您应该能够找到“leaderboard.json”文件的 link。

您可以直接访问此文件:

jsonlite::fromJSON("https://lbdata.pgatour.com/2021/r/003/leaderboard.json?userTrackingId=exp=1612495792~acl=*~hmac=722f704283f795e8121198427386ee075ce41e93d90f8979fd772b223ea11ab9")

这是一个相当复杂的列表,但您应该能够浏览不同的元素以找到所需的信息。

如前所述,此页面是由某些 javascript.
动态生成的 即使 json 文件地址似乎是动态的,您尝试打开的地址也不再有效:

https://lbdata.pgatour.com/2021/r/003/leaderboard.json?userTrackingId=exp=1612495792~acl=*~hmac=722f704283f795e8121198427386ee075ce41e93d90f8979fd772b223ea11ab9

An error occurred while processing your request.

Reference #199.cf05d517.1613439313.4ed8cf21 

要获取数据,您可以使用 RSelenium after installing a Docker Selenium server
安装非常简单,Docker 旨在使图像开箱即用。

安装 Docker 之后,运行 Selenium 服务器就像:

docker run -d -p 4445:4444 selenium/standalone-firefox:2.53.0

请注意,这作为一个整体需要超过 2 Gb 个磁盘 space。

Selenium 模拟 Web 浏览器并允许在呈现 javascript:

之后获取页面的最终 HTML 内容
library(RSelenium)
library(rvest)

remDr <- remoteDriver(
  remoteServerAddr = "localhost",
  port = 4445L,
  browserName = "firefox"
)
# Open connexion to Selenium server
remDr$open()
remDr$getStatus()

remDr$navigate("https://www.pgatour.com/leaderboard.html")

players <- xml2::read_html(remDr$getPageSource()[[1]]) %>% 
                 html_nodes(".player-name-col")   %>% 
                 html_text()

total <- xml2::read_html(remDr$getPageSource()[[1]]) %>% 
               html_nodes(".total") %>%
               html_text()

data.frame(players = players, total = total[-1])

                     players total
1        Daniel Berger  (PB)   -18
2     Maverick McNealy  (PB)   -16
3      Patrick Cantlay  (PB)   -15
4        Jordan Spieth  (PB)   -15
5           Paul Casey  (PB)   -14
6         Nate Lashley  (PB)   -14
7      Charley Hoffman  (PB)   -13
8     Cameron Tringale  (PB)   -13
...

由于 table 不使用 table 标签,html_table 不起作用,需要单独提取列。