测试老宅男扶摇

导航

Selenium4Web自动化4-鼠标键盘模拟操作

一、 Web 元素交互

参考官方文档:https://www.selenium.dev/zh-cn/documentation/webdriver/elements/interactions/
用于操纵表单的高级指令集.
仅有五种基本命令可用于元素的操作:

  • 点击 (适用于任何元素)
  • 发送键位 (仅适用于文本字段和内容可编辑元素)
  • 清除 (仅适用于文本字段和内容可编辑元素)
  • 提交 (仅适用于表单元素)
  • 选择 (参见 选择列表元素)

这些方法的设计目的是尽量模拟用户体验, 所以, 与 Actions接口 不同, 在指定制定操作之前, 会尝试执行两件事.
1.如果它确定元素在视窗之外, 则会将元素滚动到视图中, 特别是将元素底部与视窗底部对齐.
2.确保元素在执行操作之前是可交互的 . 这可能意味着滚动不成功, 或者该元素没有以其他方式显示.确定某个元素是否显示在页面上太难了 无法直接在webdriver规范中定义, 因此Selenium发送一个带有JavaScript原子的执行命令, 检查是否有可能阻止该元素显示. 如果确定某个元素不在视窗中, 不显示, 不可 键盘交互, 或不可 指针交互, 则返回一个元素不可交互 错误.

点击

元素点击命令 执行在 元素中央. 如果元素中央由于某些原因被 遮挡 , Selenium将返回一个 元素点击中断 错误.

driver.find_element(By.NAME, "q").click()

发送键位

元素发送键位命令 将录入提供的键位到 可编辑的 元素. 通常, 这意味着元素是具有 文本 类型的表单的输入元素或具有 内容可编辑 属性的元素. 如果不可编辑, 则返回 无效元素状态 错误.
WebDriver支持的按键列表:
https://www.w3.org/TR/webdriver/#keyboard-actions

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()

    # Navigate to url
driver.get("http://www.google.com")

    # Enter "webdriver" text and perform "ENTER" keyboard action
driver.find_element(By.NAME, "q").send_keys("webdriver" + Keys.ENTER)

清除

元素清除命令 重置元素的内容. 这要求元素 可编辑, 且 可重置. 通常, 这意味着元素是具有 文本 类型的表单的输入元素或具有 内容可编辑 属性的元素. 如果不满足这些条件, 将返回 无效元素状态 错误.

from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()

    # Navigate to url
driver.get("http://www.google.com")
    # Store 'SearchInput' element
SearchInput = driver.find_element(By.NAME, "q")
SearchInput.send_keys("selenium")
    # Clears the entered text
SearchInput.clear()

提交

在Selenium 4中, 不再通过单独的端点以及脚本执行的方法来实现. 因此, 建议不要使用此方法, 而是单击相应的表单提交按钮.

二、 使用选择列表元素

与其他元素相比,选择列表具有特殊的行为.
选择元素可能需要大量样板代码(boilerplate code)才能自动化. 为了减少这种情况并使您的测试更简洁, 在Selenium的support包中有一个 Select 类. 要使用它,您将需要以下导入语句:

from selenium.webdriver.support.select import Select

然后,参考 select元素,基于WebElement创建一个Select对象。

select_element = driver.find_element(By.ID,'selectElementID')
select_object = Select(select_element)

Select对象现在将为您提供一系列命令,使您可以与 select元素进行交互. 首先,有多种方法可以从 select 元素中选择一个选项

<select>
 <option value=value1>Bread</option>
 <option value=value2 selected>Milk</option>
 <option value=value3>Cheese</option>
</select>

有三种方法可以从上述元素中选择第一个选项:

# Select an <option> based upon the <select> element's internal index
# 选项索引
select_object.select_by_index(1)

# Select an <option> based upon its value attribute
# 选项value属性值
select_object.select_by_value('value1')

# Select an <option> based upon its text
# 选项文本
select_object.select_by_visible_text('Bread')

然后,您可以检视所有被选择的选项:

# Return a list[WebElement] of options that have been selected
# 检查所有被选择的选项
all_selected_options = select_object.all_selected_options

# Return a WebElement referencing the first selection option found by walking down the DOM
# 返回列表中第一个被选择的选项
first_selected_option = select_object.first_selected_option

或者可能只对 select 元素包含哪些 option 元素感兴趣:

# Return a list[WebElement] of options that the <select> element contains
# 返回列表的所有选项
all_available_options = select_object.options

如果要取消选择任何元素,现在有四个方法(仅适用于多选列表):

# Deselect an <option> based upon the <select> element's internal index
# 选项索引
select_object.deselect_by_index(1)

# Deselect an <option> based upon its value attribute
# 选项value属性值
select_object.deselect_by_value('value1')

# Deselect an <option> based upon its text
# 选项文本
select_object.deselect_by_visible_text('Bread')

# Deselect all selected <option> elements
# 取消所有被选择的选项
select_object.deselect_all()

最后,一些 select 元素允许选择多个选项. 可以通过使用以下命令确定您的 select 元素是否允许多选:

does_this_allow_multiple_selections = select_object.is_multiple

三、Action接口

用于向 Web 浏览器提供虚拟化设备输入操作的低级接口.
除了刚刚讲过的Web元素交互之外, Actions 接口 还提供了对指定输入设备 可以执行的确切操作的精细控制. Selenium为3种输入源提供了接口: 键盘设备的键输入, 鼠标, 笔或触摸设备的输入, 以及滚轮设备的滚轮输入 (在Selenium 4.2中引入). Selenium允许您构建分配给特定输入的独立操作命令, 会将他们链接在一起, 并调用关联的执行方法以一次执行它们.
Actions 接口官方文档
https://w3c.github.io/webdriver/#dfn-actions

Action构造器

在从遗留JSON Wire协议迁移到 新的W3C WebDriver协议的过程中, 低级的操作构建块变得特别详细. 它非常强大, 但每个输入设备都有多种使用方法, 如果您需要管理多个设备, 则负责确保他们之间的同步正确.
值得庆幸的是, 不需要学习如何直接使用低级命令, 因为要执行的几乎所有操作, 都已提供了相应的简便方法, 这些方法可以组合较低级别的命令. 请分别参阅下面相应的键盘, 鼠标, 笔 和滚轮 小节.

暂停

指针移动和滚轮滚动 允许用户设置操作的持续时间, 有时只需要在操作之间等待一下, 即可正常工作.

    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver)\
        .move_to_element(clickable)\
        .pause(1)\
        .click_and_hold()\
        .pause(1)\
        .send_keys("abc")\
        .perform()

释放所有Actions

需要注意的重要一点是, 驱动程序会记住整个会话中所有输入项的状态. 即使创建actions类的新实例, 按下的键和指针的位置 也将处于以前执行的操作离开它们的任何状态.
有一种特殊的方法来释放所有当前按下的键和指针按钮. 此方法在每种语言中的实现方式不同, 因为它不会使用perform方法执行.

    ActionBuilder(driver).clear_actions()

四、Keyboard actions(键盘事件)

用于与网页交互的任何关键输入设备的表示。

只有两个操作可以用键盘完成:按下一个键和释放一个按下的键。除了支持ASCII字符之外,每个键盘键都有一个表示,可以按下或释放指定的序列。

Keys(键)

除了由常规unicode表示的键之外,还将unicode值分配给其他键盘键,以便与Selenium一起使用。每种语言都有自己的方法来引用这些键;
完整的列表链接:
https://www.w3.org/TR/webdriver/#keyboard-actions

from selenium.webdriver.common.keys import Keys

Key down (按下键位)

    ActionChains(driver)\
        .key_down(Keys.SHIFT)\
        .send_keys("abc")\
        .perform()

Key up (松开键位)

    ActionChains(driver)\
        .key_down(Keys.SHIFT)\
        .send_keys("a")\
        .key_up(Keys.SHIFT)\
        .send_keys("b")\
        .perform()

Send keys (发送按键信息)

这是Actions API中的一个方便的方法,它将keyDown和keyUp命令组合在一个操作中。执行此命令与使用元素方法略有不同,但主要用于需要在其他操作中间输入多个字符的情况。

Active Element (活性元素)

活性元素,也就是当前所在的元素,比如例子中的输入框

    ActionChains(driver)\
        .send_keys("abc")\
        .perform()

Designated Element (指定的元素)

    text_input = driver.find_element(By.ID, "textInput")
    ActionChains(driver)\
        .send_keys_to_element(text_input, "abc")\
        .perform()

Copy and Paste (复制和粘贴)

下面是一个使用上述所有方法来执行复制/粘贴操作的示例。注意,此操作使用的键将根据是否是Mac OS而有所不同。这段代码将以以下文本结束:SeleniumSelenium!

    cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL

    ActionChains(driver)\
        .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 actions(鼠标事件)

用于与网页交互的任何指针设备的表示形式。

只有3个动作可以用鼠标完成:按下一个按钮,释放一个被按下的按钮,移动鼠标。Selenium提供了最常见的方式组合这些操作的方便方法。

Click and hold (点击并按住不放)

此方法结合了将鼠标移动到元素中心与按下鼠标左键。这对于聚焦特定元素很有用

    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver)\
        .click_and_hold(clickable)\
        .perform()

Click and release (点击然后松开)

此方法将移动到元素中心与按下和释放鼠标左键结合在一起。这也被称为“点击”

    clickable = driver.find_element(By.ID, "click")
    ActionChains(driver)\
        .click(clickable)\
        .perform()

Alternate Button Clicks (交替点击按钮)

一个鼠标共有5个定义按钮:

  • 0 — Left Button (the default) 左键(默认)
  • 1 — Middle Button (currently unsupported) 中键(目前不支持)
  • 2 — Right Button 右键
  • 3 — X1 (Back) Button (后退)按钮
  • 4 — X2 (Forward) Button (前进)按钮

Context Click (单击右键)

这种方法结合了移动到元素中心与按下并释放鼠标右键(按钮2)

    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver)\
        .context_click(clickable)\
        .perform()

Back Click (点击后退)

按下并释放鼠标按钮3

    action = ActionBuilder(driver)
    action.pointer_action.pointer_down(MouseButton.BACK)
    action.pointer_action.pointer_up(MouseButton.BACK)
    action.perform()

普通鼠标没有前进和后退按钮,代码会报错,

AttributeError: type object 'MouseButton' has no attribute 'BACK'

游戏鼠标有,左侧还有2个按键的那种

Forward Click (点击前进)

按下和释放鼠标按钮4

    action = ActionBuilder(driver)
    action.pointer_action.pointer_down(MouseButton.FORWARD)
    action.pointer_action.pointer_up(MouseButton.FORWARD)
    action.perform()

Double click (双击)

此方法将移动到元素中心与两次按下并释放鼠标左键结合在一起

    clickable = driver.find_element(By.ID, "clickable")
    ActionChains(driver)\
        .double_click(clickable)\
        .perform()

Move to element (移动到元素)

此方法将鼠标移动到元素的视图内中心点。这也被称为“悬停”。注意元素必须在视窗中,否则命令会出错。

    hoverable = driver.find_element(By.ID, "hover")
    ActionChains(driver)\
        .move_to_element(hoverable)\
        .perform()

Move by offset (按偏移量移动)

这些方法首先将鼠标移动到指定的原点,然后移动提供的偏移量中的像素数。请注意,鼠标的位置必须在视口中,否则命令将出错。

Offset from Element (Top Left Origin) 从元素偏移(左上原点)

此方法将鼠标移动到元素的视图中心点,然后尝试移动到元素的左上角,然后移动提供的偏移量。
这将在 Selenium 4.3 中作为一个选项被删除,并且仅支持从元素中心的偏移。从 Selenium 4.2 开始,这是 Ruby、.NET 和 Python 的默认行为,以便向后兼容之前的 Selenium 版本。当元素不完全位于视窗内时,此方法无法正常工作。

    mouse_tracker = driver.find_element(By.ID, "mouse-tracker")
    ActionChains(driver)\
        .move_to_element_with_offset(mouse_tracker, 8, 0)\
        .perform()

Offset from Element (Center Origin) 从元素偏移(中心原点)

此方法移动到元素的视图中心点,然后将鼠标移动到提供的偏移量
这是自 Selenium 4.0 起的 Java 中的默认行为,自 Selenium 4.3 起将成为其余语言的默认行为。

**在 Selenium 4.3 中推出**

JAVA 版本

        WebElement tracker = driver.findElement(By.id("mouse-tracker"));
        new Actions(driver)
                .moveToElement(tracker, 8, 0)
                .perform();

Offset from Viewport 从视窗偏移

此方法将鼠标从当前视口的左上角移动提供的偏移量。

    action = ActionBuilder(driver)
    action.pointer_action.move_to_location(8, 0)
    action.perform()

Offset from Current Pointer Location 从当前指针位置偏移

此方法将鼠标从其当前位置移动用户提供的偏移量。如果鼠标之前没有移动过,该位置将位于视窗的左上角。请注意,滚动页面时指针位置不会改变。
请注意,第一个参数 X 指定当为正时向右移动,而第二个参数 Y 指定当为正时向下移动。所以moveByOffset(30, -10)从当前鼠标位置向右移动 30 和向上 10。

    ActionChains(driver)\
        .move_by_offset( 13, 15)\
        .perform()

Drag and Drop on Element 在元素上拖放

该方法首先在源元素上单击并按住,移动到目标元素的位置,然后释放鼠标。

    draggable = driver.find_element(By.ID, "draggable")
    droppable = driver.find_element(By.ID, "droppable")
    ActionChains(driver)\
        .drag_and_drop(draggable, droppable)\
        .perform()

Drag and Drop by Offset 按偏移量拖放

此方法首先在源元素上执行单击并按住,移动到给定的偏移量,然后释放鼠标。

    draggable = driver.find_element(By.ID, "draggable")
    start = draggable.location
    finish = driver.find_element(By.ID, "droppable").location
    ActionChains(driver)\
        .drag_and_drop_by_offset(draggable, finish['x'] - start['x'], finish['y'] - start['y'])\
        .perform()

六、Pen actions(笔操作)

一种用于与网页交互的触控笔类型的指针输入的表示。
PS:这块内容,目前没找到合适的应用场景,稍作了解即可

Chromium Only
仅支持谷歌浏览器,上面这个链接网址展示的是官方测试用例结果集,其中
test_touch_pointer_properties 用例说明 Pen actions 只有谷歌可以成功

Pen 是一种指针输入类型,其行为与鼠标的大部分行为相同,但也可以具有触控笔独有的事件属性。此外,虽然鼠标有 5 个按钮,但笔有 3 个等效的按钮状态:
0 — Touch Contact(默认值;相当于左键单击)
2 — Barrel Button 桶形按钮(相当于右键单击)
5 — Eraser Button 橡皮擦按钮(驱动程序目前不支持)

Using a Pen 使用笔

Selenium v4.2
该代码要求Selenium 4.2以上版本

    
    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2)\
        .pointer_up()
    action.perform()

Adding Pointer Event Attributes 添加指针事件属性

Selenium v4.2
该代码要求Selenium 4.2以上版本

    pointer_area = driver.find_element(By.ID, "pointerArea")
    pen_input = PointerInput(POINTER_PEN, "default pen")
    action = ActionBuilder(driver, mouse=pen_input)
    action.pointer_action\
        .move_to(pointer_area)\
        .pointer_down()\
        .move_by(2, 2, tilt_x=-72, tilt_y=9, twist=86)\
        .pointer_up(0)
    action.perform()

七、滚轮

Scroll wheel actions 滚轮动作

用于与网页交互的滚轮输入设备的表示。
Selenium v4.2
Chromium Only
Selenium V4.2以上版本,仅支持谷歌浏览器

在页面上滚动有 5 种场景

Scroll to element 滚动到元素

这是最常见的情况。与传统的单击和发送键方法不同,动作类不会自动将目标元素滚动到视图中,因此如果元素不在视窗内,则需要使用此方法。
此方法将 Web 元素作为唯一参数。
无论元素是在当前视图屏幕的上方还是下方,视窗都会滚动,因此元素的底部位于屏幕的底部。

    iframe = driver.find_element(By.TAG_NAME, "iframe")
    ActionChains(driver)\
        .scroll_to_element(iframe)\
        .perform()

Scroll by given amount 按给定数值滚动

这是第二个最常见的滚动场景。传入一个 delta x 和一个 delta y 值来确定向右和向下滚动多少。负值分别代表左和上。

    footer = driver.find_element(By.TAG_NAME, "footer")
    delta_y = footer.rect['y']
    ActionChains(driver)\
        .scroll_by_amount(0, delta_y)\
        .perform()

PS:这个rect,就是显示元素在浏览器页面中的坐标位置,具体值,可以在开发者工具里,查看元素右侧的Properties信息中的:offsetTop (高) 和 offsetWidth (宽)

Scroll from an element by a given amount 基于元素按给定数值滚动

这种情况实际上是上述两种方法的组合。
要执行此操作,请使用“Scroll From”方法,该方法需要 3 个参数。第一个表示起始点,我们将其指定为元素,后两个是 delta x 和 delta y 值。
如果元素超出视窗,它将滚动到屏幕底部,然后页面将滚动提供的 delta x 和 delta y 值。

    iframe = driver.find_element(By.TAG_NAME, "iframe")
    scroll_origin = ScrollOrigin.from_element(iframe)
    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()

Scroll from an element with an offset 基于元素按偏移量滚动

当您只需要滚动屏幕的一部分并且它在视窗之外时使用此方案。或者在视窗内并且必须滚动的屏幕部分是距特定元素的已知偏移量。
这里再次使用了“Scroll From”方法,除了指定元素外,还指定了一个偏移量来表示滚动的原点。偏移量是从提供的元素的中心计算的。
如果元素在视窗之外,首先会滚动到屏幕底部,然后通过将偏移量添加到元素中心的坐标来确定滚动的原点,最后页面将按提供的 delta x 和 delta y 值滚动。
请注意,如果距元素中心的偏移量落在视窗之外,则会导致异常。

    footer = driver.find_element(By.TAG_NAME, "footer")
    scroll_origin = ScrollOrigin.from_element(footer, 0, -50)
    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()

Scroll from a offset of origin (element) by given amount

基于原点(或元素)的偏移量按给点数值滚动
当只需要滚动屏幕的一部分并且它已经在视窗内时,使用最后一个场景。
这再次使用“Scroll From”方法,但指定的是视窗而不是元素。从当前视窗的左上角指定偏移量。确定原点后,页面将按提供的 delta x 和 delta y 值滚动。
请注意,如果从视窗左上角的偏移量落在屏幕之外,则会导致异常。

    ActionChains(driver)\
        .scroll_from_origin(scroll_origin, 0, 200)\
        .perform()

posted on 2022-10-17 22:25  测试老宅男扶摇  阅读(1549)  评论(0编辑  收藏  举报