• 【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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    释放(Clear)

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

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

    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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2. 键盘(Keyboard)

    2.1 Key

    模拟键盘上的键操作。

    from selenium.webdriver import Keys
    
    """
    The Keys implementation.
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    2.3 抬起键
    # 按下 shift 输入大写 A
    # 松开 shift 输入小写 b
    ActionChains(driver)\
        .key_down(Keys.SHIFT)\
        .send_keys("a")\
        .key_up(Keys.SHIFT)\
        .send_keys("b")\
        .perform()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    2.4 输入字符
    # 基于当前元素
    ActionChains(driver)\
     .send_keys("abc")\
     .perform()
    
    • 1
    • 2
    • 3
    • 4
    2.5 向指定元素输入字符
    text_input = driver.find_element(By.ID, "textInput")
    ActionChains(driver)\
      .send_keys_to_element(text_input, "abc")\
      .perform()
    
    • 1
    • 2
    • 3
    • 4
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4. 滚轮(Wheel)

    4.1 滚动到元素

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

    iframe = driver.find_element(By.TAG_NAME, "iframe")
    ActionChains(driver)\
      .scroll_to_element(iframe)\
      .perform()
    
    • 1
    • 2
    • 3
    • 4
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    4.5 基于原点的偏移量向指定偏移量滚动
    scroll_origin = ScrollOrigin.from_viewport(10, 10)
    ActionChains(driver)\
      .scroll_from_origin(scroll_origin, 0, 200)\
      .perform()
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    Android Framework 核心,为何初级开发需要重点学习Framework?
    WebSocke(简略笔记)
    ISO食品安全管理体系认证条件
    SpringCloud 微服务全栈体系(十)
    手撕520页PDF高级文档,成功“挤掉”7年开发架构师,牛逼
    一文解码语言模型:语言模型的原理、实战与评估
    Lego-Laom算法深度解析
    电视连续剧 ffmpeg 批量去掉片头片尾
    springcloudalibaba架构(25):RocketMQ事务消息
    Elasticsearch概述
  • 原文地址:https://blog.csdn.net/lan_yangbi/article/details/127968206