爬取basketball-reference Q1表格报ValueError列数不匹配错误如何解决
报错原因及解决方案
错误根源
你遇到的ValueError: 60 columns passed, passed data had 282 columns报错由三个核心问题导致:
- 目标Q1分段表格默认不在页面正常DOM结构中,而是存储在HTML注释块内,你当前代码直接查找的
sortable stats_table类表格是默认展示的全场汇总数据,并非你需要的Q1单节数据 - 表头提取逻辑错误:直接提取表格内所有
th标签,会把行首球员名、多层级表头的冗余内容全部算入表头,导致表头长度和实际数据列数不匹配 - 行数据遍历逻辑错误:外层
for row in table循环内,每次都全局查找整个表格的所有td元素,会把全表所有单元格塞进每一行的列表中,最终行数据长度远大于表头长度,触发列数不匹配报错
可直接运行的修正代码
import requests from bs4 import BeautifulSoup, Comment import pandas as pd headers = {'User-Agent': 'Mozilla/5.0'} url = 'https://www.basketball-reference.com/boxscores/202110190MIL.html' response = requests.get(url, headers=headers) soup = BeautifulSoup(response.content, 'html.parser') # 提取页面所有注释内容,找到Q1表格所在的注释块 comments = soup.find_all(string=lambda text: isinstance(text, Comment)) q1_table_html = '' for comment in comments: if 'box-NETS-q1-basic' in comment: q1_table_html = comment break # 解析Q1表格的HTML q1_soup = BeautifulSoup(q1_table_html, 'html.parser') table = q1_soup.find('table', id='box-NETS-q1-basic') # 正确提取表头:只取表头行的有效列,加上首列的球员名列 header_row = table.find('thead').find_all('tr')[1] headers = ['球员'] + [th.text for th in header_row.find_all('th')] # 遍历表体行,逐行提取数据 temp = [] tbody = table.find('tbody') for row in tbody.find_all('tr'): # 跳过合计行等无效行 if 'thead' in row.get('class', []): continue player_name = row.find('th').text row_data = [td.text for td in row.find_all('td')] temp.append([player_name] + row_data) # 生成DataFrame df = pd.DataFrame(temp, columns=headers) print(df)
代码修改说明
- 新增了注释块提取逻辑,直接从页面预存的注释中拿到Q1表格内容,不需要模拟前端点击操作
- 修正了表头提取逻辑,只取单层有效表头,额外补充了首列的球员名列,保证表头和数据列数一致
- 修正了行遍历逻辑,逐行提取单行列数据,避免全局查找所有单元格导致的数据长度异常
内容的提问来源于stack exchange,提问作者Amen Aziz
相关产品推荐
相关产品推荐

