Python中Selenium抓取YouTube链接遇stale element reference错误
修改方案及代码优化
问题分析
- Stale Element错误:点击搜索按钮后重复调用
driver.get(new_path),导致页面重新加载,后续操作可能引用失效的元素;滚动加载后页面DOM更新,若元素引用未同步更新也会触发该错误。 - 链接过滤失效:判断
i != "None"逻辑错误,href为空时返回的是Python的None对象而非字符串"None",导致过滤逻辑无法生效。 - 元素定位冗余:遍历所有
a标签再过滤的方式效率低,可直接定位目标链接减少无效操作。
具体修改点
- 移除重复跳转:点击搜索按钮后已自动进入搜索结果页,无需再次调用
driver.get(new_path)。 - 修正过滤逻辑:将
i != "None"改为i is not None,正确识别空链接。 - 优化元素定位:用CSS选择器
a[href*="watch?v="]直接定位目标视频链接,避免全量遍历。 - 增加显式等待:滚动后等待页面元素加载完成,避免DOM未更新完全导致的元素获取失败。
- 增加去重逻辑:避免重复抓取同一视频链接。
修改后的完整代码
from selenium import webdriver import time 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 options = webdriver.ChromeOptions() options.add_experimental_option("detach", True) options.add_argument("--disable-extensions") options.add_argument("--disable-notifications") options.add_argument("--disable-advertisement") options.add_argument("--disable-popup-blocking") options.add_argument("start-maximized") driver = webdriver.Chrome(options=options) driver.get("https://youtube.com") # 等待搜索框加载并定位 search_box = WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, 'input#search')) ) search_word = input("Enter the search keyword: ") search_box.send_keys(search_word) # 等待搜索按钮加载并点击 search_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, 'button#search-icon-legacy')) ) search_button.click() SCROLL_PAUSE_TIME = 3 last_height = driver.execute_script("return document.documentElement.scrollHeight") while True: driver.execute_script("window.scrollTo(0, document.documentElement.scrollHeight);") time.sleep(SCROLL_PAUSE_TIME) new_height = driver.execute_script("return document.documentElement.scrollHeight") # 等待页面视频链接加载完成 WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, 'a[href*="watch?v="]')) ) if new_height == last_height: break last_height = new_height # 直接获取所有目标视频链接并去重 filtered_links = [] video_links = driver.find_elements(By.CSS_SELECTOR, 'a[href*="watch?v="]') for link in video_links: href = link.get_attribute("href") if href is not None and href not in filtered_links: filtered_links.append(href) print(href) # 可选:将结果保存到CSV文件 pd.DataFrame({"video_links": filtered_links}).to_csv("youtube_video_links.csv", index=False)
额外说明
- 用CSS选择器替代全量XPATH,定位更稳定且维护成本更低。
- 显式等待替代固定sleep,提升脚本对网络延迟的适应性,减少元素加载失败概率。
- 去重逻辑避免重复存储同一视频链接,优化结果质量。
内容的提问来源于stack exchange,提问作者Aleksandra25
相关产品推荐
相关产品推荐

