
Selenium 4 及更高版本已彻底移除所有 find_element_by_* 和 find_elements_by_* 方法,必须改用 By 类配合 find_element()/find_elements() 调用,否则将触发 AttributeError。本文详解迁移步骤、代码重构要点及最佳实践。
selenium 4 及更高版本已彻底移除所有 `find_element_by_*` 和 `find_elements_by_*` 方法,必须改用 `by` 类配合 `find_element()`/`find_elements()` 调用,否则将触发 attributeerror。本文详解迁移步骤、代码重构要点及最佳实践。
在 Selenium 4(2021年10月发布)中,官方正式弃用了所有以 find_element_by_*(如 find_element_by_class_name、find_element_by_id)和 find_elements_by_* 命名的定位方法。这一变更旨在统一 API 设计、提升可维护性,并与 WebDriver W3C 标准保持一致。若继续使用旧语法,运行时将抛出 AttributeError: 'WebDriver' object has no attribute 'find_elements_by_class_name' —— 正如你在示例代码中所遇到的错误。
✅ 正确迁移方式:使用 By 类 + 显式导入
首先,确保导入 By 枚举类:
from selenium import webdriver from selenium.webdriver.common.by import By # ? 关键:必须显式导入 from selenium.webdriver.common.keys import Keys
然后,将所有旧式调用替换为以下格式:
| 旧写法(已失效) | 新写法(推荐) |
|---|---|
| driver.find_element_by_class_name("word") | driver.find_element(By.CLASS_NAME, "word") |
| driver.find_elements_by_class_name("word") | driver.find_elements(By.CLASS_NAME, "word") |
| div.find_elements_by_tag_name("letter") | div.find_elements(By.TAG_NAME, "letter") |
| driver.find_element_by_id("wordsInput") | driver.find_element(By.ID, "wordsInput") |
? 注意:find_element() 返回单个 WebElement(找不到则抛 NoSuchElementException),find_elements() 返回空列表(而非异常),二者语义更清晰、行为更可预测。
✅ 修复后的完整示例代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.edge.service import Service # 推荐显式管理 driver service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 推荐:使用 Service 显式指定 EdgeDriver 路径(如需)
# service = Service("/path/to/msedgedriver")
# driver = webdriver.Edge(service=service)
driver = webdriver.Edge()
try:
driver.get("https://example.com")
# ✅ 使用 By.CLASS_NAME 定位多个 div
letters_divs = driver.find_elements(By.CLASS_NAME, "word")
for div in letters_divs:
# ✅ 使用 By.TAG_NAME 定位子元素
letters = div.find_elements(By.TAG_NAME, "letter")
for letter in letters:
# ✅ 使用 By.ID 定位输入框(推荐 find_element + 显式等待)
target_element = WebDriverWait(driver, 5).until(
EC.element_to_be_clickable((By.ID, "wordsInput"))
)
target_element.send_keys(letter.text)
finally:
driver.quit()
⚠️ 重要注意事项
- 不要混用新旧语法:一旦升级到 Selenium 4.0+,所有 find_element_by_* 调用均会失败,无兼容层。
- 优先使用 find_element() + WebDriverWait:相比直接调用 find_element(),显式等待可避免 ElementNotInteractableException 或 StaleElementReferenceException,大幅提升稳定性。
-
检查标签名是否真实存在:
并非 HTML 标准标签,请确认目标页面实际使用的是自定义元素(如 Web Component)或拼写错误(常见误写为 );若为自定义标签,需确保浏览器支持且元素已渲染完成。 -
批量输入优化建议:频繁调用 send_keys() 效率较低。如需输入整词,可先聚合文本再一次性发送:
word_text = "".join(letter.text for letter in letters) target_element.send_keys(word_text)
✅ 总结
Selenium 的定位 API 迁移是向标准化、健壮性和可读性迈出的关键一步。核心原则只有三点:
① 必导 By(from selenium.webdriver.common.by import By);
② 必用 find_element(By.XXX, "value") 替代所有 find_element_by_*;
③ 必配显式等待,尤其对动态加载内容。
遵循此模式,你的自动化脚本将更稳定、更易维护,并与未来 Selenium 版本持续兼容。










