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 方法中,确保即使报错也能执行资源释放
相关推荐
小康小小涵1 小时前
基于ESP32S3实现无人机RID模块底层源码编译
linux·开发语言·python
lzjava20241 小时前
Python的函数
开发语言·python
掌心向暖RPA自动化1 小时前
如何获取网页某个元素在屏幕可见部分的中心坐标影刀RPA懒加载坐标定位技巧
java·javascript·自动化·rpa·影刀rpa
Awesome Baron2 小时前
skill、tool calling、MCP区别
开发语言·人工智能·python
测试员周周2 小时前
【AI测试系统】第4篇:告别硬编码!基于 Markdown + Python 的 Skill 引擎设计:让 AI 测试系统拥有无限扩展的“灵魂”
人工智能·python·测试
武帝为此2 小时前
【Selenium 屏幕截图】
python·selenium·测试工具
念恒123063 小时前
Python(列表进阶)
python·学习
27669582923 小时前
阿里最新acw_sc__v2 分析
开发语言·python·acw_sc__v2·acw_sc__v2逆向·acw_sc__v2算法·acw_sc__v2算法分析·cookie逆向
架构源启4 小时前
OpenClaw 只能手动写脚本?我用 Chrome 插件实现了“录制即生成“
前端·人工智能·chrome·自动化
vortex54 小时前
python 库劫持:原理、利用与防御
python·网络安全·提权