使用bs4爬取MLB棒球赔率时无法提取span标签内文本的问题
问题成因
- 目标站点的赔率为前端动态渲染内容:
requests仅能获取服务器返回的初始静态HTML,此时赔率数据还未通过JavaScript异步请求加载、填充到DOM节点中,因此返回结果只有占位符-,或对应标签完全不存在。 - 站点使用动态生成的样式类名:你当前匹配用到的
eventsByLeague-2wGLV、margin-2SxKQ这类带随机后缀的class是前端构建工具自动生成的,随时可能发生变更,即使内容加载完成也可能出现匹配失败的情况。
解决方法
方案1:模拟浏览器获取渲染后内容(上手门槛低)
使用Selenium等模拟浏览器工具,调用真实浏览器内核执行页面所有JS,等数据完全加载后再提取元素,获取的内容和浏览器中看到的完全一致。
首先安装依赖:
pip install selenium webdriver-manager
参考代码:
from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time # 配置浏览器参数 options = webdriver.ChromeOptions() # 不需要显示浏览器窗口可以取消下方注释 # options.add_argument("--headless=new") options.add_argument("user-agent=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0") driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options) # 访问目标页面 target_date = "20210615" driver.get(f"https://www.sportsbookreview.com/betting-odds/mlb-baseball/totals/?date={target_date}") # 等待页面元素加载,最长等待10秒 wait = WebDriverWait(driver, 10) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div[class*='eventMarketGridContainer']"))) # 额外等待1秒保证所有数据渲染完成 time.sleep(1) # 遍历提取数据 table_rows = driver.find_elements(By.CSS_SELECTOR, "div[class*='eventMarketGridContainer']") for row in table_rows: odds_items = row.find_elements(By.CSS_SELECTOR, "span[class*='margin-']") odds_list = [item.text.strip() for item in odds_items if item.text.strip()] print(odds_list) print('===================================') # 关闭浏览器 driver.quit()
方案2:直接请求数据接口(性能更高)
打开浏览器控制台的「网络」标签,筛选XHR/Fetch类型的请求,找到站点请求赔率数据的后端接口,直接调用接口获取结构化的JSON数据,无需解析HTML,效率更高也更稳定。只需要修改接口请求参数中的日期字段,即可批量获取多日期的全量赔率数据。
内容的提问来源于stack exchange,提问作者matthew_obrien
相关产品推荐
相关产品推荐

