如何使用BeautifulSoup遍历HTML采集NBA全维度排名数据
实现方案
原代码存在几个明显问题:
- 重复发起两次相同HTTP请求,属于冗余代码
- 遍历tbody的循环与后续行遍历循环平级,
rows变量会被最后一个tbody覆盖,存在数据遗漏风险 - 仅硬编码定位东部联盟单张表,未覆盖西部联盟、6个分赛区、全联盟三个维度的所有排名表
- 仅提取球队名单个字段,未采集胜场、负场、胜率等其他排名指标
- 裸
except会吞掉所有运行错误,排查问题困难 - 额外注意:该站点的分赛区排名表默认写在HTML注释中,直接调用
find方法无法定位,必须单独处理注释内容。
整体实现逻辑:
- 单次请求拉取页面源码
- 同时抓取页面直接可见的联盟排名、全联盟排名表,以及注释中隐藏的分赛区排名表,覆盖所有需要的数据源
- 遍历每张表时先记录表所属的维度名称(如东部联盟、大西洋赛区、全联盟排名等)
- 逐行解析时跳过表头分隔行,按字段属性提取所有数据,统一结构化存储
- 移除无意义的全局异常捕获,通过条件判断跳过无效行,避免错误被吞
完整可运行代码:
import requests from bs4 import BeautifulSoup, Comment url = 'https://www.basketball-reference.com/leagues/NBA_2022_standings.html' r = requests.get(url) soup = BeautifulSoup(r.text, 'html.parser') standings_tables = [] # 收集直接可见的东西部联盟、全联盟排名表 for table in soup.find_all('table'): table_id = table.get('id', '') if table_id.startswith('confs_standings') or table_id == 'expanded_standings': standings_tables.append((table_id, table)) # 收集注释中隐藏的分赛区排名表 for comment in soup.find_all(string=lambda x: isinstance(x, Comment)): comment_soup = BeautifulSoup(comment, 'html.parser') for table in comment_soup.find_all('table'): if table.get('id', '').startswith('divs_standings'): standings_tables.append((table.get('id'), table)) all_standings = [] for table_id, table in standings_tables: # 获取当前表的维度名称 dimension = table.find('caption').text.strip() # 遍历表体行 for row in table.find('tbody').find_all('tr'): # 跳过分隔用的标题行(这类行没有球队跳转链接) team_cell = row.find('th') if not team_cell or not team_cell.find('a'): continue # 组装单条数据 item = {'dimension': dimension} item['rank'] = team_cell.text.strip().split()[0] # 提取排名数字 item['team'] = team_cell.find('a').text.strip() # 提取其余所有数据列 for td in row.find_all('td'): stat_key = td.get('data-stat') item[stat_key] = td.text.strip() all_standings.append(item) # 测试输出 for row in all_standings[:10]: print(row) # 后续连接数据库后,直接遍历all_standings列表批量插入即可
代码说明:
- 表定位通过id前缀规则匹配,不需要手动硬编码每个表的id,后续爬取其他赛季只需要修改URL中的年份参数即可复用
- 自动处理注释内的隐藏表格,不会遗漏分赛区维度的数据
- 最终采集结果存在
all_standings列表中,每个元素是结构化字典,包含所属维度、排名、球队名、胜场、负场、胜率、胜场差、主客场战绩、同赛区/同联盟战绩等全部页面展示字段,可直接对接数据库插入逻辑 - 字段key取自HTML标签自带的
data-stat属性,不依赖列的固定顺序,即使网站微调列顺序也不会出现数据错位问题 - 移除了裸异常捕获,通过判断球队链接是否存在来跳过无效行,运行出错时会直接抛出具体错误信息,方便调试
内容的提问来源于stack exchange,提问作者DrewS
相关产品推荐
相关产品推荐

