如何修改Python BeautifulSoup代码获取NBA球员数据数值而非文本
问题描述
我想从指定ESPN球员数据页面获取“All Splits”行的数值,但当前代码返回的是“All Splits”文本而非目标数值,需要修改GetStats函数中的查找逻辑来获取对应数值。
现有代码
import requests from bs4 import BeautifulSoup import re from concurrent.futures import ThreadPoolExecutor import pandas as pd import csv urls = [] data = [] for year in range(2003, 2005): for page in range(1, 9): url = f'http://www.espn.com/nba/hollinger/statistics/_/page/{page}/year/{year}/qualified/false' if url is not None: urls.append(url) def GetData(url): names_list = [] # 球员姓名列表 pers = [] # 球员效率值列表 playeridlist = [] # 用于生成数据查询链接的球员ID列表 statsurls = [] # 获取球员数据的链接列表 # 定义正则匹配模式 pattern = re.compile('playerId=(\d+)') # 初始化BeautifulSoup req = requests.get(url) soup = BeautifulSoup(req.text, 'lxml') # 获取球员姓名并加入列表 names = soup.find(lambda tag: tag.name == 'a' and 'playerId' in tag['href']) bodytext = names.text names_list.append(bodytext) # 获取球员效率值并加入列表 pertag = soup.find('td', class_='sortcell') per = pertag.text pers.append(per) # 获取球员ID names = soup.find('a', href=pattern) player_id = names['href'].split('playerId=')[1] playeridlist.append(player_id) # 生成球员数据查询链接 for player_id in playeridlist: statsurl = f"https://insider.espn.com/nba/player/splits/_/id/{player_id}/type/nba/year/{year}/category/perGame" if statsurl is not None: statsurls.append(statsurl) # 解析球员数据 def GetStats(statsurl): # 后续需要在此函数内添加线程执行器逻辑 statsreq = requests.get(statsurl) statssoup = BeautifulSoup(statsreq.text, 'lxml') focusing_search = statssoup.find('tr', class_='Table__TR Table__TR--sm Table__even', attrs={'data-idx': '1'}) playerstathtml = focusing_search.find('td', class_='Table__TD') stat_values = [playerstats.text for playerstats in playerstathtml] print(stat_values) GetStats("https://insider.espn.com/nba/player/splits/_/id/532/type/nba/year/2003/category/perGame") # name_and_stats_list = dict(map(lambda i, j: (i, j), names_list, pers)) print(f"{bodytext}: {per}") print(player_id) GetData('http://www.espn.com/nba/hollinger/statistics/_/page/1/year/2003/qualified/false')
修改方案
问题分析
原代码的核心问题:
- 仅获取了目标行的第一个
<td>元素,而该元素正好是“All Splits”文本,未提取后续包含数值的单元格 - 依赖
data-idx=1定位行不够稳定,页面结构变动时会失效,应该直接通过目标文本定位行
修改后的GetStats函数
def GetStats(statsurl): statsreq = requests.get(statsurl) statssoup = BeautifulSoup(statsreq.text, 'lxml') # 精准定位“All Splits”所在单元格,再获取其父元素(整行tr) all_splits_td = statssoup.find('td', string='All Splits') if not all_splits_td: print("未找到All Splits行") return [] target_row = all_splits_td.parent # 获取该行所有数据单元格 all_tds = target_row.find_all('td', class_='Table__TD') # 跳过第一个文本单元格,提取剩余数值 stat_values = [td.text.strip() for td in all_tds[1:]] print(stat_values) return stat_values
修改说明
- 稳定行定位:通过文本直接找到目标单元格,再向上获取整行,避免依赖页面结构的动态属性
- 完整数值提取:获取该行所有单元格后,跳过第一个文本单元格,直接提取后续的数值数据
- 容错处理:增加未找到目标行的判断,避免程序报错
内容的提问来源于stack exchange,提问作者Gregory Durgin
相关产品推荐
相关产品推荐

