
本文详解为何 find_element(By.CLASS_NAME, "class1 class2") 会失败,并提供使用 By.CSS_SELECTOR 精准定位含多个类名元素的完整解决方案,附带显式等待、常见错误避坑与可运行代码示例。
本文详解为何 `find_element(by.class_name, "class1 class2")` 会失败,并提供使用 `by.css_selector` 精准定位含多个类名元素的完整解决方案,附带显式等待、常见错误避坑与可运行代码示例。
在 Selenium 自动化测试中,初学者常误以为 By.CLASS_NAME 支持传入多个空格分隔的类名(如 "css-v84xw-NakedButton eml2css7"),但这是根本性误解:By.CLASS_NAME 仅接受单个、不包含空格的类名字符串,且它匹配的是元素 class 属性中恰好等于该字符串的单一类(注意:不是“包含”,更不支持多类组合)。
观察目标按钮的 HTML 片段:
<button data-testid="expand-offer-summary" aria-label="Expand offer details" type="button" class="css-v84xw-NakedButton eml2css7"> <svg>...</svg></button>
其 class 属性包含两个独立类名:css-v84xw-NakedButton 和 eml2css7。此时若调用:
driver.find_element(By.CLASS_NAME, "css-v84xw-NakedButton eml2css7") # ❌ 错误!空格导致异常
Selenium 会将其视为一个类名字符串,而 DOM 中并不存在名为 "css-v84xw-NakedButton eml2css7" 的类(实际是两个类),因此抛出 NoSuchElementException。
✅ 正确做法是使用 CSS 选择器(By.CSS_SELECTOR):
- 若需同时匹配两个类(即元素必须同时具有这两个类),应写作:
".css-v84xw-NakedButton.eml2css7"(无空格,表示“同一个元素拥有这两个类”) - 若用空格(如 ".css-v84xw-NakedButton .eml2css7"),则表示后代选择器(即 .eml2css7 是 .css-v84xw-NakedButton 的某个后代元素),这通常不符合意图。
此外,原始代码存在多个关键问题,需一并修正:
- 缺少显式等待:页面动态加载内容(如酒店房型区域)需等待目标按钮可点击,而非仅依赖 implicitly_wait;
- 重复导入:webdriver 被导入两次,属冗余;
- 未关闭浏览器:脚本结束未调用 driver.quit(),易致资源泄漏;
- find_element('class name', ...) 写法已弃用:新版本 Selenium 要求使用 By 枚举常量。
以下是修复后的健壮代码示例(含错误处理与最佳实践):
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
def expand_rooms():
driver = webdriver.Chrome()
try:
driver.get("https://www.qantas.com/hotels/properties/18482?adults=2&checkIn=2024-04-16&checkOut=2024-04-17&children=0&infants=0#view-rooms")
# 显式等待:等待按钮出现且可点击(推荐!)
wait = WebDriverWait(driver, 15)
expand_btn = wait.until(
EC.element_to_be_clickable((By.CSS_SELECTOR, ".css-v84xw-NakedButton.eml2css7"))
)
expand_btn.click()
print("✅ 房型详情已成功展开")
except Exception as e:
print(f"❌ 操作失败:{e}")
finally:
driver.quit() # 确保浏览器关闭
if __name__ == "__main__":
expand_rooms()
? 关键注意事项总结:
- ✅ 始终优先使用 By.CSS_SELECTOR 定位含多个类的元素,语法简洁且语义明确;
- ✅ 务必结合 WebDriverWait + expected_conditions 实现可靠等待,避免 NoSuchElementException 或 ElementNotInteractableException;
- ❌ 禁止在 By.CLASS_NAME 中传入含空格的字符串;
- ⚠️ 动态类名(如 eml2css7)可能随前端构建变化,建议结合更稳定的属性定位(如 data-testid="expand-offer-summary"):
driver.find_element(By.CSS_SELECTOR, "[data-testid='expand-offer-summary']")
- ? 使用浏览器开发者工具(F12)实时验证 CSS 选择器是否唯一命中目标元素。
掌握此方法,即可高效、稳定地定位现代 Web 应用中普遍存在的多类名动态元素。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











