动态嵌套元素定位及Destiny 2战绩爬取故障求助
修复后的代码
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 from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException nested_win_lists = [] # 移到循环外,避免每次清空数据 driver = webdriver.Chrome() url = "https://destinytracker.com/destiny-2/profile/psn/4611686018440125811/matches?mode=crucible" driver.get(url) wait = WebDriverWait(driver, 30, ignored_exceptions=(NoSuchElementException, StaleElementReferenceException)) # 等待战绩列表加载完成 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 = game_report.find_element(By.CLASS_NAME, "trn-gamereport-list__group-entries") win_match = group_entry.find_elements(By.CLASS_NAME,"trn-match-row--outcome-win") win_match = win_match[0:2] # 仅处理前2场获胜对局 for win_element in win_match: # 精准定位当前获胜对局的点击区域,避免误点其他对局 win_left = win_element.find_element(By.CLASS_NAME, "trn-match-row__section--left") driver.execute_script("arguments[0].scrollIntoView();", win_left) wait.until(EC.element_to_be_clickable(win_left)).click() # 等待对局详情页面加载 wait.until(EC.visibility_of_element_located((By.CLASS_NAME,"match-rosters"))) # 合并两队所有条目,统一遍历 team_alpha = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.match-roster.alpha"))) team_bravo = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.match-roster.bravo"))) all_entries = team_alpha.find_element(By.CLASS_NAME,"roster-entries").find_elements(By.CLASS_NAME,"entry") + \ team_bravo.find_element(By.CLASS_NAME, "roster-entries").find_elements(By.CLASS_NAME,"entry") target_name = "Murtala" found = False for entry in all_entries: try: # 从当前条目内定位用户名,避免全局匹配错误 name = entry.find_element(By.CLASS_NAME, "name").text if name == target_name: # 点击当前条目的详情按钮 details_btn = entry.find_element(By.CLASS_NAME, "details") wait.until(EC.element_to_be_clickable(details_btn)).click() # 从当前条目详情内提取统计数据 entry_details = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "entry-details"))) left_area = entry_details.find_element(By.CLASS_NAME, "left-area") additional_stats = left_area.find_element(By.CLASS_NAME, "additional-stats") bucket_stats = additional_stats.find_element(By.CLASS_NAME, "trn-bucket-stats") # 提取所有统计值并加入列表 stat_values = [stat.find_element(By.CLASS_NAME,"value").text for stat in bucket_stats.find_elements(By.CLASS_NAME, "trn-bucket-stat")] nested_win_lists.append(stat_values) found = True break # 找到目标条目后直接退出循环,减少无效遍历 except (NoSuchElementException, StaleElementReferenceException): continue # 跳过无法定位元素的条目 # 找到目标后关闭详情弹窗 if found: wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div.close"))).click() # 输出最终结果 print(nested_win_lists) driver.quit()
关键修改说明
- 数据存储优化:将
nested_win_lists移到所有循环外部,避免每次处理新对局时清空已收集的数据。 - 对局点击精准化:从当前遍历的
win_element内部定位点击区域,解决原代码总是点击第一个获胜对局的问题。 - 两队条目合并遍历:把Alpha和Bravo队的条目合并为一个列表,一次遍历覆盖所有可能的位置,不管你在哪个队都能找到自己的条目。
- 元素查找范围限定:所有与条目相关的元素(用户名、详情按钮、统计数据)都从当前
entry或entry_details下查找,避免匹配到页面其他无关元素。 - 语法与逻辑修复:删除原代码中多余的语法错误符号,替换无效的
skip语句为合理的异常处理和循环控制。 - 等待逻辑优化:移除固定时长的
sleep,改用显式等待元素状态,提升代码稳定性和效率。 - 终止遍历逻辑:找到目标条目并提取数据后,直接退出条目循环,减少不必要的遍历操作。
内容的提问来源于stack exchange,提问作者internshiphopeful
相关产品推荐
相关产品推荐

