Python Selenium爬取PrizePicks NBA Fantasy数据及ESPN对比求助
NBA Fantasy分值对比爬虫修复方案
第一部分 PrizePicks平台数据爬取修复
原代码核心错误
find_element_by_class_name('projections')返回单个父容器元素,不可迭代,循环直接报错,需先定位所有球员卡片节点- 方法名拼写错误:
fine_element_by_xpath应为find_element_by_xpath - 使用绝对路径xpath,依赖页面固定层级,稳定性极差
- 无元素等待逻辑,页面未渲染完成就查找元素大概率返回空
修复后代码
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import pandas as pd PATH = "C:\Program Files (x86)\chromedriver.exe" driver = webdriver.Chrome(PATH) driver.get("https://app.prizepicks.com/") wait = WebDriverWait(driver, 15) # 关闭弹窗 wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "close"))).click() # 选择NBA分类 wait.until(EC.element_to_be_clickable((By.XPATH, "//div[@class='name'][normalize-space()='NBA']"))).click() # 选择Fantasy Score标签 wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "segment-selector-button"))).click() # 等待所有球员卡片加载完成 player_cards = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "#projections .projection"))) nbaPlayers = [] for card in player_cards: # 相对路径匹配当前卡片内的姓名和分值 name = card.find_element(By.CSS_SELECTOR, ".player-name").text points = float(card.find_element(By.CSS_SELECTOR, ".score").text) nbaPlayers.append({ "Name": name, "FantasyPoints": points }) df_prizepicks = pd.DataFrame(nbaPlayers) print(df_prizepicks) driver.quit()
第二部分 ESPN球员近10场数据爬取修复
原代码核心错误
- xpath语法错误:
//*[@id='fittPageContainer'']多写了一个单引号,直接定位失败 - 只取了最近1场比赛的数据,未计算近10场平均值,不符合需求
- 未将元素文本转为数值类型,直接进行算术运算会报错
- 跳转球员页后无等待逻辑,表格未加载就查找元素会报错
修复后核心逻辑代码
# 接上面df_prizepicks数据,逐行遍历处理 driver = webdriver.Chrome(PATH) wait = WebDriverWait(driver, 20) result = [] for idx, row in df_prizepicks.iterrows(): player_name = row["Name"] prizepicks_score = row["FantasyPoints"] # 打开ESPN搜索 driver.get("https://www.espn.com/") # 触发搜索框 wait.until(EC.element_to_be_clickable((By.ID, "global-search-trigger"))).click() search_input = wait.until(EC.element_to_be_clickable((By.XPATH, "//input[@placeholder='Search Sports, Teams or Players...']"))) search_input.clear() search_input.send_keys(player_name) # 点击第一个搜索结果 wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".search_results__details"))).click() # 等待比赛数据表格加载 stats_table = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "table.Table--align-right tbody"))) game_rows = stats_table.find_elements(By.TAG_NAME, "tr")[:10] # 取最近10场 total_pts = 0 total_reb = 0 total_ast = 0 total_blk = 0 total_stl = 0 total_tov = 0 valid_games = 0 for game in game_rows: cols = game.find_elements(By.TAG_NAME, "td") if len(cols) < 13: continue try: pts = float(cols[12].text) reb = float(cols[6].text) ast = float(cols[7].text) blk = float(cols[8].text) stl = float(cols[9].text) tov = float(cols[11].text) total_pts += pts total_reb += reb total_ast += ast total_blk += blk total_stl += stl total_tov += tov valid_games += 1 except: continue if valid_games == 0: continue # 计算近10场平均Fantasy分值 avg_pts = total_pts / valid_games avg_reb = total_reb / valid_games avg_ast = total_ast / valid_games avg_blk = total_blk / valid_games avg_stl = total_stl / valid_games avg_tov = total_tov / valid_games espn_projected = avg_pts + avg_reb*1.2 + avg_ast*1.5 + avg_blk*3 + avg_stl*3 - avg_tov*1 result.append({ "Name": player_name, "FantasyPoints": prizepicks_score, "ESPN L10 Avg": round(espn_projected, 1), "Judgement": "高于预测" if espn_projected > prizepicks_score else "低于预测" }) df_final = pd.DataFrame(result) print(df_final) driver.quit()
实现逻辑说明
- 先爬取PrizePicks平台所有NBA球员的Fantasy预测分值,存入DataFrame
- 遍历DataFrame中每条球员数据,在ESPN搜索对应球员
- 爬取球员最近10场有效比赛的基础数据,计算平均Fantasy分值
- 对比两个平台的分值,输出高低判断结果
内容的提问来源于stack exchange,提问作者Consiglere
相关产品推荐
相关产品推荐

