跳转至

最后更新:2026-09-04 01:19

实验14 鼠标键盘与窗口交互

难度:★★☆ | 预估时长:90 分钟

14.1 实验目的

  • 知识目标:理解复数定位(find_elements_by_*)返回 list 队列的原理;理解 ActionChains 队列执行机制、三种时间等待方式的区别、窗口句柄 handle 的概念。
  • 技能目标:能用 find_elements_by_* 下标操作一组元素;能用 ActionChains 完成双击/右击/悬停等鼠标操作、用 Keys 完成回车/全选/复制/粘贴;能使用强制/隐式/显式三种等待;能用 switch_to.window 进行多窗口切换。
  • 素养目标:养成"等待元素加载后再操作、操作多窗口前先切换句柄"的稳健脚本习惯。

14.2 实验环境

  1. 操作系统:Windows 10 / Windows 11;
  2. 工具:PyCharm + Python + Selenium;
  3. 浏览器:Chrome;
  4. 被测系统:人力资源综合服务系统(http://192.168.X.XXX/suthr/logon)。

14.3 实验重难点

重点:ActionChains 的 perform() 执行机制;Keys 键盘组合键;三种等待的区别;窗口句柄切换四步法。

难点:ActionChains 链式/分步写法;显式等待 WebDriverWaituntil + lambda 理解;多窗口操作前必须切换句柄。

14.4 实验内容

14.4.1 复数定位方式

1. 任务描述 用复数定位(find_elements_by_*)定位一组元素,并通过下标操作其中的元素。

2. 实验步骤

  • 步骤 1:记住复数定位的对应关系(在单数后加 s):

复数定位对应关系

图 14-1:复数定位对应关系
单数 复数
find_element_by_id find_elements_by_id
find_element_by_name find_elements_by_name
find_element_by_class_name find_elements_by_class_name
find_element_by_tag_name find_elements_by_tag_name
find_element_by_link_text find_elements_by_link_text
find_element_by_partial_link_text find_elements_by_partial_link_text
find_element_by_xpath find_elements_by_xpath
find_element_by_css_selector find_elements_by_css_selector
  • 步骤 2:理解返回值:复数定位返回一组同类元素,是一个 list 队列,可以通过下标 [0][1] 取单个元素。

  • 步骤 3:实例——用户名和密码输入框都有共同的标签 input,用户名排第一个:

1
2
3
4
5
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://192.168.X.XXX/suthr/logon")
driver.find_elements_by_tag_name("input")[0].send_keys("hrteacher")  # 输入用户名
driver.find_elements_by_tag_name("input")[1].send_keys("123456")     # 输入密码

复数定位是什么?

find_elements_by_*(注意复数多了 s)会一次性返回一组元素,装在一个 list 里;再用 [0][1] 按下标取出某一个,特别适合"页面上一排结构相同的元素"。

数组下标从 0 开始

[0] 是第一个元素、[1] 是第二个元素。复数定位尤其适合"页面结构相同的一批元素"。

常见错误与排错

  • 若下标超范围报 IndexError:说明该标签数量不够,检查页面到底有几个这样的元素;
  • 若复数定位返回空列表:确认定位方式拼写正确、元素已加载(可加等待)。

14.4.2 鼠标模拟操作 ActionChains

1. 任务描述 使用 ActionChains 完成双击、右击、单击、悬停等鼠标操作。

2. 实验步骤

  • 步骤 1:导入 ActionChains 并理解执行原理:

ActionChains常用方法表

图 14-2:ActionChains常用方法表
from selenium.webdriver import ActionChains

ActionChains 调用时不会立即执行,而是把操作按顺序放进一个队列; - 调用 perform() 时才按队列顺序执行,perform() 必须放在最后。

  • 步骤 2:两种写法(本质一样):
1
2
3
4
5
6
7
8
# 链式写法
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

# 分步写法
actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()
  • 步骤 3:实例——双击、右击、单击、悬停:
import time
from selenium import webdriver
from selenium.webdriver import ActionChains

driver = webdriver.Chrome()
driver.get("http://192.168.X.XXX/suthr/logon")
driver.find_element_by_name("username").send_keys("hrteacher")
time.sleep(5)
a = driver.find_element_by_name("username")
ActionChains(driver).double_click(a).perform()    # 双击
time.sleep(5)
ActionChains(driver).context_click(a).perform()   # 右击
time.sleep(5)
driver.find_element_by_name("password").send_keys("123456")
time.sleep(5)
b = driver.find_element_by_class_name("uppercase")
ActionChains(driver).click(b).perform()           # 单击"登录"
time.sleep(5)
c = driver.find_element_by_xpath("/html/body/div[1]/div/div[2]/div[2]/ul/li[7]/a/span")
ActionChains(driver).move_to_element(c).perform() # 悬停

ActionChains 为什么最后才 perform()?

它像一个"排队下单"的过程:双击、右击、悬停等操作只是先排进队列,perform() 才是"提交订单"真正执行。所以 perform() 必须写在最后。

常用 ActionChains 方法

click() 单击、double_click() 双击、context_click() 右击、move_to_element() 鼠标悬停、drag_and_drop() 拖拽。

常见错误与排错

  • 若操作没反应:忘了写 perform(),或把 perform() 写在了中间而非最后;
  • 若报 ActionChains is not defined:检查是否 from selenium.webdriver import ActionChains

14.4.3 键盘模拟操作 Keys

1. 任务描述 使用 Keys 模拟回车、全选、复制、粘贴等键盘操作。

2. 实验步骤

  • 步骤 1:导入 Keys 模块:

Keys键盘按键对照表

图 14-3:Keys键盘按键对照表
from selenium.webdriver.common.keys import Keys
  • 步骤 2:两种键盘操作方式:
1
2
3
4
5
# 方式1:ActionChains 先移动鼠标,再键盘操作
ActionChains(driver).send_keys(Keys.TAB).send_keys(Keys.ENTER).perform()

# 方式2:定位元素后用 send_keys 做键盘操作
driver.find_element_by_id("kw").send_keys(Keys.ENTER)   # 回车
  • 步骤 3:实例——输入信息后全选、复制、粘贴、回车查询:
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.get("http://192.168.X.XXX/suthr/logon")
driver.find_element_by_name("username").send_keys("hrteacher")
driver.find_element_by_name("password").send_keys("123456")
driver.find_element_by_class_name("uppercase").click()      # 登录
driver.find_element_by_link_text("培训进修").click()        # 培训进修
driver.find_element_by_id("content").send_keys("dd")        # 输入 dd
time.sleep(3)
driver.find_element_by_id("content").send_keys(Keys.CONTROL, 'a')  # 全选
time.sleep(3)
driver.find_element_by_id("content").send_keys(Keys.CONTROL, 'c')  # 复制
time.sleep(3)
driver.find_element_by_id("content").send_keys(Keys.CONTROL, 'v')  # 粘贴
time.sleep(3)
driver.find_element_by_id("content").send_keys(Keys.CONTROL, 'v')  # 再粘贴
time.sleep(3)
ActionChains(driver).send_keys(Keys.TAB).send_keys(Keys.TAB).send_keys(Keys.TAB).send_keys(Keys.ENTER).perform()  # 查询

Keys 键盘操作怎么用?

有两种方式:一是 ActionChains(driver).send_keys(...) 先把按键排进队列再 perform();二是直接对"已定位的元素"调用 send_keys(Keys.XXX)。组合键用逗号分隔,如 send_keys(Keys.CONTROL, 'a')

常见 Keys

Keys.ENTER 回车、Keys.TAB 制表、Keys.CONTROL + 'a/c/v' 全选/复制/粘贴、Keys.BACKSPACE 退格、Keys.F5 刷新。

常见错误与排错

  • Keys 报未定义:检查 from selenium.webdriver.common.keys import Keys
  • 若组合键无效:注意格式是 send_keys(Keys.CONTROL, 'a')(逗号分隔),别写成字符串拼接。

14.4.4 时间等待处理

1. 任务描述 掌握显式等待、隐式等待、强制等待三种等待方式。

2. 实验步骤

  • 步骤 1:理解三种等待:
等待方式 关键字 特点
强制等待 sleep(秒) 非智能,必须等够设定时间,便于观察效果
隐式等待 driver.implicitly_wait(秒) 智能等待,最长时间为设定值
显式等待 WebDriverWait(...).until(...) 等某个条件发生才继续,超时抛异常
  • 步骤 2:强制等待 sleep()——最简单但"死等":
1
2
3
4
from time import sleep
# 输入用户名密码后等5秒再点登录
sleep(5)
driver.find_element_by_class_name("uppercase").click()
  • 步骤 3:隐式等待 implicitly_wait()——设置等待时间范围(最长等待时间):
1
2
3
4
driver = webdriver.Chrome()
driver.get("http://192.168.X.XXX/suthr/logon")
driver.implicitly_wait(30)   # 全局智能等待,最长30秒
driver.find_element_by_name("username").send_keys("hrteacher")
  • 步骤 4:显式等待 WebDriverWait()——等元素出现后再继续:
1
2
3
4
5
from selenium.webdriver.support.wait import WebDriverWait

element = WebDriverWait(driver, 10).until(
    lambda x: x.find_element_by_id("loginBtn"))   # 等"登录"按钮出现
element.click()

格式:WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None) - until(method):直到返回值为 True 才继续;until_not(method):直到返回值为 False 才继续。

三种等待怎么选?

  • 观察效果/演示:用 sleep()
  • 一般脚本:用隐式等待 implicitly_wait() 打底;
  • 关键元素:用显式等待 WebDriverWait().until() 最稳。

常见错误与排错

  • 若页面没加载完就操作,报"找不到元素":别只靠 sleep,优先加隐式或显式等待;
  • 若显式等待报 TimeoutException:检查 until 里的条件元素是否真的会出现、定位是否正确。

14.4.5 窗口切换

1. 任务描述 处理点击链接后新开窗口的情况,用句柄(handle)切换窗口。

2. 实验步骤

  • 步骤 1:理解句柄:浏览器每个窗口有一个唯一标识(handle),切换窗口就是切换句柄。

  • 步骤 2:窗口切换四步法

1
2
3
4
5
6
7
8
# 1. 获取当前(第一个)窗口名
print(driver.current_window_handle)
# 2. 获取所有窗口名
print(driver.window_handles)
# 3. 获取第二个窗口名(数组下标原理)
print(driver.window_handles[1])
# 4. 切换窗口
driver.switch_to.window(driver.window_handles[1])
  • 步骤 3:完整实例——登录后点开新标签页并切换:
import time
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://192.168.X.XXX/suthr/logon")
driver.implicitly_wait(30)
driver.find_element_by_name("username").send_keys("hrteacher")
driver.find_element_by_name("password").send_keys("123456")
driver.find_element_by_class_name("uppercase").click()     # 登录
driver.find_element_by_link_text("人资工作台").click()
driver.find_element_by_link_text("论坛后台管理").click()
driver.find_element_by_link_text("举报处理").click()
driver.find_element_by_link_text("回帖举报").click()
driver.find_element_by_xpath("/html/body/div[4]/div[2]/div/div[2]/div/div/div[2]/div[2]/table/tbody/tr[1]/td[10]/a[1]").click()  # 举报流水
print(driver.current_window_handle)     # 第一个窗口
print(driver.window_handles)            # 所有窗口
print(driver.window_handles[1])         # 第二个窗口
driver.switch_to.window(driver.window_handles[1])   # 切换窗口
time.sleep(5)
driver.close()                          # 关闭新窗口

什么是句柄 handle?

每个浏览器窗口都有一个唯一编号(handle)。切换窗口,本质上是切换到对应的 handle,就像用编号在多个打开的标签页之间切换。

新窗口不切换会怎样?

点开新标签页后,如果不 switch_to.window 切换,脚本仍在旧窗口上找元素,会报"找不到元素"。先切换句柄,再操作新页面的元素

14.5 实验总结

本次实验把自动化脚本的"交互能力"补齐了:

  1. 一是掌握了复数定位(find_elements_by_* 返回 list、下标取元素)处理"一组同类元素"(对应知识/技能目标);
  2. 二是掌握了 ActionChains 鼠标操作(双击/右击/悬停,perform() 执行)与 Keys 键盘操作(回车/全选/复制/粘贴)(对应技能目标);
  3. 三是掌握了三种等待方式(强制 sleep、隐式 implicitly_wait、显式 WebDriverWait)与多窗口句柄切换(先切换句柄再操作)(对应知识/技能目标)。

14.6 作业提交

  1. 提交地点:吾爱作业网
  2. 提交资料:
  3. 14.4.2 鼠标操作实例运行结果截图;
  4. 14.4.3 键盘操作实例运行结果截图;
  5. 14.4.5 窗口切换实例运行结果截图(能看到 print 输出多个窗口名)。
  6. 不会做时填写"心得感悟"(1~50 字)。

14.7 知识检测

  • [ ] (填空)定位一组同类元素用复数方法 find_elements_by_*,它返回的是 list(列表/队列),可用 [0][1] 取下标。
  • [ ] (填空)ActionChains 把操作排进队列后,必须调用 perform() 才会真正执行。
  • [ ] (选择)想等某个元素出现后再继续,最稳的等待方式是?
  • A. sleep(10) B. implicitly_wait(10) C. WebDriverWait(...).until(...) D. 不等待
查看解析

正确答案:C。显式等待 WebDriverWait().until() 会等到条件满足才继续,超时抛异常,最精准。

  • [ ] (选择)点击链接弹出新窗口后,要操作新窗口必须先?
  • A. driver.close() B. driver.switch_to.window(handle) C. driver.back() D. driver.refresh()
查看解析

正确答案:B。不切换句柄,脚本仍在旧窗口找元素会报"找不到元素"。

本课相关资源

序号 资源名称 类型 说明
1 任务3.3 复数定位方式方法使用.pptx 课件 复数定位
2 任务3.4 鼠标模拟操作方法使用.pptx 课件 ActionChains
3 任务3.5 键盘模拟操作方法使用.pptx 课件 Keys
4 任务3.6 时间等待处理方法使用.pptx 课件 三种等待
5 任务3.7 窗口切换方法使用.pptx 课件 窗口切换

实验素材下载

点击下方链接获取本节课全部资源(含课件、任务清单、安装包等): 🔗 夸克网盘

本站总访问 次 | 访客 人 | 本页阅读