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

如何修改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')
修改方案

问题分析

原代码的核心问题:

  1. 仅获取了目标行的第一个<td>元素,而该元素正好是“All Splits”文本,未提取后续包含数值的单元格
  2. 依赖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

修改说明

  1. 稳定行定位:通过文本直接找到目标单元格,再向上获取整行,避免依赖页面结构的动态属性
  2. 完整数值提取:获取该行所有单元格后,跳过第一个文本单元格,直接提取后续的数值数据
  3. 容错处理:增加未找到目标行的判断,避免程序报错

内容的提问来源于stack exchange,提问作者Gregory Durgin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 08:35:23