【selenium】动作链接 ActionChains

用于向 Web 浏览器提供虚拟化输入操作的低级接口。

  • 键盘输入
  • 鼠标输入
  • 笔或触摸设备的指针输入
  • 滚轮输入(v4.2+)

实现动作交互依赖ActionChains库,是对更底层动作类ActionBuilder的封装。

当调用ActionChains操作方法时,操作事件被存储在ActionChains对象的队列中。在调用perform()时,将按照操作事件的顺序一个接一个触发执行。

暂停(Pause)

鼠标操作链中设置等待时间。

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

释放(Clear)

当已经生成了动作链但是没有进行perform操作,即使后面创建了新的动作类实例,鼠标依然处于先前的状态,所以需要释放已经生成但没有执行的动作链。

from selenium.webdriver.common.actions.action_builder import ActionBuilder
# 释放所有 actions
ActionBuilder(driver).clear_actions()

1. 鼠标(Mouse)

1.1 点击
# 鼠标左键并按住不放
ActionChains(driver)\
 .click_and_hold(clickable)\
 .perform()

# 鼠标左键
clickable = driver.find_element(By.ID, "click")
ActionChains(driver)\
 .click(clickable)\
 .perform()

# 鼠标右键
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
 .context_click(clickable)\
 .perform()

# 鼠标左键双击
clickable = driver.find_element(By.ID, "clickable")
ActionChains(driver)\
 .double_click(clickable)\
 .perform()

"""
鼠标键
部分鼠标无按键不支持,经测试 Mac 与罗技无线鼠标均可
"""
# 鼠标后退键(v4.2+)
action = ActionBuilder(driver)
action.pointer_action.pointer_down(MouseButton.BACK)
action.pointer_action.pointer_up(MouseButton.BACK)
action.perform()

# 鼠标前进键(v4.2+)
action = ActionBuilder(driver)
action.pointer_action.pointer_down(MouseButton.FORWARD)
action.pointer_action.pointer_up(MouseButton.FORWARD)
action.perform()
1.2 移动
# 将鼠标移动到元素的中心点
hoverable = driver.find_element(By.ID, "hover")
ActionChains(driver)\
 .move_to_element(hoverable)\
 .perform()

""" 
按偏移量移动
offset(13, 15)    向右移动 13,向下移动 15
offset(-15, -20) 向左移动 15,向上移动 20
"""
# 从元素偏移(左上原点)
mouse_tracker = driver.find_element(By.ID, "mouse-tracker")
ActionChains(driver)\
 .move_to_element_with_offset(mouse_tracker, 8, 0)\
 .perform()

# 从元素偏移(中心原点)
action = ActionBuilder(driver)
action.pointer_action.move_to_location(8, 0)
action.perform()

# 基于当前指针位置的偏移量
ActionChains(driver)\
 .move_by_offset( 13, 15)\
 .perform()
1.3 拖放
# 点击并按住 A 元素,移动到 B 元素,释放鼠标
draggable = driver.find_element(By.ID, "draggable")
droppable = driver.find_element(By.ID, "droppable")
ActionChains(driver)\
 .drag_and_drop(draggable, droppable)\
 .perform()

# 点击并按住 A 元素,移动到给定的偏移量,释放鼠标
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()

2. 键盘(Keyboard)

2.1 Key

模拟键盘上的键操作。

from selenium.webdriver import Keys

"""
The Keys implementation.
"""
2.2 按下键
from selenium.webdriver import Keys, ActionChains
from selenium.webdriver.common.by import By

# 按下 shift 键不放,输入字母,得到大写字母
ActionChains(driver)\
    .key_down(Keys.SHIFT)\
    .send_keys("abc")\
    .perform()
2.3 抬起键
# 按下 shift 输入大写 A
# 松开 shift 输入小写 b
ActionChains(driver)\
    .key_down(Keys.SHIFT)\
    .send_keys("a")\
    .key_up(Keys.SHIFT)\
    .send_keys("b")\
    .perform()
2.4 输入字符
# 基于当前元素
ActionChains(driver)\
 .send_keys("abc")\
 .perform()
2.5 向指定元素输入字符
text_input = driver.find_element(By.ID, "textInput")
ActionChains(driver)\
  .send_keys_to_element(text_input, "abc")\
  .perform()
2.6 复制粘贴
cmd_ctrl = Keys.COMMAND if sys.platform == 'darwin' else Keys.CONTROL

"""
官方文档通过 firefox_driver 执行
"""
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()

"""
chrome 通过下面的方法实现
"""
ele = driver.find_element(value="textInput")
ele.send_keys('Selenium!')
ele.send_keys(cmd_ctrl, 'a')
time.sleep(2)
# 键盘的复制操作
ele.send_keys(cmd_ctrl, 'c')
time.sleep(2)
# 键盘的剪切操作
ele.send_keys(cmd_ctrl, 'x')
time.sleep(2)
# 键盘的粘贴操作
ele.send_keys(cmd_ctrl, 'v')
time.sleep(2)
# 键盘的删除操作
ele.send_keys(cmd_ctrl, 'a')
ele.send_keys(Keys.BACKSPACE)

3. 笔(Pen)

仅支持 chromium;v4.2+

笔是一种指针输入,具有与鼠标基本相同的行为,但也可以具有手写笔独有的事件属性。此外,鼠标有5个按钮,而笔有3个等效的按钮状态:

  • 0:触摸(默认,相当于左键单击)
  • 2:筒状按钮(相当于右键单击)
  • 5:橡皮擦按钮(目前不支持)
driver.get('https://www.selenium.dev/selenium/web/pointerActionsPage.html')
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()

# 添加指针事件属性
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()

4. 滚轮(Wheel)

4.1 滚动到元素

一直滚动,直到指定元素出现在屏幕中。

iframe = driver.find_element(By.TAG_NAME, "iframe")
ActionChains(driver)\
  .scroll_to_element(iframe)\
  .perform()
4.2 按指定偏移量滚动
# 传入一个 delta x 和 delta y 值,表示向右和向下滚动的量。负值分别代表左和上。

footer = driver.find_element(By.TAG_NAME, "footer")
# rect 具有元素位置和大小的字典,取元素的 y 值
# {'height': 23, 'width': 1169, 'x': 8, 'y': 5217.5}
delta_y = int(footer.rect['y'])
ActionChains(driver)\
  .scroll_by_amount(0, delta_y)\
  .perform()
4.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()
4.4 基于元素的偏移量向指定偏移量滚动
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()
4.5 基于原点的偏移量向指定偏移量滚动
scroll_origin = ScrollOrigin.from_viewport(10, 10)
ActionChains(driver)\
  .scroll_from_origin(scroll_origin, 0, 200)\
  .perform()

猜你喜欢

转载自blog.csdn.net/lan_yangbi/article/details/127968206