基于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
相关产品推荐
相关产品推荐

