为何使用R爬取Fangraphs部分球员数据表格成功,其他表格却返回NULL?
为何使用R爬取Fangraphs部分球员数据表格成功,其他表格却返回NULL?
嘿,我来帮你排查这个问题!你遇到的情况其实很常见——这不是你的XPATH写错了,而是Fangraphs上的部分表格加载方式和你成功抓取的那些不一样。
问题根源:静态VS动态加载
你能成功抓取的Dashboard、Standard这类表格,是页面首次加载时就直接嵌入在静态HTML里的,所以read_html()能直接读到它们的代码。但像Fielding、Statcast - Bat Tracking这类标签对应的表格,是要等你点击标签切换时,才通过JavaScript动态注入到页面中的。
而read_html()只能获取页面刚加载时的静态内容,根本看不到这些后续才生成的表格节点,所以html_nodes()找不到对应元素,自然返回NULL啦。
两种解决方案
方案1:用浏览器自动化工具抓取动态内容(适合新手直观操作)
这种方法会模拟你手动操作浏览器的过程(比如点击标签),能完整获取动态加载的内容。推荐用playwright包(比传统的RSelenium更轻量易用):
首先安装依赖:
install.packages("playwright") playwright::install_browsers() # 安装浏览器驱动
然后写代码模拟操作并抓取Fielding表格:
library(playwright) library(purrr) library(rvest) # 启动无头浏览器(不会弹出可视化窗口) pw <- chromium$launch(headless = TRUE) page <- pw$new_page() # 打开Basallo的球员页面 page$goto("https://www.fangraphs.com/players/samuel-basallo/28824/stats/batting") # 点击Fielding标签(用文本匹配定位按钮) page$click("text=Fielding") # 等待表格加载完成(给JavaScript留渲染时间) page$wait_for_selector("#fielding table") # 读取完整的页面HTML(包含动态加载的内容) html_content <- page$content() url_read_html <- read_html(html_content) # 抓取并提取表格 data_look <- url_read_html |> html_nodes(css = "#fielding table") |> # 用CSS选择器比XPATH更稳定 html_table() |> pluck(1) # 关闭浏览器 pw$close()
方案2:直接抓取AJAX接口(更高效稳定)
如果你想批量抓取或者追求效率,直接抓Fangraphs加载表格的后台接口会更好——不用模拟浏览器,速度快,还不容易因为页面布局变化失效:
- 打开Chrome开发者工具(F12),切换到Network标签,勾选「XHR/Fetch」过滤项
- 点击页面上的Fielding标签,观察Network列表里新增的请求,找到返回表格数据的AJAX接口(通常是JSON格式)
- 复制这个接口的URL,用
httr2直接请求并解析数据:
示例代码(请替换成你抓到的真实接口URL):
library(httr2) library(jsonlite) # 替换成你从Network面板抓到的真实接口地址 api_url <- "https://www.fangraphs.com/api/players/stats?playerid=28824&position=B&type=fielding&season=2024&leagueid=all" # 请求接口并解析JSON数据 fielding_data <- request(api_url) |> req_perform() |> resp_body_json() |> pluck("data") |> # 根据接口返回的JSON结构调整提取路径 as.data.frame()
这种方法的好处是,接口返回的是结构化数据,不用再清洗HTML表格,而且批量抓取时速度会比模拟浏览器快很多。
小提示
- 尽量用CSS选择器(比如
#fielding table)代替XPATH,因为页面布局变化时XPATH更容易失效 - 如果要批量抓取多个球员,直接用AJAX接口会节省大量时间,模拟浏览器的话速度会慢很多
备注:内容来源于stack exchange,提问作者Buckaroo Banzai
相关产品推荐
相关产品推荐

