使用rvest爬取NHL球队统计数据的CSS选择器问题及批量需求
爬取Hockey-Reference上NHL球队统计数据的R实现方案
我来帮你梳理一下怎么用R实现这个爬取需求,既然你已经加载了tidyverse和rvest包,咱们一步步来:
第一步:先搞定1991年单年份的数据爬取
先把单年份的逻辑跑通,确保每一步都没问题:
# 确认加载所需包(你已经加载过,这里再明确一下) library(tidyverse) library(rvest) # 定义1991年的目标URL url_1991 <- "https://www.hockey-reference.com/leagues/NHL_1991.html" # 读取网页内容 nhl_page <- read_html(url_1991) # 提取第4个表格(也就是你指定的Team Statistics) # html_nodes("table")会返回页面所有表格,用[[4]]定位第4个 team_stats_raw <- nhl_page %>% html_nodes("table") %>% .[[4]] %>% html_table(header = FALSE) # 先不自动设置表头,避免处理页面上的浮动重复表头 # 剔除首行(重复的表头行)和末行(汇总行) team_stats_clean <- team_stats_raw %>% # 移除第1行和最后一行 slice(-c(1, nrow(.))) %>% # 将原始表格的第1行设置为列名 set_names(team_stats_raw[1, ]) %>% # 可选:自动转换数据类型,让数值列变为数值型 type_convert() # 查看处理后的结果 head(team_stats_clean)
第二步:扩展到1991-2017年批量爬取
接下来把逻辑封装成函数,批量处理所有年份的数据:
1. 生成所有年份的URL列表
先批量生成1991到2017年对应的目标链接:
# 生成年份序列 years <- 1991:2017 # 拼接成完整的URL stat_urls <- paste0("https://www.hockey-reference.com/leagues/NHL_", years, ".html")
2. 编写批量爬取的函数
为了代码更复用,写一个处理单个URL的函数,包含数据清理、年份标识等逻辑:
scrape_single_year_stats <- function(url) { # 读取目标网页 page <- read_html(url) # 更稳妥的表格定位方式:通过表格标题匹配Team Statistics # 比依赖第4个表格更可靠,避免不同年份页面结构变化导致爬错 team_table <- page %>% html_nodes("table:has(caption:contains('Team Statistics'))") %>% html_table(header = FALSE) %>% pluck(1) # 提取匹配到的第一个表格(通常只有一个符合条件) # 从URL中提取年份信息 year <- str_extract(url, "\\d{4}") %>% as.integer() # 清理数据:去冗余行、设置列名、添加年份列 cleaned_data <- team_table %>% slice(-c(1, nrow(.))) %>% set_names(team_table[1, ]) %>% mutate(Year = year) %>% type_convert() # 添加请求延迟,避免频繁访问触发网站反爬机制 Sys.sleep(2) return(cleaned_data) }
3. 批量执行爬取并合并数据
用map_dfr把函数应用到所有URL上,自动将结果合并成一个数据框:
# 批量爬取所有年份数据 all_nhl_team_stats <- map_dfr(stat_urls, scrape_single_year_stats) # 查看最终合并后的数据结构 glimpse(all_nhl_team_stats)
一些实用提示
- 反爬规避:hockey-reference会限制高频请求,
Sys.sleep(2)让每次请求间隔2秒,如果遇到访问被拒,可以适当延长间隔时间。 - 表格定位容错:如果部分年份的表格位置不是第4个,用表格标题匹配的方式会更稳定,避免爬取错误数据。
- 特殊格式处理:少数年份的表格可能存在空行或额外汇总行,如果遇到异常数据,可以针对特定年份调整清理逻辑。
内容的提问来源于stack exchange,提问作者papelr
相关产品推荐
相关产品推荐

