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

如何高效获取ESPN NHL全部有效gameId及对应比赛日期?

问题

需要获取ESPN NHL技术统计页面(https://www.espn.com/nhl/boxscore/_/gameId/)下的所有有效gameId,每个有效URL对应唯一gameId(示例:https://www.espn.com/nhl/boxscore/_/gameId/4014559236)。已知不同赛季gameId起始值不同:2023-2024赛季起始为4014559236,2007-2008赛季起始为271009021,目标是尽可能获取最早的有效gameId。

当前使用的R代码仅能小范围验证URL有效性,但覆盖271009021到4014559236的超大范围时效率极低,同时希望获取每个gameId对应的比赛日期。

当前低效代码示例:

library(httr)
library(purrr)
library(RCurl)

urls <- paste0("https://www.espn.com/nhl/boxscore/_/gameId/",4014559236:4014559240)

safe_url_logical <- map(urls, http_error)
temp <- cbind(unlist(safe_url_logical), unlist(urls))
colnames(temp) <- c("logical","url")
temp <- as.data.frame(temp)
safe_urls <- temp %>% 
  dplyr::filter(logical=="FALSE")
dead_urls <- temp %>% 
  dplyr::filter(logical=="TRUE")

df_exist <- list()

for (i in 1:nrow(safe_urls)) {
  url <- as.character(safe_urls$url[i])
  exist <- url.exists(url)
  df_exist <- rbind(df_exist, url)
}

urls = df_exist

game_ids = sub('.*\\/', '', urls)
print(game_ids)
[1] "401559238" "401559239" "401559240"
高效实现方案

1. 优先用ESPN公开API替代盲遍历

ESPN的赛事数据有公开API接口,无需逐个验证URL:

  • 先请求NHL赛季列表接口,获取各赛季的完整赛事集合
  • 直接从赛事数据中提取gameId和对应比赛日期,无需遍历猜ID
  • 核心优势:完全避免无效请求,数据准确率100%

2. 二分法快速定位最早有效gameId

如果必须通过URL验证,用二分法替代全范围遍历:

  • 针对已知的ID范围(271009021到4014559236),不断取中间值验证有效性,逐步缩小有效区间
  • 示例逻辑:
    • 初始化左边界left=271009021,右边界right=4014559236
    • 计算中间值mid=(left+right)//2,验证mid对应的URL是否有效
    • 若有效,尝试往左缩小范围(right=mid);若无效,往右缩小(left=mid+1)
    • 重复直到left==right,得到最早的有效gameId

3. 并行请求优化批量验证

若需批量验证URL,用并行请求替代串行循环:

  • 使用furrr包实现并行映射,比purrr串行处理效率提升数倍
  • 先通过HEAD请求快速过滤4xx/5xx状态码的无效URL,再对疑似有效URL做二次验证并提取日期

4. 提取比赛日期的高效方法

获取有效URL后,直接从页面HTML提取日期:

  • ESPN的boxscore页面中,比赛日期通常在.game-info__date类标签下
  • 用rvest包快速解析HTML并提取日期文本,无需额外请求
改进后的R代码示例
library(httr)
library(furrr)
library(rvest)
library(dplyr)

# 验证单gameId有效性并提取日期
check_valid_game <- function(game_id) {
  url <- paste0("https://www.espn.com/nhl/boxscore/_/gameId/", game_id)
  # 先快速判断HTTP状态码
  resp <- HEAD(url, timeout(5))
  if (http_error(resp)) return(NULL)
  
  # 解析页面提取日期
  page <- read_html(url)
  date <- page %>% html_element(".game-info__date") %>% html_text()
  if (!is.na(date)) {
    return(data.frame(game_id = game_id, date = date, url = url))
  } else {
    return(NULL)
  }
}

# 二分法查找最早有效gameId
find_earliest_game_id <- function(left, right) {
  while (left < right) {
    mid <- floor((left + right) / 2)
    url <- paste0("https://www.espn.com/nhl/boxscore/_/gameId/", mid)
    resp <- HEAD(url, timeout(3))
    if (!http_error(resp)) {
      right <- mid
    } else {
      left <- mid + 1
    }
  }
  # 最终验证
  if (!http_error(HEAD(paste0("https://www.espn.com/nhl/boxscore/_/gameId/", left), timeout(3)))) {
    return(left)
  } else {
    return(NULL)
  }
}

# 批量处理流程
plan(multisession, workers = 8) # 开启并行计算
start_id <- find_earliest_game_id(271009021, 4014559236)
end_id <- 4014559236

# 分批次处理,避免一次性请求过多
batch_size <- 1000
batches <- split(start_id:end_id, ceiling(seq_along(start_id:end_id)/batch_size))

valid_games <- map_dfr(batches, function(batch) {
  map_dfr(batch, check_valid_game)
})

# 输出结果
print(valid_games)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:14:53