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

基于R实现Transfermarkt欧洲Top25联赛数据抓取自动化

基于R实现欧洲前25市值联赛Transfermarkt数据抓取自动化

我已经完成英格兰超级联赛(英超)的基础数据抓取,现在要将流程自动化,获取欧洲市值排名前25的联赛的同类数据,包括:

  • 俱乐部名称
  • 平均年龄
  • 市场价值
  • 经验层级划分(基于平均年龄区间)

以下是我用于抓取英超数据的原始代码:

library(tidyverse)
library(magrittr) # 更便捷的管道操作
library(purrr) # 处理列表与映射函数
library(glue) # 字符串拼接
library(stringr) # 字符串处理

library(rvest) # 简化网页抓取
library(polite) # 合规礼貌的网页抓取工具
library(xml2) # 简化HTML/XML处理

# 英超页面URL
epl_url <- "http://www.transfermarkt.com/premier-league/startseite/wettbewerb/GB1"
page_link <- epl_url %>% read_html()

# 查看页面对象信息
page_link %>% typeof()
page_link %>% glimpse() 
page_link %>% html_structure()

# 定义CSS选择器
name_selector <- '#yw1 .no-border-links a:nth-child(1)' # 俱乐部名称选择器
market_value_selector <- 'td.rechts a' # 市场价值选择器
avg_age_selector <- '#yw1 tbody .zentriert:nth-child(4)' # 平均年龄选择器

# 单字段抓取测试
club_name <- page_link %>% html_elements(name_selector) %>% html_text2()
market_value <- page_link %>% html_elements(market_value_selector) %>% html_text()
average_age <- page_link %>% html_elements(avg_age_selector) %>% html_text()

# 查看抓取结果
club_name
market_value # 检查市场价值数据
average_age

# 单字段抓取函数封装
get_club_name <- function(page_link){
  page_link %>% html_elements(name_selector) %>% html_text()
}

get_avg_age <- function(page_link){
  page_link %>% html_elements(avg_age_selector) %>% html_text()
}

get_market_val <- function(page_link){
  page_link %>% html_elements(market_value_selector) %>% html_text()
}

# 整合为单函数,返回俱乐部详情数据框
get_club_details <- function(link){
  page <- link %>% read_html()
  
  club <- page %>% html_elements(name_selector) %>% html_text()
  average_age <- page %>% html_elements(avg_age_selector) %>% html_text()
  market_value <- page %>% html_elements(market_value_selector) %>% html_text()
  
  tibble(Club = club, Average_Age = average_age, Market_Value = market_value)
}

# 测试函数
get_club_details(epl_url)

# 数据清洗与经验层级划分
epl_table_df <- get_club_details(epl_url)
epl_table_df %>% glimpse()

epl_table_df %<>%
  mutate(
    Average_Age = as.numeric(Average_Age), # 转换为数值型
    Tier = case_when(
      Average_Age > 27 & Average_Age <= 28 ~ "经验丰富",
      Average_Age > 25 & Average_Age <= 27 ~ "中等经验",
      Average_Age > 23 & Average_Age <= 25 ~ "缺乏经验",
      TRUE ~ "其他层级" # 覆盖未匹配的区间
    )
  )

# 封装完整的数据抓取与处理函数
generate_club_details_df <- function(league_url){
  get_club_details(league_url) %>%
    mutate(
      Average_Age = as.numeric(Average_Age),
      Tier = case_when(
        Average_Age > 27 & Average_Age <= 28 ~ "经验丰富",
        Average_Age > 25 & Average_Age <= 27 ~ "中等经验",
        Average_Age > 23 & Average_Age <= 25 ~ "缺乏经验",
        TRUE ~ "其他层级"
      )
    )
}

# 测试完整函数
generate_club_details_df(epl_url)

自动化扩展:抓取欧洲前25市值联赛数据

1. 抓取欧洲联赛列表页面的联赛链接

先从欧洲联赛排名页面获取前25个联赛的URL,使用polite库合规请求:

# 欧洲联赛排名页面
europe_leagues_url <- "https://www.transfermarkt.com/wettbewerbe/europa"

# 创建礼貌会话,填写你的邮箱用于网站识别
session <- bow(europe_leagues_url, user_agent = "your-email@example.com")

# 抓取前25个联赛的名称与URL
leagues_data <- scrape(session) %>%
  html_elements("#yw1 tbody tr") %>%
  head(25) %>% # 取前25个联赛
  map_dfr(function(row){
    league_name <- row %>% html_element("a") %>% html_text()
    league_url <- row %>% html_element("a") %>% html_attr("href") %>% 
      str_c("https://www.transfermarkt.com", .) # 补全完整URL
    tibble(League_Name = league_name, League_URL = league_url)
  })

# 查看联赛列表
leagues_data

2. 批量抓取所有联赛的俱乐部数据

用purrr::map批量处理每个联赛URL,加入请求延迟避免封禁:

# 批量抓取函数,加入延迟
batch_scrape_leagues <- function(leagues_df){
  leagues_df %>%
    mutate(Club_Data = map(League_URL, function(url){
      Sys.sleep(2) # 每次请求间隔2秒,合规爬取
      generate_club_details_df(url) %>%
        mutate(League = League_Name) # 添加联赛名称字段
    })) %>%
    unnest(Club_Data) # 展开嵌套数据框
}

# 执行批量抓取
all_leagues_club_data <- batch_scrape_leagues(leagues_data)

# 查看最终数据
all_leagues_club_data %>% glimpse()

3. 数据清洗与保存

统一清洗数据并保存为本地文件:

# 清洗市场价值字段(去除非数值字符,转换为数值)
all_leagues_club_data_clean <- all_leagues_club_data %>%
  mutate(
    Market_Value = str_remove_all(Market_Value, "[^0-9.]") %>% as.numeric(),
    # 处理缺失值
    Average_Age = replace_na(Average_Age, 0),
    Market_Value = replace_na(Market_Value, 0)
  )

# 保存为CSV文件
write_csv(all_leagues_club_data_clean, "欧洲前25联赛俱乐部数据.csv")

注意事项

  • 合规爬取:必须设置合理的user_agent(填写你的邮箱),并添加请求延迟,遵守网站爬取规则。
  • 选择器兼容性:部分联赛页面的CSS选择器可能略有差异,抓取失败时需检查调整对应选择器。
  • 数据类型转换:原抓取的平均年龄和市场价值为字符型,需转换为数值型才能进行层级划分和分析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:55:24