You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用rvest爬取NHL薪资数据部分年份返回NULL的解决方法

解决rvest爬取NHL历年薪资数据的节点定位问题

我用rvest爬取Spotrac的NHL薪资数据时遇到问题,作为新手搞不清元素定位。需要获取2011-2022年的数据,但只有2020、2021、2022年能拿到,其余年份返回NULL。我的代码如下:

# vector of years
years <- c(rep(2011:2022, by = 1))

# empty vector to store urls
urls <- c()

# create full urls for each year
for (i in 1:12) {
  urls[i] <- paste0("https://www.spotrac.com/nhl/cap/", years[i], "/")
}

# empty list to store payroll tables
payrolls <- list()

# read in url and create a table for each year
for (i in 1:length(urls)) {
  temp <- read_html(urls[i])
  temp2 <- temp %>% html_nodes("table")
  payrolls[i] <- temp2 %>% html_table
}

输出列表最后三个元素是正常格式,其余年份拿不到,猜测非目标年份的节点不是"table",用Selector Gadget提取节点没成功。


问题原因

Spotrac的页面结构在2020年前后有变化:

  • 2020及之后的年份,薪资表格直接放在主页面的<table>标签里;
  • 2011-2019年的薪资表格嵌入在iframe中,直接爬主页面的table会找不到数据。

修正代码

通过先提取iframe的链接,再爬取iframe内的表格,就能解决旧年份的数据获取问题:

library(rvest)

# 生成2011-2022的年份序列
years <- 2011:2022
payrolls <- list()

for (year in years) {
  # 构造主页面URL
  main_url <- paste0("https://www.spotrac.com/nhl/cap/", year, "/")
  main_page <- read_html(main_url)
  
  # 尝试提取iframe的src属性(旧年份表格在iframe里)
  iframe_src <- main_page %>% 
    html_node("iframe#capview") %>% 
    html_attr("src")
  
  # 分情况处理:有iframe则爬iframe页面,无则直接爬主页面
  if (!is.na(iframe_src)) {
    # 拼接完整的iframe URL(原src是相对路径)
    iframe_url <- paste0("https://www.spotrac.com", iframe_src)
    table_data <- read_html(iframe_url) %>% 
      html_node("table") %>% 
      html_table()
  } else {
    table_data <- main_page %>% 
      html_node("table") %>% 
      html_table()
  }
  
  # 给表格添加年份标识,存入列表
  table_data$year <- year
  payrolls[[as.character(year)]] <- table_data
}

说明

  • 代码通过html_node("iframe#capview")定位到承载旧年份表格的iframe,提取其链接后再爬取内部表格;
  • 加入年份列方便后续对各年份数据进行合并或分析;
  • 自动适配2020年前后两种页面结构,一次性获取所有年份的数据。

内容的提问来源于stack exchange,提问作者jacfein

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 10:28:39