为何Inspect Element可见的DraftKings数据无法被BeautifulSoup解析?
问题根源
DraftKings这类体育博彩网站的部分页面内容是JavaScript动态渲染的,requests.get只能获取页面初始的静态HTML,动态加载的数据不会出现在返回内容里,所以BeautifulSoup找不到对应的选择器元素。之前爬本垒打数据成功,大概率是那个页面的内容刚好是静态嵌入的,而总垒打(total-bases)的内容需要浏览器执行JS后才会加载。
解决方案
按优先级推荐两种处理方式:
方法1:直接爬网站的API接口(最优)
这类网站通常会通过API接口加载数据,比解析HTML稳定得多,步骤如下:
- 打开浏览器访问目标URL,按F12打开开发者工具,切换到「Network」标签后刷新页面
- 过滤「XHR」或「Fetch」请求,找包含球员数据的接口(URL通常带有
odds、props、players这类关键词) - 用
requests直接请求该API URL,解析返回的JSON数据生成DataFrame
示例代码(需替换为你找到的真实API接口):
import requests import pandas as pd # 替换为实际找到的API地址 api_url = "https://api.draftkings.com/sportsbook/v1/odds/baseball/mlb/batter-props/total-bases" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } response = requests.get(api_url, headers=headers) data = response.json() # 从JSON结构中提取所需字段(需根据实际返回结构调整) player_data = [] for event in data["events"]: for offering in event["offerings"]: line = offering["line"] for outcome in offering["outcomes"]: player_name = outcome["participant"]["name"] odds = int(outcome["odds"].replace('−', '-')) if outcome["label"] == "Over": over_odds = odds under_odds = None else: under_odds = odds over_odds = None player_data.append({ "Player Name": player_name, "Line": line, "Over": over_odds, "Under": under_odds }) # 整理数据并去重 df = pd.DataFrame(player_data) df = df.groupby(["Player Name", "Line"]).agg({"Over": "first", "Under": "first"}).reset_index()
方法2:用动态渲染工具(Selenium)
如果找不到可用的API,就用Selenium模拟浏览器加载页面,等JS渲染完成后再解析HTML:
- 安装依赖:
pip install selenium - 下载对应浏览器的驱动(比如ChromeDriver,需和浏览器版本匹配),放到系统PATH或指定路径
- 编写代码模拟浏览器访问并等待内容加载
示例代码:
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 from bs4 import BeautifulSoup url = 'https://sportsbook.draftkings.com/leagues/baseball/mlb?category=batter-props&subcategory=total-bases' # 初始化Chrome浏览器(需确保ChromeDriver已配置) driver = webdriver.Chrome() driver.get(url) # 等待页面核心元素加载完成(最长等待10秒) wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.CLASS_NAME, "sportsbook-row-name"))) # 获取渲染后的完整HTML page_source = driver.page_source soup = BeautifulSoup(page_source, 'html.parser') # 提取数据(需根据实际页面结构调整选择器) player_names = [row.get_text(strip=True) for row in soup.find_all(class_="sportsbook-row-name")] lines = [float(el.text.strip().replace(",", "")) for el in soup.select(".sportsbook-outcome-cell__line") if el.text.strip()] over_odds = [int(el.text.strip().replace('−', '-')) for el in soup.select(".sportsbook-outcome-cell:has(.sportsbook-outcome-cell__label:contains('Over')) .default-color")] under_odds = [int(el.text.strip().replace('−', '-')) for el in soup.select(".sportsbook-outcome-cell:has(.sportsbook-outcome-cell__label:contains('Under')) .default-color")] # 生成DataFrame(确保各列表长度匹配) df = pd.DataFrame({ "Player Name": player_names, "Line": lines[::2], # 按实际页面结构调整索引逻辑 "Over": over_odds, "Under": under_odds }) # 关闭浏览器 driver.quit()
要不要换工具包?
不需要完全换掉BeautifulSoup——它只是HTML解析工具,本身处理不了动态内容。你可以结合API请求或者动态渲染工具(Selenium/Playwright)获取完整页面内容后,再用BeautifulSoup解析,或者直接处理JSON数据即可。
内容的提问来源于stack exchange,提问作者Carson Mullen
相关产品推荐
相关产品推荐

