Python侧开28期-偕行-学习笔记-高级控件交互ActionChains类

演练环境:https://vip.ceshiren.com/#/ui_study/action_chains

一、使用场景

使用场景 对应事件
复制粘贴 键盘事件
拖动元素到某个位置 鼠标事件
鼠标悬停 鼠标事件
滚动到某个元素 滚动事件
使用触控笔点击 触控笔事件(了解即可)

二、ActionChains类

Selenium的ActionChains类是用于执行一系列的鼠标和键盘操作。它提供了模拟用户行为的方法,例如拖拽、悬停、点击、按下和释放等。

1、构造方法

def __init__(self, driver: WebDriver, duration: int = 250, devices: list[AnyDevice] | None = None) -> None:
    """Creates a new ActionChains.

    :Args:
     - driver: The WebDriver instance which performs user actions.
     - duration: override the default 250 msecs of DEFAULT_MOVE_DURATION in PointerInput
    """
    self._driver = driver
    mouse = None
    keyboard = None
    wheel = None
    if devices is not None and isinstance(devices, list):
        for device in devices:
            if isinstance(device, PointerInput):
                mouse = device
            if isinstance(device, KeyInput):
                keyboard = device
            if isinstance(device, WheelInput):
                wheel = device
    self.w3c_actions = ActionBuilder(driver, mouse=mouse, keyboard=keyboard, wheel=wheel, duration=duration)
  • 说明:只有driver参数是必传的,创建一个动作对象;

2、使用步骤

  • 1、实例化ActionChains得到动作对象;
  • 2、动作对象调用方法实现键盘和鼠标事件;
  • 3、调用perform()方法执行动作;

3、动作方法

(1)鼠标点击

  • click:点击元素-左键单击;

  • click_and_hold:鼠标左键按住某个元素,长按;

  • release:在元素上释放按住的鼠标按钮。

  • context_click:右键单击;

  • double_click:双击;

(2)鼠标拖拽

  • drag_and_drop:按住源元素上的鼠标左键,然后移动到目标元素并松开鼠标按钮—拖动某个元素到某个元素;

  • drag_and_drop_by_offset:按住源元素上的鼠标左键,然后移动到目标偏移量并松开鼠标按钮—拖动某个元素到某个位置;

(3)鼠标移动-悬停

  • move_by_offset:移动鼠标到指定位置。

  • move_to_element:异动鼠标到指定元素。

  • move_to_element_with_offset:将鼠标移动到指定元素的偏移量位置,偏移量相对于元素的视图中心点。

(4)页面滚动

  • scroll_to_element:滚动到某个元素,意思是让元素可见;

  • scroll_by_amount:滚动到某个坐标,坐标原点在左上角;

  • scroll_from_origin:根据提供的滚动量和滚动基准进行滚动。滚动基准可以是元素的中心或视口的左上角加上任何偏移量。如果基准是元素,并且元素不在视口中,则首先将元素底部滚动到视口底部。

(5)模拟键盘

  • key_down(key, element=None):用于模拟按下键盘上的键并保持按下状态。该方法可以在进行一些复杂的键盘操作时使用。

    • key: 要按下的键值,可以是键盘上的任何一个键,如keys.SHIFTkeys.ENTER等。详细的键值可以参考Selenium的Keys类。
    • 该方法常用于需要模拟快捷键、组合键等键盘操作的场景。需要注意的是,key_down方法只是模拟按下键盘上的键,并不会自动释放,如果需要释放按键的状态,可以使用key_up方法或release方法。
    • key_down只是按下,其并不能实现esc、tab、enter、↑这些按键输入,这些输入需要使用send_keys
  • key_up:释放key_down方法模拟按下键盘上的键;

  • send_keys:给当前聚焦的元素发送键盘按键输入;

    • 该方法常用于模拟用户在输入框、文本域等地方输入文本、快捷键等操作。可以使用键盘上的字符、特殊键或组合键等作为输入。

    • 需要注意的是,send_keys方法会将文本发送到当前激活或焦点所在的元素上,如果需要在特定的元素上进行键盘输入,可以使用click方法或move_to_element方法先将焦点切换到对应元素。

  • send_keys_to_element:给指定元素发送键盘输入;

(6)其他方法

  • reset_actions:清除已存储在本地和远程端的操作;

  • pause:在指定的持续时间内暂停所有输入(以秒为单位)。

三、相关场景和案例

1、模拟键盘按键

  • 需求:在页面输入框输入大写字母,并控制键盘按键实现输入框内容响应
  • 地址:https://vip.ceshiren.com/#/ui_study/keypress

代码实现:

"""
模拟键盘按键
"""
import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.maximize_window()
driver.get("https://vip.ceshiren.com/#/ui_study/keypress")
driver.implicitly_wait(5)

# 创建操作对象-
action = ActionChains(driver)

# 定位元素-按回车enter触发事件
enterEl = driver.find_element(By.XPATH,'//*[@id="press_enter"]/div/input')
# 按下shift键输入内容
action.key_down(Keys.SHIFT,enterEl).send_keys("enter")
#模拟键盘enter键
action.send_keys(Keys.ENTER)
# 执行动作
action.perform()
time.sleep(2)

# 定位元素-按删除delete触发事件
deleteEl = driver.find_element(By.XPATH,'//*[@id="press_delete"]/div/input')
# 链式调用-按下shift-输入
# 因为上面已经把shift按下了,所以这里不需要再按shift
# action.key_down(Keys.SHIFT,deleteEl).send_keys("delete")
deleteEl.send_keys("delete")
# 按下delete
action.send_keys(Keys.DELETE).perform()
time.sleep(2)

# 定位元素-按退出esc触发事件
escEl = driver.find_element(By.XPATH,'//*[@id="press_esc"]/div/input')
# 链式调用-按下shift-输入---很有意思,到这里的时候shift又没有被按下了,所以要重新按下shift,不信你换注释了的赋值试试
# escEl.send_keys("esccccc")
action.key_down(Keys.SHIFT,escEl).send_keys("esc")
# 按下esc
action.send_keys(Keys.ESCAPE).perform()
time.sleep(2)

# 定位元素-按空格tab触发事件
tabEl = driver.find_element(By.XPATH,'//*[@id="press_tab"]/div/input')
tabEl.send_keys("按空格tab触发事件")
# 模拟键盘delete键并执行
action.send_keys(Keys.TAB).perform()
time.sleep(2)

# 定位元素-按上up触发事件
upEl = driver.find_element(By.XPATH,'//*[@id="press_up"]/div/input')
upEl.send_keys("按上up触发事件")
# 模拟键盘delete键并执行
action.send_keys(Keys.UP).perform()
time.sleep(2)

# 定位元素-按左left触发事件
downEl = driver.find_element(By.XPATH,'//*[@id="press_left"]/div/input')
downEl.send_keys("按左left触发事件")
# 模拟键盘delete键并执行
action.send_keys(Keys.LEFT).perform()
time.sleep(5)

driver.quit()

2、鼠标移动、双击、右击

代码实现:

"""
鼠标:双击、右击、鼠标移动
"""
import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.maximize_window()
driver.get("https://vip.ceshiren.com/#/ui_study/mouseover")
driver.implicitly_wait(5)

# 创建操作对象-
action = ActionChains(driver)

# 鼠标移动到-鼠标移入
# 定位鼠标移入元素
mouseIn = driver.find_element(By.XPATH,'//*[@class="el-button el-button--primary"]/span[(text()="鼠标移入")]')
action.move_to_element(mouseIn).perform()
time.sleep(2)

# 鼠标移动到-点击两次响应
# 定位点击两次响应元素
doubleBtn = driver.find_element(By.XPATH,'//*[@class="el-button el-button--primary"]/span[(text()="点击两次响应")]')
# 鼠标移过去并双击
# 双击的时候,如果鼠标在元素位置可以直接双击,不用传元素对象过去
# 如果鼠标不在元素位置,就需要传元素对象过去
action.move_to_element(doubleBtn).double_click().perform()
time.sleep(2)

# 鼠标右击
action.context_click().perform()
time.sleep(2)

driver.quit()

3、鼠标拖拽元素-拖拽图片验证码

地址:https://vip.ceshiren.com/#/ui_study/action_chains
image

代码实现:

"""
鼠标拖拽
"""
import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.maximize_window()
driver.get("https://vip.ceshiren.com/#/ui_study/action_chains")
driver.implicitly_wait(5)

# 创建操作对象-
action = ActionChains(driver)

# 定位源元素
originEl = driver.find_element(By.XPATH,'//*[@class="item1"]')
# 定位目标元素
targetEl = driver.find_element(By.XPATH,'//*[@class="item3"]')
# 拖拽
action.drag_and_drop(originEl,targetEl).perform()
time.sleep(2)
driver.quit()

4、鼠标移动并悬浮–下拉框处理

地址:https://vip.ceshiren.com/#/ui_study/action_chains2

代码实现:

"""
鼠标移动悬浮-下拉框处理
"""
import time
from selenium import webdriver
from selenium.webdriver import ActionChains, Keys
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.maximize_window()
driver.get("https://vip.ceshiren.com/#/ui_study/action_chains2")
driver.implicitly_wait(5)

# 创建操作对象-
action = ActionChains(driver)

# 定位下拉框元素
selectEl = driver.find_element(By.XPATH,'//*[@class="title"]')
# 鼠标移动过去
action.move_to_element(selectEl).perform()
time.sleep(2)

# 定位下拉框内的元素
jybEl = driver.find_element(By.XPATH,'//*[(text()=" 就业班 ")]')
# 移动上去
action.move_to_element(jybEl).perform()
time.sleep(2)

# 定位下拉框内的元素
jybEl = driver.find_element(By.XPATH,'//*[(text()=" 定向班 ")]')
# 移动上去
action.move_to_element(jybEl).perform()
time.sleep(2)

# 定位下拉框内的元素
jybEl = driver.find_element(By.XPATH,'//*[(text()=" 测开班 ")]')
# 移动上去
action.move_to_element(jybEl).perform()
time.sleep(2)

# 定位下拉框内的元素
jybEl = driver.find_element(By.XPATH,'//*[(text()=" 管理班 ")]')
# 移动上去
action.move_to_element(jybEl).perform()
time.sleep(2)

# 定位下拉框内的元素
jybEl = driver.find_element(By.XPATH,'//*[(text()=" 性能班 ")]')
# 移动上去
action.move_to_element(jybEl).perform()
# 模拟鼠标点击最后一个--鼠标就在当前位置,click不用传元素对象
action.click().perform()
time.sleep(2)

# 再点击单选框
jyBox = driver.find_element(By.XPATH,"//*[@name='jy']")
action.move_to_element(jyBox).click().perform()
time.sleep(5)

driver.quit()

5、页面滚动–炸了–TODO

  • 注意:页面滚动的方法需要在selenium4.2及以上版本才会生效;
# 升级selenium
pip install -U selenium==4.15.1
"""
页面滚动
"""
import time

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Edge()
driver.maximize_window()
driver.get("https://ceshiren.com")
driver.implicitly_wait(15)

# 创建操作对象-
action = ActionChains(driver)

#试一下能不能定位到
a = driver.find_element(By.XPATH,'//*[(text()="使用代理服务器录制请求")]')
action.scroll_to_element(a).perform()
time.sleep(5)