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

Python抓取Pro-Football-Reference防守冲球统计表格遇列数不匹配错误

解决Pro-Football-Reference防守冲球统计转CSV的列不匹配问题

问题描述

我尝试将Pro-Football-Reference网站的防守冲球统计表格转换为CSV文件,此前处理跑卫统计数据时程序可正常获取10列数据,但处理防守统计数据时,出现错误:Assertion Error: 4 columns passed, passed data had 3 columns。

我的代码如下:

headers = [th.getText() for th in soup.findAll('tr')[1].findAll('th')]
headers = headers[1:]
print(headers[:5])
rows = soup.findAll('tr', class_ = lambda table_rows: table_rows != "thead")
player_stats = [[td.getText() for td in rows[i].findAll('td')]
                for i in range(len(rows))]
player_stats = player_stats[2:]
stats = pd.DataFrame(player_stats, columns = headers)
stats.head()

经排查,问题源于表格存在双层表头(多个“Rush”),且程序无法正确抓取球队名称。目标表格示例(省略其余30支球队):

Rush    Rush    Rush
Tm                   Att     Yds     TD
Arizona Cardinals   25.8    119.2   0.82
Seattle Seahawks    24.0    106.8   1.12

问题根源

  • 表格是双层表头结构:第一行是重复的“Rush”分类,第二行是具体统计项(Att/Yds/TD),但球队名称列(Tm)属于独立表头列,原代码未处理这种合并表头的情况,导致列数统计错误。
  • 筛选数据行的逻辑无效:lambda table_rows: table_rows != "thead" 无法准确排除表头行,导致抓取到无效数据行,进一步打乱列数匹配关系。

修正后的代码

1. 正确处理双层表头

合并两层表头,生成清晰的列名:

# 获取表头的两行数据
header_rows = soup.select('thead tr')
upper_headers = [th.getText().strip() for th in header_rows[0].findAll('th')]
lower_headers = [th.getText().strip() for th in header_rows[1].findAll('th')]

# 合并表头:Tm单独保留,Rush类的列合并为Rush_Att、Rush_Yds、Rush_TD
headers = []
for upper, lower in zip(upper_headers, lower_headers):
    if lower == 'Tm':
        headers.append(lower)
    else:
        headers.append(f"{upper}_{lower}" if upper else lower)
# 剔除表格最左侧的空序号列表头
headers = headers[1:]

2. 准确筛选数据行

利用网站内置的行类名,直接抓取有效数据行:

# 只抓取完整/部分数据行,排除表头、汇总行
data_rows = soup.select('tr.full_table, tr.partial_table')
player_stats = []
for row in data_rows:
    # 抓取该行所有单元格的文本,包含球队名称
    row_data = [td.getText().strip() for td in row.findAll('td')]
    player_stats.append(row_data)

3. 生成匹配的DataFrame

此时列数与数据行数完全匹配,可正常生成表格:

import pandas as pd
stats = pd.DataFrame(player_stats, columns=headers)
stats.head()

验证效果

修正后,表头会变为:['Tm', 'Rush_Att', 'Rush_Yds', 'Rush_TD'],每一行数据都包含4个值,彻底解决列数不匹配的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 17:05:01