使用Selenium爬取DestinyTracker胜利对局数据时遭遇超时异常的问题求助
Selenium爬取DestinyTracker胜利对局数据时遭遇超时异常的问题求助
我现在想从DestinyTracker网站爬取自己《命运2》Crucible模式的对局数据,目标是点击每一场胜利的对局条目,进入详情页收集个人数据。我已经写了一段代码,但总是碰到超时异常——哪怕把等待时间从20秒调到30秒也没用,找ChatGPT帮忙也没解决。奇怪的是,代码里后面的date_time有时候还能正常打印出来,实在搞不懂问题出在哪,希望有人能帮忙排查一下。
我的代码如下:
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 driver = webdriver.Chrome() url = "https://destinytracker.com/destiny-2/profile/psn/4611686018440125811/matches?mode=crucible" driver.get(url) wait = WebDriverWait(driver, 20) crucible_content = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.trn-gamereport-list.trn-gamereport-list--compact"))) game_reports = crucible_content.find_elements(By.CLASS_NAME, "trn-gamereport-list__group") for game_report in game_reports: group_entry = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "trn-gamereport-list__group-entries"))) win_match = group_entry.find_elements(By.CLASS_NAME,"trn-match-row--outcome-win") driver.execute_script("arguments[0].scrollIntoView();", win_match[0]) lose_match = group_entry.find_elements(By.CLASS_NAME, "trn-match-row--outcome-loss") for win_element in win_match: driver.execute_script("arguments[0].scrollIntoView();", win_element) win_left = wait.until(EC.presence_of_element_located((By.CLASS_NAME, "trn-match-row__section--left"))) driver.execute_script("arguments[0].click();", win_left) date_time = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='info']"))) date_time = date_time.text date_time = date_time.split(",") date_time = date_time[0] print(date_time)
可能的问题分析
- 全局元素定位导致的混乱:循环里用
wait.until全局查找元素,很可能找到页面上其他重复的元素,或者当页面跳转后,旧的元素引用失效,导致超时。 - 页面跳转后未处理返回:点击进入详情页后,没有回到列表页,后续循环还在详情页里找列表元素,必然超时。
- 元素引用失效(Stale问题):从详情页返回列表页后,之前获取的
win_match元素已经失效,继续遍历会触发异常。 - 滚动操作不彻底:
scrollIntoView()可能没让元素完全进入可视区域,导致无法点击或定位。
修正后的代码思路
下面是调整后的代码,解决了上述几个核心问题:
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 driver = webdriver.Chrome() driver.maximize_window() url = "https://destinytracker.com/destiny-2/profile/psn/4611686018440125811/matches?mode=crucible" driver.get(url) wait = WebDriverWait(driver, 30) # 等待主对局列表加载完成 wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.trn-gamereport-list.trn-gamereport-list--compact"))) # 定义函数:重新获取所有胜利对局元素,避免引用失效 def get_all_win_matches(): return wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "trn-match-row--outcome-win"))) win_matches = get_all_win_matches() # 用索引遍历,每次循环重新获取元素,规避Stale问题 for i in range(len(win_matches)): win_matches = get_all_win_matches() current_win = win_matches[i] # 滚动到元素居中位置,确保完全可见 driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", current_win) wait.until(EC.element_to_be_clickable(current_win)) # 限定在当前对局元素内查找点击区域,避免全局找错 click_area = current_win.find_element(By.CLASS_NAME, "trn-match-row__section--left") click_area.click() # 等待详情页加载,获取日期数据 date_time = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='info']"))).text date_time = date_time.split(",")[0] print(date_time) # 这里可以添加你需要的pcgr变量等数据的爬取逻辑 # 返回列表页,等待列表重新加载完成 driver.back() wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div.trn-gamereport-list.trn-gamereport-list--compact"))) driver.quit()
关键调整点说明
- 规避元素失效:每次循环都重新获取胜利对局列表,避免从详情页返回后旧元素引用失效。
- 限定查找作用域:直接在当前对局元素内查找点击区域,确保点击的是目标条目。
- 添加页面返回逻辑:爬取完详情页后回到列表页,并等待列表重新加载。
- 优化滚动效果:让元素居中显示,确保完全可见且可点击。
- 处理滚动加载(可选):如果页面需要滚动才能加载更多对局,可以在获取
win_matches前添加循环滚动逻辑,直到没有新元素加载。
备注:内容来源于stack exchange,提问作者internshiphopeful
相关产品推荐
相关产品推荐

