R批量爬取FIFA球员数据遇404错误 求解决方案
解决fifaindex.com批量爬取404错误的实操方案
先搞懂404错误的常见原因
你遇到的404本质是请求的链接无效或网站拒绝了你的请求,常见情况有三种:
- 链接构造错误:fifaindex的年度页面不用直接填年份,而是用对应FIFA版本的编码(比如2023对应230,2012对应120),参数填错直接返回404
- 被反爬机制拦截:无间隔频繁请求会被识别为爬虫,网站直接拒绝访问
- 页面结构更新:你之前用的链接规则或元素选择器已经失效
一步步解决问题
1. 确认正确的年度参数映射
fifaindex球员列表页的规则是:https://www.fifaindex.com/players/[版本编码]/?page=[页码]
版本编码和年份的对应关系是:
- 2012 → 120
- 2013 → 130
- ...
- 2023 → 230
简单说就是年份减去2000再乘10,比如2012-2000=12,12×10=120,构造链接必须用这个编码,不能直接填年份。
2. 给请求加"伪装",避免被反爬
直接用rvest::read_html()会被网站识别为爬虫,必须模拟浏览器请求:
- 加
User-Agent请求头,告诉网站你是正常浏览器访问 - 每次请求后加延迟,别让网站觉得你在"轰炸"它
3. 加错误处理,跳过无效链接
用tryCatch捕获请求失败的情况,避免整个批量爬取直接崩溃。
调整后的完整代码
library(rvest) library(httr) library(dplyr) # 1. 设置请求头,模拟Chrome浏览器(可换成你自己浏览器的User-Agent) headers <- add_headers( "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" ) # 2. 定义年份和版本编码的映射 year_to_code <- setNames(120:230, 2012:2023) # 3. 爬取单页球员详情链接的函数 get_page_links <- function(target_year, page_num) { # 构造正确的分页链接 base_url <- paste0("https://www.fifaindex.com/players/", year_to_code[as.character(target_year)], "/?page=", page_num) tryCatch({ # 发送带请求头的请求 res <- GET(base_url, headers) # 检查请求是否成功 if (res$status_code != 200) { warning(paste("页面请求失败:", base_url, "状态码:", res$status_code)) return(NULL) } # 解析HTML page_html <- content(res, "html") # 提取球员详情链接(用浏览器F12确认选择器,这里是示例) raw_links <- page_html %>% html_elements("a[href^='/player/']") %>% html_attr("href") # 补全完整链接 full_links <- paste0("https://www.fifaindex.com", raw_links) return(full_links) }, error = function(e) { warning(paste("处理页面出错:", base_url, "错误:", e$message)) return(NULL) }) } # 4. 爬取单个球员详情数据的函数 get_player_info <- function(player_url, target_year) { tryCatch({ res <- GET(player_url, headers) if (res$status_code != 200) { warning(paste("球员详情请求失败:", player_url)) return(NULL) } player_html <- content(res, "html") # 提取关键信息(根据页面实际结构调整选择器) player_name <- player_html %>% html_element("h1") %>% html_text(trim = TRUE) overall_rating <- player_html %>% html_element(".rating") %>% html_text(trim = TRUE) position <- player_html %>% html_element(".position") %>% html_text(trim = TRUE) age <- player_html %>% html_element(".age") %>% html_text(trim = TRUE) # 整理成数据框 data.frame( 姓名 = player_name, 总评 = overall_rating, 位置 = position, 年龄 = age, 详情链接 = player_url, 年份 = target_year, stringsAsFactors = FALSE ) }, error = function(e) { warning(paste("处理球员出错:", player_url, "错误:", e$message)) return(NULL) }) } # 5. 批量爬取单年度数据的函数 scrape_single_year <- function(target_year) { cat("开始爬取", target_year, "年数据...\n") all_links <- c() current_page <- 1 while(TRUE) { cat("正在爬取第", current_page, "页...\n") page_links <- get_page_links(target_year, current_page) # 如果页面无数据或者请求失败,停止分页爬取 if (is.null(page_links) || length(page_links) == 0) { cat("第", current_page, "页无数据,结束该年度分页爬取\n") break } all_links <- c(all_links, page_links) current_page <- current_page + 1 Sys.sleep(2) # 每页爬取后延迟2秒 } # 去重链接(避免重复爬取同一球员) all_links <- unique(all_links) cat("共找到", length(all_links), "名球员,开始爬取详情...\n") # 批量爬取球员详情 player_data_list <- lapply(all_links, function(link) { data <- get_player_info(link, target_year) Sys.sleep(1) # 每个球员详情爬取后延迟1秒 return(data) }) # 合并数据框并去掉空值 final_data <- bind_rows(player_data_list) %>% filter(!is.na(姓名)) # 保存为CSV文件 output_path <- paste0("FIFA_球员数据_", target_year, ".csv") write.csv(final_data, output_path, row.names = FALSE, fileEncoding = "UTF-8") cat(target_year, "年数据爬取完成,已保存到:", output_path, "\n") return(final_data) } # 6. 爬取2012-2023年所有数据 for (year in 2012:2023) { scrape_single_year(year) }
额外注意事项
- 检查robots.txt:先访问
https://www.fifaindex.com/robots.txt,确认网站是否允许爬取球员数据,避免违规 - 更新选择器:如果网站页面结构变化,用浏览器F12重新定位元素的CSS选择器,替换代码里的选择器(比如
a[href^='/player/']) - 降低请求频率:如果还是被封,把
Sys.sleep()的时间调长一点(比如3-5秒)
内容的提问来源于stack exchange,提问作者Lucky_will
相关产品推荐
相关产品推荐

