Selenium之Actions事件

鼠标、键盘组合键

在使用selenium的时候,有的时候我们需要鼠标单击、双击、拖动;或者是按下键盘的某个键,松开某个按键,以及组合键的使用;今天我们就来看一看,怎么样实现上面的操作

先把准备工作做好,需要导入ActionChains, Keys这两个模块

perform()作用就是,执行前面动作链的所有操作

复制代码
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By

serve_path = r'D:\Code_Study\driver\chromedriver-win64\chromedriver.exe'
service = Service(serve_path)
browser = webdriver.Chrome(service=service)
url = r"https://selenium.dev/selenium/web/single_text_input.html"
browser.get(url=url)

键盘Keyboard

按下按键key_down
复制代码
# 可以看到输入框中输入的是大写单词
ActionChains(driver=browser).key_down(Keys.SHIFT).send_keys("selenium").perform()
释放按键key_up
复制代码
松开按键key_up,可以看到先输入大写的HELLO,之后输入小写的world
ActionChains(driver=browser).key_down(Keys.SHIFT).send_keys("hello").key_up(Keys.SHIFT).send_keys("world").perform()
键入
  • 活跃元素send_keys

    复制代码
    # 可以看到打开网页的一瞬间, 就输入了内容;当然,还是先定位到元素,在对元素进行send_keys()的方法好用
    ActionChains(driver=browser).send_keys("selenium").perform()
  • 指定元素send_keys_to_element

    复制代码
    # 首先是定位到元素,在对元素进行内容输入
    text_input = browser.find_element(By.ID, "textInput")
    ActionChains(driver=browser).send_keys_to_element(text_input,"selenium").perform()
复制粘贴
复制代码
# send_keys(Keys.ARROW_LEFT) - 按一次左箭头键,将光标移动到"Selenium"的最后一个字母'm'的后面
# key_down(Keys.SHIFT) - 按下Shift键(不松开)
# send_keys(Keys.ARROW_UP) - 在按住Shift的同时按上箭头键(通常用于向上选择文本)
# key_up(Keys.SHIFT) - 松开Shift键
# key_down(cmd_ctrl) - 按下Command键(Mac)或Control键(Windows)
# send_keys("xvv") - 在按住Command/Control键的同时输入:
# 'x' - 通常是剪切操作(Command+X/Ctrl+X)
# 'v' - 粘贴操作(Command+V/Ctrl+V)
# 第二个'v' - 再次粘贴
# key_up(cmd_ctrl) - 松开Command/Control键
cmd_ctrl = Keys.COMMAND if sys.platform == "darwin" else Keys.CONTROL
ActionChains(driver=browser).send_keys("Selenium")\
    .send_keys(Keys.ARROW_LEFT).key_down(Keys.SHIFT)\
    .send_keys(Keys.ARROW_UP).key_up(Keys.SHIFT)\
    .key_down(cmd_ctrl).send_keys("xvv").key_up(cmd_ctrl).perform()

鼠标Mouse

复制代码
url = r"https://selenium.dev/selenium/web/single_text_input.html"
browser.get(url=url)
点击鼠标左键click
复制代码
# 可以看到点击了一个链接,进入了一个新页面
clickable =browser.find_element(By.ID,"click")
ActionChains(driver=browser).click(clickable).perform()
按住鼠标左键click_and_hold
复制代码
# 可以看到点击一下,右侧展示【focused】;
clickable = browser.find_element(By.ID,"clickable")
ActionChains(driver=browser).click_and_hold(clickable).perform()
双击左键double_click
复制代码
# 点击二下右侧展示【double-clicked】
clickable = browser.find_element(By.ID,"clickable")
ActionChains(driver=browser).double_click(clickable).perform()
assert browser.find_element(By.ID, "click-status").text == "double-clicked"
点击鼠标右键context_click
复制代码
# 可以看到点击右键的一些信息和平时手动右键出现的内容一模一样
clickable = browser.find_element(By.ID, "clickable")
ActionChains(driver=browser) \
        .context_click(clickable) \
        .perform()

鼠标对应按键数字

复制代码
"""
使用 数字 代替 MouseButton.FORWARD:
0 = 左键(MouseButton.LEFT)
1 = 中键(MouseButton.MIDDLE)
2 = 右键(MouseButton.RIGHT)
3 = 前进侧键(MouseButton.FORWARD)
4 = 后退侧键(MouseButton.BACK)
"""
点击鼠标前进键MouseButton.FORWARD
复制代码
# 可以看到鼠标点击链接跳转后,再后退以下;然后会前进一步
from selenium.webdriver.common.actions.action_builder import ActionBuilder
from selenium.webdriver.common.devtools.v132.input_ import MouseButton

# 点击click后,链接的title为We Arrive Here
browser.find_element(By.ID,"click").click()
time.sleep(3)
browser.back()
print(browser.title)
assert browser.title == "BasicMouseInterfaceTest"


# ActionBuilder 是 Selenium 提供的一个底层动作构造器,用于构建复杂的输入设备(如鼠标、键盘、触摸屏等)操作。
这里初始化了一个 ActionBuilder 对象,绑定到当前的浏览器实例 browser。
# pointer_action表示鼠标指针操作
# pointer_down、pointer_up表示按下、释放;往往成对出现
# action = ActionBuilder(driver=browser)
# 这里我的鼠标对应的4,才是前进键;其他的可以各位私下尝试
# 因为使用方法会报错,这里用了数字可以使用
action.pointer_action.pointer_down(4)
action.pointer_action.pointer_up(4)
action.perform()
print(browser.title)
assert browser.title == "We Arrive Here"
点击鼠标回退键MouseButton.BACK
复制代码
browser.find_element(By.ID, "click").click()
assert browser.title == "We Arrive Here"
print(browser.title)

# ActionBuilder 是 Selenium 提供的一个底层动作构造器,用于构建复杂的输入设备(如鼠标、键盘、触摸屏等)操作。
这里初始化了一个 ActionBuilder 对象,绑定到当前的浏览器实例 browser。
# pointer_action表示鼠标指针操作
# pointer_down、pointer_up表示按下、释放;往往成对出现

action = ActionBuilder(browser)

# 这里我的鼠标对应的3,才是前进键;其他的可以各位私下尝试
# 因为使用方法会报错,这里用了数字可以使用
action.pointer_action.pointer_down(3)
action.pointer_action.pointer_up(3)
action.perform()
print(browser.title)
assert browser.title == "BasicMouseInterfaceTest"
移动光标到元素上move_to_element
复制代码
# 可以看到鼠标移动过去,右侧展示文字
hoverable = browser.find_element(By.ID, "hover")
ActionChains(driver=browser).move_to_element(hoverable).perform()
通过偏移量移动光标
  • 先移动到指定的坐标原点

  • 通过px单位的偏移量进行光标相对原点的偏移移动

  • 光标位置必须在可视化窗口区域,否则报错

从元素中心点【原点】偏移move_to_element_with_offset

先将光标移动到元素中心点(原点),然后通过偏移量进行光标相对原点的偏移。

python 复制代码
move_to_element_with_offset接受三个参数,可以查看源码
move_to_element_with_offset(self, to_element: WebElement, xoffset: int, yoffset: int) -> ActionChains:
        """Move the mouse by an offset of the specified element. Offsets are
        relative to the in-view center point of the element.

        :Args:
         - to_element: The WebElement to move to.
         - xoffset: X offset to move to, as a positive or negative integer.
         - yoffset: Y offset to move to, as a positive or negative integer.
        """

        self.w3c_actions.pointer_action.move_to(to_element, int(xoffset), int(yoffset))
        self.w3c_actions.key_action.pause()

        return self
复制代码
# 先定位到元素
mouse_tracker = browser.find_element(By.ID, "mouse-tracker")
# 先移动到元素,默认就是中心点
ActionChains(driver=browser).move_to_element(mouse_tracker).click().perform()
time.sleep(5)
# x轴增加了8个px,y轴不动
ActionChains(driver=browser).move_to_element_with_offset(mouse_tracker, 8, 0).perform()
# 获取Relative Location in Box:内容
coordinates = browser.find_element(By.ID, "relative-location").text.split(",")
assert abs(int(coordinates[0]) - 100 - 8) < 2
从左上角偏移move_to_location

先将光标移动到窗口左上角原点,然后通过偏移量进行偏移

复制代码
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.ID, "absolute-location")))
action = ActionBuilder(browser)
action.pointer_action.move_to_location(8, 0)
action.perform()
coordinates = browser.find_element(By.ID, "absolute-location").text.split(", ")
assert abs(int(coordinates[0]) - 8) < 2
从当前光标位置偏移move_by_offset

光标位于当前位置的,通过偏移量进行偏移;如果之前没有移动过光标,则位置是窗口左上角;

页面发生滚动后,光标位置不会发生变化

查看源码,发现第一个参数指定为正数往右移动;第二个参数指定正数往下移动

复制代码
 move_by_offset(self, xoffset: int, yoffset: int) -> ActionChains:
        """Moving the mouse to an offset from current mouse position.

        :Args:
         - xoffset: X offset to move to, as a positive or negative integer.
         - yoffset: Y offset to move to, as a positive or negative integer.
        """

        self.w3c_actions.pointer_action.move_by(xoffset, yoffset)
        self.w3c_actions.key_action.pause()

action = ActionBuilder(browser)
# 先右移动6px;下移动3px
action.pointer_action.move_to_location(6, 3)
action.perform()
ActionChains(browser).move_by_offset(13,15).perform()
拖放元素drag_and_drop

在原元素上提交执行按下鼠标左键,移动到目标元素位置后是释放鼠标左键。

查看源码,第一个是需要移动的元素,第二个是要移动到哪里的元素,释放鼠标

复制代码
    def drag_and_drop(self, source: WebElement, target: WebElement) -> ActionChains:
        """Holds down the left mouse button on the source element, then moves
        to the target element and releases the mouse button.

        :Args:
         - source: The element to mouse down.
         - target: The element to mouse up.
        """
        self.click_and_hold(source)
        self.release(target)
        return self

draggable = browser.find_element(By.ID, "draggable")
droppable = browser.find_element(By.ID, "droppable")
ActionChains(browser).drag_and_drop(draggable, droppable).perform()
time.sleep(5)
assert browser.find_element(By.ID, "drop-status").text == "dropped"
通过偏移量拖放元素drag_and_drop_by_offset

查看源码,发现需要一个开始元素的element;和需要移动x、y的偏移量

复制代码
    def drag_and_drop_by_offset(self, source: WebElement, xoffset: int, yoffset: int) -> ActionChains:
        """Holds down the left mouse button on the source element, then moves
        to the target offset and releases the mouse button.

        :Args:
         - source: The element to mouse down.
         - xoffset: X offset to move to.
         - yoffset: Y offset to move to.
        """
        self.click_and_hold(source)
        self.move_by_offset(xoffset, yoffset)
        self.release()
        return self

首先计算需要拖动的元素的location,之后计算出要释放鼠标的元素的location;之后后者的x轴,y轴分别减去前者的x、y坐标;就是需要移动的x、y坐标的偏移量

复制代码
draggable = browser.find_element(By.ID, "draggable")
start = draggable.location
finish = browser.find_element(By.ID, "droppable").location
ActionChains(browser)\
    .drag_and_drop_by_offset(draggable,
                             finish["x"] - start["x"],
                             finish["y"] - start["y"]).perform()

assert browser.find_element(By.ID, "drop-status").text == "dropped"
相关推荐
有技巧搬砖5 小时前
为什么锂电池组的电池老化测试很重要?
测试工具·锂电池·电池老化
蒲公英内测分发9 小时前
智能手表卖出去后,包装、说明书和官网里的 App 下载入口怎么统一?
前端·人工智能·测试工具·智能家居·智能硬件·智能手表
蒲公英内测分发11 小时前
智能手环出海测试,海外合作方分散在不同国家,Android 测试包怎么持续分发和更新?
android·前端·人工智能·测试工具·智能手表
无语的小歪歪13 小时前
ATF 智测 1.0
python·测试工具·集成测试
SHENGWEI胜为1 天前
交换机端口显示正常,终端却获取不到 IP 地址?从 DHCP 流程定位故障
服务器·网络·测试工具·缓存·通信工程
xie881018021 天前
长表格跨页重复表头:排版上的做法
测试工具
老孟说禅2 天前
测试工具示波器的使用
测试工具
步行cgn2 天前
为什么使用接口测试工具?
测试工具
P1Browser2 天前
Puppeteer 与 Selenium 技术对比:多账号自动化管理如何做环境隔离?
selenium·测试工具·自动化
weihubeats3 天前
10 MB 的 Postman 替代品,启动不到 1 秒
测试工具·postman