Selenium运行无限循环?Python爬取Genius歌词遇异常
问题分析与解决方案
核心问题排查
你的代码陷入无限运行且浏览器无法关闭,主要源于两个关键问题:
- 异常未捕获:
WebDriverWait超时会抛出TimeoutException,若未捕获该异常,程序会直接终止,driver.quit()无法执行,导致浏览器进程残留。 - 元素定位器不稳定:Genius采用React生成的动态类名(如
ReferentFragmentdesktop__Highlight-sc-110r0d9-1),这类类名会随网站版本更新变化,且可能因页面加载逻辑问题导致元素始终无法被定位,进而让等待逻辑陷入异常状态。
具体修复步骤
1. 强制保证浏览器退出(添加异常捕获)
用try-except-finally包裹核心逻辑,确保无论是否出现异常,driver.quit()都会执行:
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 TimeoutException timeout = 10 driver = launchBrowser(path) try: # 等待歌词元素加载(改用更稳定的定位器) body = EC.visibility_of_element_located( (By.CSS_SELECTOR, 'div[data-lyrics-container="true"]') ) WebDriverWait(driver, timeout).until(body) # 获取所有歌词段落 paragraphs = driver.find_elements( By.CSS_SELECTOR, 'div[data-lyrics-container="true"] span' ) # 处理歌词内容示例 for p in paragraphs: print(p.text) except TimeoutException: print("超时:未找到歌词元素") finally: # 无论成功失败,强制关闭浏览器 driver.quit()
2. 替换为稳定的元素定位器
Genius的歌词容器有固定的data-lyrics-container属性,用该属性定位比动态类名可靠得多。如果这个选择器不生效,也可尝试以下备选方案:
- CSS选择器:
.Lyrics__Container-sc-1ynbvzw-6(当前Genius歌词容器的常用类名,需根据实际页面结构调整) - XPath:
//div[contains(@class, 'Lyrics__Container')]
3. 应对Genius的反爬机制
Genius会检测Selenium的特征,导致页面加载异常或元素无法获取,可在launchBrowser函数中添加Chrome选项伪装浏览器:
from selenium import webdriver def launchBrowser(path): options = webdriver.ChromeOptions() # 禁用自动化检测 options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) # 设置真实User-Agent options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") # 可选:禁用图片加载提升爬取速度 options.add_argument("--blink-settings=imagesEnabled=false") driver = webdriver.Chrome(executable_path=path, options=options) return driver
4. 补充页面加载等待
如果页面加载缓慢,可在获取页面后添加额外等待逻辑:
driver.get("目标Genius歌词页面URL") # 等待页面完全加载 while driver.execute_script("return document.readyState") != "complete": pass
内容的提问来源于stack exchange,提问作者Kellen Karls
相关产品推荐
相关产品推荐

