Selenium 常用操作 API

1. 元素本身属性操作

获取元素状态或内容,用于断言或逻辑判断。

复制代码
# 假设已定位到元素: element = driver.find_element(By.ID, "xxx")

# 1. 获取元素文本 (获取标签对之间的文本,不含 HTML 标签)
text_content = element.text

# 2. 判断元素是否被选中 (常用于单选框 radio、复选框 checkbox)
is_checked = element.is_selected()  # 返回 True/False

# 3. 判断元素是否可用 (未被 disabled 禁用)
is_usable = element.is_enabled()    # 返回 True/False

# 4. 判断元素是否可见 (在页面上显示且宽高不为0)
is_visible = element.is_displayed() # 返回 True/False


模拟点击:element.click()
模拟输入:element.send_keys()
模拟清除:element.clear()
页面刷新:element.refresh()

2. 浏览器窗口操作

控制浏览器窗口的行为和生命周期。

复制代码
# 1. 最大化窗口
driver.maximize_window()

# 2. 刷新页面
driver.refresh()

# 3. 后退 (相当于点击浏览器后退按钮)
driver.back()

# 4. 前进 (相当于点击浏览器前进按钮)
driver.forward()

# 5. 退出 (关闭所有关联窗口并结束驱动进程,务必在脚本末尾使用)
driver.quit()
# 注意: driver.close() 仅关闭当前焦点窗口

3. 滚动条处理 (JavaScript 执行)

Selenium 无法直接操作滚动条,需通过执行 JS 代码实现。

复制代码
# 1. 定义 JS 字符串
# 方式 A: 滚动到绝对坐标 (x=横向, y=纵向)
js_scroll_abs = "window.scrollTo(0, 500)" 

# 方式 B: 滚动到底部
js_scroll_bottom = "window.scrollTo(0, document.body.scrollHeight)"

# 方式 C: 滚动到特定元素位置 (需先定位元素)
# element = driver.find_element(By.ID, "footer")
# js_scroll_elem = "arguments[0].scrollIntoView();"

# 2. 执行 JS 代码
driver.execute_script(js_scroll_abs)

4. 截图处理

用于自动化测试失败时的现场保留或验证。

复制代码
# 截取整个页面并保存为文件
# 参数为文件路径 (支持 .png)
driver.get_screenshot_as_file("./screenshots/error_page.png")

# 或者获取二进制数据 (不保存文件,用于内存处理)
# img_data = driver.get_screenshot_as_png()

5. 多窗口/标签页切换

当点击链接打开新标签页时,需切换句柄(Handle)才能操作新窗口。

复制代码
# 1. 获取所有窗口句柄 (列表形式)
handles = driver.window_handles

# 2. 切换到指定窗口 (通过下标或具体句柄值)
# 切换到最新打开的窗口 (通常是列表最后一个)
driver.switch_to.window(handles[-1])

# 切换到第一个窗口
driver.switch_to.window(handles[0])

# 3. (可选) 关闭当前窗口后切回主窗口
# driver.close()
# driver.switch_to.window(driver.window_handles[0])

6. Frame/Iframe 切换

若元素位于 <iframe><frame> 内部,必须先切换进入,操作完后再切出。

复制代码
# 1. 定位到 frame 元素
frame_element = driver.find_element(By.ID, "login_frame") 
# 或者直接通过 ID/Name 字符串: driver.switch_to.frame("login_frame")

# 2. 切换到该 frame (之后只能操作 frame 内部的元素)
driver.switch_to.frame(frame_element)

# ... 执行内部元素操作 ...

# 3. 切回主文档 (默认内容),以便操作外部元素
driver.switch_to.default_content()

# (可选) 切换到父级 frame (若嵌套多层)
# driver.switch_to.parent_frame()

7. 时间等待机制

解决页面加载慢导致的 NoSuchElementException

A. 强制等待 (不推荐作为主要手段)

复制代码
import time
# 程序暂停执行指定秒数,无论页面是否加载完成
time.sleep(5) 

B. 隐式等待 (全局设置)

复制代码
# 设置全局超时时间。若元素未立即出现,轮询查找直到超时。
# 只需设置一次,对后续所有 find_element 生效。
driver.implicitly_wait(10) 

C. 显式等待 (推荐,局部精准控制)

配合 WebDriverWaitexpected_conditions (EC) 使用。

复制代码
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# 初始化等待对象:最大等待10秒,每0.5秒检查一次
wait = WebDriverWait(driver, 10, poll_frequency=0.5)

# 场景 1: 等待元素可见 (推荐,确保元素不仅能找到,还能交互)
element = wait.until(
    EC.visibility_of_element_located((By.ID, "username"))
)

# 场景 2: 等待元素存在 (仅在 DOM 中,不一定可见)
element = wait.until(
    EC.presence_of_element_located((By.ID, "username"))
)

# 场景 3: 等待元素可点击
element = wait.until(
    EC.element_to_be_clickable((By.ID, "submit_btn"))
)

# 场景 4: 自定义条件 (Lambda 表达式)
element = wait.until(
    lambda x: x.find_element(By.ID, "dynamic_content")
)

8. 鼠标与键盘操作

用于处理悬停 (Hover)、拖拽 (Drag & Drop)、右键点击、双击等复杂交互。

复制代码
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.keys import Keys

# 1. 初始化动作链
actions = ActionChains(driver)

# 2. 鼠标悬停 (二级菜单常用)
# 先定位到父级菜单元素
menu_element = driver.find_element(By.ID, "menu_item")
actions.move_to_element(menu_element).perform() # .perform() 必须调用以执行动作
# action.perform() 执行鼠标动作

# 3. 右键点击
# actions.context_click(element).perform()

# 4. 双击
# actions.double_click(element).perform()

# 5. 拖拽 (从源元素拖到目标元素)
# source = driver.find_element(By.ID, "drag")
# target = driver.find_element(By.ID, "drop")
# actions.drag_and_drop(source, target).perform()

# 6. 键盘组合键 (如: Ctrl+A 全选, Ctrl+C 复制)
# input_box = driver.find_element(By.ID, "content")
# input_box.send_keys(Keys.CONTROL, "a") # 全选
# input_box.send_keys(Keys.CONTROL, "c") # 复制

9. 浏览器原生弹框处理

针对 window.alert, window.confirm, window.prompt 生成的原生弹窗,无法用普通元素定位。

复制代码
from selenium.webdriver.common.alert import Alert

# 1. 切换到弹框
alert = driver.switch_to.alert

# 2. 获取弹框文本内容
alert_text = alert.text

# 3. 点击"确定" (接受)
alert.accept()

# 4. 点击"取消" (解散,仅适用于 confirm/prompt)
# alert.dismiss()

# 5. 在 prompt 弹框中输入内容
# alert.send_keys("输入的内容")
# alert.accept()

10. 下拉框处理 (Select)

针对标准的 <select> 标签,Selenium 提供了专用类 Select

复制代码
from selenium.webdriver.support.ui import Select

# 1. 定位到 select 元素
select_element = driver.find_element(By.ID, "province")
dropdown = Select(select_element)

# 2. 通过可见文本选择
dropdown.select_by_visible_text("北京市")

# 3. 通过 value 属性值选择
dropdown.select_by_value("BJ")

# 4. 通过索引选择 (从0开始)
dropdown.select_by_index(1)

# 5. 取消选择 (仅支持多选下拉框)
# dropdown.deselect_all()
# dropdown.deselect_by_visible_text("北京市")

# 6. 判断是否多选
is_multi = dropdown.is_multiple

11. 其他 JavaScript 高级用法

除了滚动条,JS 还可用于修改元素属性(绕过前端限制)或直接点击。

复制代码
# 1. 移除元素的 disabled 属性 (强制启用按钮)
# btn = driver.find_element(By.ID, "submit_btn")
# driver.execute_script("arguments[0].removeAttribute('disabled')", btn)

# 2. 直接通过 JS 点击元素 (当 element.click() 被遮挡或失效时)
# driver.execute_script("arguments[0].click()", btn)

# 3. 修改输入框的值 (绕过某些监听事件限制)
# input_box = driver.find_element(By.ID, "username")
# driver.execute_script("arguments[0].value='admin'", input_box)

# 4. 获取页面标题或当前 URL (通常直接用 driver.title / driver.current_url,但也可用 JS)
# title = driver.execute_script("return document.title")

12. 定位不到元素?排查清单 (Troubleshooting) 🛠️

当报错 NoSuchElementExceptionElementNotInteractableException 时,按此顺序检查:

序号 可能原因 解决方案
1 元素未加载 页面慢,元素还没出来。解决 :加显式等待 (WebDriverWait)。
2 在 Frame 里 元素在 <iframe> 内部,主文档找不到。解决switch_to.frame()
3 在新窗口 点击后开了新标签页,焦点还在旧窗口。解决switch_to.window()
4 需要悬停 元素是隐藏菜单,需鼠标移上去才显示。解决ActionChains.move_to_element()
5 属性动态变化 ID 或 Class 是随机生成的 (如 id="btn_123" )。解决:改用 XPath 模糊匹配或稳定属性。
6 元素被遮挡 有广告弹窗或透明层盖住了元素。解决 :先关闭弹窗,或用 execute_script 强制点击。
7 不在可视区 元素在屏幕下方,未滚动到。解决scrollIntoView 滚动。
8 非标准下拉框 不是 <select> 标签,而是 div+ul+li 模拟的。解决 :直接用普通元素定位点击,不要用 Select 类。

13. 验证码处理方案 (Captcha Handling) 🛡️

Selenium 无法直接识别图形验证码。根据项目阶段和验证码类型,通常采用以下 4 种策略:

方案 A:测试环境"万能码/后门" (⭐⭐⭐⭐⭐ 推荐)

场景 :公司内部测试环境。
做法 :联系开发人员,在测试环境设置一个"万能验证码"(如固定输入 88881234 即可通过),或者在代码中判断如果是测试账号则跳过验证逻辑。
优点 :最稳定、执行最快、维护成本最低。
缺点:需要开发配合,生产环境不可用。

复制代码
# 示例:测试环境固定验证码
if env == "test":
    code_input.send_keys("8888") # 开发约定的万能码

方案 B:Cookie 绕过法 (⭐⭐⭐⭐ 推荐)

场景 :登录一次后,后续操作不需要重复登录。
做法

  1. 手动登录一次成功网站。

  2. 获取浏览器的 Cookie (特别是包含用户身份信息的 Session ID)。

  3. 在自动化脚本启动浏览器后,先注入该 Cookie,然后刷新页面,直接处于"已登录"状态,跳过验证码步骤。
    优点 :无需识别验证码,模拟真实用户状态。
    缺点:Cookie 有有效期,过期需重新获取;首次仍需人工或识别介入。

    1. 打开首页

    driver.get("http://example.com")

    2. 添加 Cookie (格式需与浏览器一致)

    driver.add_cookie({"name": "SESSION_ID", "value": "abc123xyz...", "domain": "example.com"})

    3. 刷新页面生效

    driver.refresh()

    此时已自动登录,可直接操作内部页面

方案 C:第三方打码平台 (⭐⭐⭐ 通用方案)

场景 :必须通过真实验证码,且无后门。
做法 :调用第三方 OCR 识别平台 API(如:超级鹰、云打码、2Captcha 等)。
流程 :截图验证码 -> 发送图片到平台 -> 平台返回识别结果 -> 填入输入框。
优点 :能解决大多数常见图形验证码。
缺点:收费、有网络延迟、识别率非 100%、依赖外部服务稳定性。

复制代码
# 伪代码示例 (以超级鹰为例)
from chaojiying import ChaojiyingClient

# 1. 截取验证码元素图片
element = driver.find_element(By.ID, "captcha_img")
element.screenshot("./code.png")

# 2. 调用第三方 API
client = ChaojiyingClient('用户名', '密码', '软件ID')
result = client.post_file(9004, './code.png') # 9004代表验证码类型

# 3. 获取识别结果并输入
if result['ret'] == 0:
    code = result['pic_str']
    driver.find_element(By.ID, "captcha_input").send_keys(code)
else:
    print("识别失败")

方案 D:本地 OCR 库 (⭐⭐ 简单验证码)

场景 :验证码非常简单(纯数字、无干扰线、字体清晰)。
做法 :使用 tesseract-ocr (Python 库 pytesseract) 本地识别。
优点 :免费、无需网络。
缺点:对复杂验证码(干扰线、扭曲、点选)识别率极低,配置环境麻烦。

复制代码
import pytesseract
from PIL import Image

# 1. 截图
element.screenshot("./code.png")
# 2. 图片预处理 (去色、二值化等,提高识别率 - 需OpenCV配合)
# ... 预处理代码 ...

# 3. 识别
text = pytesseract.image_to_string(Image.open("./code.png"), lang='eng')
driver.find_element(By.ID, "captcha_input").send_keys(text.strip())

💡 核心建议

  • 首选:找开发加测试后门(方案 A)。
  • 次选:Cookie 绕过(方案 B),适合登录后的大流程测试。
  • 最后手段:第三方打码(方案 C),仅在必须验证登录功能且无其他办法时使用。
  • 避免:不要试图用 Selenium 自己去"猜"或硬编码复杂的动态验证码。

💡 Selenium 核心操作与最佳实践终极速查表

场景分类 推荐方法 / 核心类 关键语法/注意点 🏆 最佳实践建议
基础交互 click(), send_keys(), clear() 输入前建议先 clear() 清空旧值 操作前先检查 is_displayed()is_enabled(),确保元素可见且可用
状态断言 element.text, is_selected() is_enabled(), is_displayed() text 仅获取可见文本; is_系列返回布尔值 不要只依赖 find_element 不报错,务必用 is_ 系列做逻辑判断
复杂鼠标 ActionChains 必须 调用 .perform() 才会执行动作 用于悬停 (Hover)、拖拽、右键;链式调用更清晰
原生弹窗 driver.switch_to.alert 必须先切换上下文才能操作 (.accept(), .dismiss()) 仅处理浏览器原生 Alert/Confirm/Prompt,非原生模态框需用普通定位
下拉菜单 Select 仅限 <select> 标签 (select_by_visible_text 等) 若是 div+ul 模拟的下拉框,直接使用普通元素定位点击,勿用 Select 类
滚动/JS driver.execute_script() JS 是操作滚动条、修改属性的唯一途径 优先用 scrollIntoView 滚动到元素;可用于移除 disabled 属性或强制点击
Frame 切换 switch_to.frame() switch_to.default_content() 进得去必须出得来 操作完嵌套页面后,务必立即调用 default_content() 切回主文档,避免后续定位失败
多窗口 window_handles switch_to.window() 句柄是动态列表,需重新获取 切换到新窗口操作完后,若需回主窗口,记得再次切换句柄
等待机制 WebDriverWait + EC 拒绝 滥用 time.sleep() 慎用 全局隐式等待 首选显式等待 (精准控制),次选隐式等待,尽量避免强制等待以提高脚本稳定性
环境清理 driver.quit() 关闭所有窗口并结束驱动进程 务必放在 finally 块或 tearDown 方法中,确保即使报错也能执行资源释放
相关推荐
2301_816651222 小时前
如何从Python初学者进阶为专家?
jvm·数据库·python
2501_918126912 小时前
学习所有python写服务器的语句
服务器·人工智能·python·学习·个人开发
m0_569881472 小时前
使用Python自动收发邮件
jvm·数据库·python
极光代码工作室2 小时前
基于机器学习的房价预测系统设计与实现
人工智能·python·深度学习·机器学习
weixin_421922692 小时前
使用Python进行图像识别:CNN卷积神经网络实战
jvm·数据库·python
Csvn2 小时前
异常处理与错误调试
python
Csvn2 小时前
Python 面向对象编程基础:类与对象
python
yy我不解释2 小时前
关于comfyui的mmaudio音频生成插件时时间不一致问题(四)(video upload)(解决方法)
开发语言·python·ai作画·音视频·comfyui
2301_776508722 小时前
用Python和Twilio构建短信通知系统
jvm·数据库·python