使用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
相关产品推荐
相关产品推荐

