基于球员姓名关联Basketball Reference多表数据的Python实现求助
实现从Basketball Reference匹配球员花名册与统计数据的方案建议
嘿,看起来你已经迈出了很棒的第一步——成功抓取到凯尔特人队的花名册了!接下来要把totals表的球员数据匹配到对应花名册行的末尾,核心是找到球员的唯一标识来关联两个表格,我给你梳理下具体的实现方向和代码修改建议:
核心思路
Basketball Reference的表格里,每个球员都有一个唯一的data-append-csv属性值(比如球员Kyrie Irving的这个值是irvinky01),这个值是跨表格匹配的关键——不管是roster表还是totals表,同一个球员的这个值是一致的,我们可以用它来建立映射关系。
具体实现步骤
- 步骤1:提取花名册时,同时获取球员的唯一标识和基本信息
不要只提取td的文本,还要把每个球员行的data-append-csv属性值存下来,这个是后续匹配的钥匙。 - 步骤2:提取totals表格的球员统计数据
同样从totals表中提取每个球员的data-append-csv值,以及对应的得分、篮板、助攻等统计字段,把这些数据存成一个字典,键是data-append-csv值,值是统计数据的列表。 - 步骤3:关联两个表格的数据
遍历花名册的每一行,用该行的data-append-csv值去字典里查找对应的统计数据,找到后就追加到该行的末尾;如果找不到(比如某些球员没有totals数据),可以用空值填充。 - 步骤4:输出整理好的数据
把合并后的结果转换成DataFrame或者直接写入CSV文件,方便后续使用。
修改后的代码示例
from selenium import webdriver from bs4 import BeautifulSoup import pandas as pd # 直接使用你指定的2019赛季凯尔特人页面 team_url = "https://www.basketball-reference.com/teams/BOS/2019.html" driver = webdriver.Chrome() driver.get(team_url) soup = BeautifulSoup(driver.page_source, 'lxml') driver.quit() # 用完浏览器记得关闭 # 1. 提取花名册数据(包含唯一标识) roster_data = [] roster_table = soup.find('table', id='roster') # 获取花名册表头 roster_headers = [th.text for th in roster_table.select('thead tr th')] # 遍历每一行球员数据 for row in roster_table.select('tr')[1:]: # 获取球员的唯一标识 player_slug = row.get('data-append-csv') # 获取该行的文本数据 row_text = [td.text for td in row.select("td")] # 把唯一标识插入到行数据的开头 row_text.insert(0, player_slug) roster_data.append(row_text) # 给表头添加唯一标识的列名 roster_headers.insert(0, 'Player_Slug') # 2. 提取totals表格的统计数据,建立slug到数据的映射 totals_map = {} totals_table = soup.find('table', id='totals') # 获取totals的表头(跳过第一列的Rk) totals_headers = [th.text for th in totals_table.select('thead tr th')[1:]] for row in totals_table.select('tr')[1:]: # 跳过空行和汇总行 if not row.get('data-append-csv'): continue player_slug = row.get('data-append-csv') # 获取统计数据,跳过第一列的Rk stats = [td.text for td in row.select("td")[1:]] totals_map[player_slug] = stats # 3. 合并两个表格的数据 merged_data = [] # 合并表头:花名册表头 + totals表头 merged_headers = roster_headers + totals_headers for row in roster_data: player_slug = row[0] # 查找对应的统计数据,找不到就用空值填充 player_stats = totals_map.get(player_slug, [''] * len(totals_headers)) # 合并行数据 merged_row = row + player_stats merged_data.append(merged_row) # 4. 转换成DataFrame并输出 df = pd.DataFrame(merged_data, columns=merged_headers) print(df.head()) # 保存成CSV文件 df.to_csv('bos_2019_roster_with_stats.csv', index=False)
额外注意事项
- 表格里可能存在空行或者汇总行(比如totals表底部的球队总计行),所以要判断
row.get('data-append-csv')是否存在,避免程序报错。 - 如果遇到球员没有totals数据(比如只在花名册但没出场),用空值填充是比较稳妥的方式,不会打断程序运行。
- 如果你不需要Selenium,其实可以直接用
requests库获取页面内容,因为Basketball Reference的静态页面不需要渲染,这样运行效率会更高(把Selenium的部分换成requests.get(team_url)再解析即可)。
内容的提问来源于stack exchange,提问作者Shaun




