使用Selenium与XPath抓取BetMGM足球赔率时元素列表为空的技术求助
解决Selenium抓取BetMGM足球赔率时元素为空的问题
我来帮你排查这个问题,你遇到的情况在动态渲染的网站(比如用Angular构建的BetMGM)里很常见,主要原因是页面还没加载完成你就尝试获取元素了,另外XPath的匹配也可以再优化下。
问题根源分析
- 动态页面加载延迟:BetMGM使用Angular框架(从
ng-star-inserted类名能看出来),页面内容是异步渲染的,你调用driver.get(url)后立刻查找元素,此时元素还没被渲染到DOM里,所以返回空列表。 - XPath匹配精度问题:原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 url = "https://sports.va.betmgm.com/en/sports/football-11/betting/usa-9" # 优化XPath:更精准定位比赛对应的球队和赔率元素 team_xpath = "//div[contains(@class, 'participant') and not(contains(@class, 'country'))]/text()[normalize-space()]" mline_xpath = "//div[@class='option option-value ng-star-inserted']//ms-font-resizer/text()[normalize-space()]" with webdriver.Firefox() as driver: driver.get(url) try: # 显式等待元素加载,最长等待15秒 WebDriverWait(driver, 15).until( EC.presence_of_all_elements_located((By.XPATH, team_xpath)) ) # 获取元素文本(使用execute_script直接提取文本,避免元素交互问题) teams = driver.execute_script(f"return Array.from(document.evaluate('{team_xpath}', document, null, XPathResult.STRING_TYPE, null)).filter(t => t.trim() !== '')") mlines = driver.execute_script(f"return Array.from(document.evaluate('{mline_xpath}', document, null, XPathResult.STRING_TYPE, null)).filter(t => t.trim() !== '')") # 打印结果验证 print("球队列表:", teams) print("赔率列表:", mlines) # 转成DataFrame df = pd.DataFrame({"球队": teams, "Moneyline赔率": mlines}) print(df) except Exception as e: print(f"抓取过程出错:{str(e)}")
关键改进点说明
- 显式等待:用
WebDriverWait替代直接查找元素,确保DOM中已经渲染出目标元素后再进行提取,避免因加载延迟导致的空列表。 - 优化XPath:
- 球队的XPath直接提取
participant下的非空文本,过滤掉participant country的干扰元素。 - 赔率的XPath直接定位到
ms-font-resizer内部的文本,确保拿到准确的赔率值。
- 球队的XPath直接提取
- 使用execute_script提取文本:对于动态渲染的文本,有时候直接用
element.text可能拿不到内容,通过JS执行XPath查询能更可靠地获取文本节点。
额外注意事项
- 如果页面需要滚动才能加载更多比赛,你可以在等待后加入滚动逻辑,比如:
# 滚动到页面底部加载更多内容 driver.execute_script("window.scrollTo(0, document.body.scrollHeight);") # 等待新内容加载 WebDriverWait(driver, 10).until( EC.presence_of_all_elements_located((By.XPATH, team_xpath)) ) - 部分地区访问BetMGM可能需要验证身份,确保你的浏览器会话能正常访问目标页面。
内容的提问来源于stack exchange,提问作者Steven Newton
相关产品推荐
相关产品推荐

