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

使用Selenium捕获Oddsportal特定XHR请求遇阻求助

问题排查与解决方案

核心问题是目标XHR请求仅在页面从后台切换到前台时触发,当前代码的日志捕获逻辑和页面切换模拟方式未能满足触发条件,以下是针对性的修复方案:

1. 替换日志捕获方式:改用CDP实时事件监听

driver.get_log('performance')存在日志缓存上限,可能导致晚触发的请求日志被覆盖。改用Chrome DevTools Protocol(CDP)的Network.requestWillBeSent事件实时监听所有请求,确保不会遗漏目标请求。

2. 正确模拟页面可见性变化

Selenium的标签切换不一定能触发浏览器的visibilitychange事件(这是目标请求触发的关键条件),需要用CDP直接设置页面可见性状态,模拟从后台切回前台的操作。

3. 优化等待逻辑:去掉固定sleep,改用显式等待

固定时间的time.sleep()不稳定,改用Selenium的显式等待确保页面元素加载完成后再执行后续操作。


修改后的完整代码

import json
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# Paths
driver_path = r'C:\Users\tugbe\Desktop\basit_oddsportal\drivers\chromedriver-win64\chromedriver.exe'
binary_path = r'C:\Users\tugbe\AppData\Local\Programs\Opera\opera.exe'

# Set up Chrome options for Opera
options = Options()
options.binary_location = binary_path
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
options.debugger_address = "127.0.0.1:9222"  # Connect to existing Opera instance

# Initialize WebDriver service and driver
service = Service(driver_path)
driver = webdriver.Chrome(service=service, options=options)

# Enable Network monitoring via CDP
driver.execute_cdp_cmd('Network.enable', {})

captured_urls = set()

# Define callback to capture network requests
def capture_requests(request):
    url = request.get('params', {}).get('request', {}).get('url')
    if url and url not in captured_urls:
        captured_urls.add(url)
        print(f"捕获到请求URL: {url}")
        # 检查是否是目标请求
        if 'feed/postmatch-score' in url:
            print("✅ 找到目标比分请求!")
            # 可在此处添加获取响应的逻辑
            response = driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': request['params']['requestId']})
            print(f"比分响应内容: {json.dumps(response, indent=2)}")

# Register CDP listener for requestWillBeSent event
driver.add_cdp_listener('Network.requestWillBeSent', capture_requests)

try:
    # Open target URL in a new tab
    driver.execute_script("window.open('about:blank', '_blank');")
    driver.switch_to.window(driver.window_handles[-1])
    url = 'https://www.oddsportal.com/football/brazil/serie-a/bragantino-athletico-pr-xx0ujiJ5/'
    driver.get(url)

    # 显式等待页面加载完成(等待body元素可见)
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.TAG_NAME, 'body')))

    # 模拟页面切换到后台(设置为不可见)
    driver.execute_cdp_cmd('Page.setVisibilityState', {'state': 'hidden'})
    print("页面已切换到后台")

    # 等待2秒后切回前台(触发可见性变化)
    driver.execute_cdp_cmd('Page.setVisibilityState', {'state': 'visible'})
    print("页面已切回前台,等待捕获请求...")

    # 保持监听30秒,确保捕获到目标请求
    WebDriverWait(driver, 30).until(lambda d: any('feed/postmatch-score' in u for u in captured_urls))

finally:
    # Cleanup
    driver.remove_cdp_listener('Network.requestWillBeSent', capture_requests)
    driver.execute_cdp_cmd('Network.disable', {})
    driver.quit()

关键修复点说明

  • CDP事件监听:通过add_cdp_listener实时监听Network.requestWillBeSent事件,避免日志丢失
  • 模拟页面可见性:用Page.setVisibilityState直接设置页面状态为hidden再切换回visible,准确触发目标请求的触发条件
  • 显式等待:用WebDriverWait替代固定sleep,确保页面加载完成后再执行操作,提升稳定性
  • 目标请求检测:在回调中直接检查URL是否包含目标路径,一旦捕获到立即打印响应内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:35:58