Python Selenium.WebDriver清除输入框再输入『详解』

Python Selenium.WebDriver 清除输入框再输入『详解』


一、如何清除输入框中的默认内容

首先,要明确一点的是,Selenium是模拟人们去操作浏览器,它能操作的事大部分都是我们人们能够自己手动实现的事情。

知道这一点后,我们再想想平时浏览网页时遇到存在默认文本内容的输入框时,我们会怎么将其清除掉再输入呢?

  • 慢慢敲退格键?虽然麻烦但也是一个方法
  • 拖动并点击鼠标,将默认内容选中后再按退格键将其删除;
  • 双击默认文本内容,在选中后的情况下输入我们想要的内容将其替换掉;
  • 与双击有着同样原理的是使用ctrl + a 全选快捷键将其全部选中,这个会比双击能够更可靠地选中默认文本内容,再输入我们想要的内容将其替换掉;
  • 不断刷新网页,祈祷输入框中的默认文本内容不再出现,哈哈别逗了,这不太可能

二、WebDriverWait 的功能键实现

在上诉的实现方法,都离不开对键盘的操作,全选、回车这些都是需要在代码中去实现,那么如何使用Selenium实现这些操作呢,这就需要用到 Selenium WebDriver 的功能键API(接口)

使用下列导入语句将其导入

from selenium.webdriver.common.keys import Keys

其实源码实现原理很简单,我们来看看源码,只要明白了规则甚至连该模块都不用导入就能实现功能键的输入

class Keys(object):
    """
    Set of special keys codes.
    """

    NULL = '\ue000'
    CANCEL = '\ue001'  # ^break
    HELP = '\ue002'
    BACKSPACE = '\ue003'
    BACK_SPACE = BACKSPACE
    TAB = '\ue004'
    CLEAR = '\ue005'
    RETURN = '\ue006'
    ENTER = '\ue007'
    SHIFT = '\ue008'
    LEFT_SHIFT = SHIFT
    CONTROL = '\ue009'
    LEFT_CONTROL = CONTROL
    ALT = '\ue00a'
    LEFT_ALT = ALT
    PAUSE = '\ue00b'
    ESCAPE = '\ue00c'
    SPACE = '\ue00d'
    PAGE_UP = '\ue00e'
    PAGE_DOWN = '\ue00f'
    END = '\ue010'
    HOME = '\ue011'
    LEFT = '\ue012'
    ARROW_LEFT = LEFT
    UP = '\ue013'
    ARROW_UP = UP
    RIGHT = '\ue014'
    ARROW_RIGHT = RIGHT
    DOWN = '\ue015'
    ARROW_DOWN = DOWN
    INSERT = '\ue016'
    DELETE = '\ue017'
    SEMICOLON = '\ue018'
    EQUALS = '\ue019'

    NUMPAD0 = '\ue01a'  # number pad keys
    NUMPAD1 = '\ue01b'
    NUMPAD2 = '\ue01c'
    NUMPAD3 = '\ue01d'
    NUMPAD4 = '\ue01e'
    NUMPAD5 = '\ue01f'
    NUMPAD6 = '\ue020'
    NUMPAD7 = '\ue021'
    NUMPAD8 = '\ue022'
    NUMPAD9 = '\ue023'
    MULTIPLY = '\ue024'
    ADD = '\ue025'
    SEPARATOR = '\ue026'
    SUBTRACT = '\ue027'
    DECIMAL = '\ue028'
    DIVIDE = '\ue029'

    F1 = '\ue031'  # function  keys
    F2 = '\ue032'
    F3 = '\ue033'
    F4 = '\ue034'
    F5 = '\ue035'
    F6 = '\ue036'
    F7 = '\ue037'
    F8 = '\ue038'
    F9 = '\ue039'
    F10 = '\ue03a'
    F11 = '\ue03b'
    F12 = '\ue03c'

    META = '\ue03d'
    COMMAND = '\ue03d'

将源码中的常用的功能键总结整理成表格

键位中文释义Unicode码
BACKSPACE / BACK_SPACE退格\ue003
DELETE删除\ue017
HOME开头\ue011
END末尾\ue010
ENTER回车\ue007
CONTROL(CTRL)控制(CTRL)\ue009
ALTALT\ue00a
SPACE空格\ue00d

三、退格大法好😍

万能的退格,输入框里有都是内容那就退格多少次,这是一个比较容易想出的方法,相信也有不少人也是一直在使用这个方法
缺点也很明显,比较繁琐,一个两个输入框还好,但如果输入框中的内容有点多,或则输入框的数量有点多,这个方法就不太行了

需要用到退格功能键,我们可以利用Keys包下的 Keys.BACKSPACE 实现或则自行写入Unicode编码 \ue003 即可

思路:
思路很简单,使用get_attribute方法获取输入框中的内容值,计算其长度并与偏差相加,循环需要摁下的次数并使用send_keys发送空格

def backspace_clean(element, deviation=3):
    """
    退格原理清除输入框中的内容
    :param element: 元素 
    :param deviation: 退格数偏差,默认会多输入3个以确保可靠度
    """
    quantity = len(element.get_attribute("value")) + deviation
    for _ in range(quantity):
        element.send_keys(Keys.BACKSPACE)

将其封装成 清除并输入内容 函数

def backspace_clean(element, deviation=3):
    """
    退格原理清除输入框中的内容
    :param element: 需要操作的元素
    :param deviation: 退格数偏差,默认会多输入3个以确保可靠度
    """
    quantity = len(element.get_attribute("value")) + deviation
    for _ in range(quantity):
        element.send_keys(Keys.BACKSPACE)


def clean_with_send(element, text: str, **kwargs):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param text: 输入的内容
    """
    backspace_clean(element, **kwargs)
    element.send_keys(text)

四、不靠谱的拖动鼠标🤐

如果输入框中的内容较多进行了隐藏或则分了几行,那么可靠度是挺低的。除此之外,还得考虑鼠标的拖动范围,从哪里开始定位,这一系列的动作链操作,编写起来也是比较麻烦的

在开始讲解之前,需要注意三个点:

  • 一是鼠标点击操作是在元素的正中间(经过我的测试得出),这就需要先将鼠标移动到元素的开头的进行步骤预处理才行
  • 需要事先将浏览器最大化操作browser.maximize_window(),如果输入框超出窗口化所显示的范围时候会抛出异常
  • 导入Selenium的动作链库再进行代码的编写,from selenium.webdriver import ActionChains

还需要了解动作链的一些方法,这些方法将在下面的代码中所使用:

方法参数描述
.move_by_offset(xoffset, yoffset)x 偏移量(横轴),y 偏移量(纵轴)鼠标从当前位置移动到某个坐标(x, y)(默认在浏览器左上角,类似网页布局中的固定定位)
.move_to_element(to_element)element(目标元素)鼠标移动到目标元素中间
.move_to_element_with_offset(to_element, xoffset, yoffset)element(目标元素),x 偏移量(横轴),y 偏移量(纵轴)鼠标移动到相对于目标元素的坐标(x, y)「以元素左上角作为参照物」
.click_and_hold(on_element=None)element(目标元素,可选)在目标元素下摁下鼠标左键并且不松开。如果没有传入目标元素,则在当前鼠标指针位置下操作
.click(on_element=None)element(目标元素,可选)左键点击目标元素。如果没有传入目标元素,则在当前鼠标指针位置下操作
.release(on_element=None)element(目标元素,可选)在目标元素处松开鼠标摁键。如果没有传入目标元素,则在当前鼠标指针位置下操作

值得注意的是,鼠标移动的位置是继承的,不会移动往后会自动归位到页面左上角。在每次写好 操作设置函数 后要记得加上动作链执行函数.perform(),在调用.perform时,讲连续执行之前所设置的操作设置函数,然后结束

思路:
先获取输入框的大小,确定需要拖动的范围。将鼠标指针移到相当目标输入框(横轴: 1,纵轴: 1)的位置,并摁下左键不松开,移动指针到输入框最右下角的位置并向输入框发送退格功能键,清空内容。最后释放鼠标。

def drag_clean(element, browser):
    """
    拖动鼠标原理清除输入框中的内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    """
    s_y, s_x = element.size.values()
    action = ActionChains(browser)
    action.move_to_element_with_offset(element, 1, 1).click_and_hold().perform()
    action.move_by_offset(s_x, s_y).send_keys(Keys.BACKSPACE).perform()
    action.release()    # 释放鼠标

将其封装成 清除并输入内容 函数

def drag_clean(element, browser):
    """
    拖动鼠标原理清除输入框中的内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    """
    s_y, s_x = element.size.values()
    action = ActionChains(browser)
    action.move_to_element_with_offset(element, 1, 1).click_and_hold().perform()
    action.move_by_offset(s_x, s_y).send_keys(Keys.BACKSPACE).perform()
    action.release()    # 释放鼠标


def clean_with_send(element, browser, text: str):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    :param text: 输入的内容
    """
    drag_clean(element, browser)
    element.send_keys(text)

五、双击后替换😲

双击后替换,这也是一个比较常用的解决方案,但还是存在有可能没选全的情况,因此可以考虑多次双击解决这个问题,代码编写也比较方便,对于简单的输入框还是值得去使用的

导入Selenium的动作链库再进行代码的编写,from selenium.webdriver import ActionChains

思路:
直接双击输入框,使其内容被选中后向输入框发送退格功能键,清空内容。将上述方法写在循环里,循环次数通过number_of_executions参数控制,默认值为1次,即执行一次双击清空内容操作。

def double_click_clean(element, browser, number_of_executions=1):
    """
    双击内容原理清除输入框中的内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    :param number_of_executions: 执行次数,多次执行能有效避免未选全情况
    """
    action = ActionChains(browser)
    for _ in range(number_of_executions):
        action.double_click(element).send_keys(Keys.BACKSPACE).perform()

将其封装成 清除并输入内容 函数

def double_click_clean(element, browser, number_of_executions=1):
    """
    双击内容原理清除输入框中的内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    :param number_of_executions: 执行次数,多次执行能有效避免未选全情况
    """
    action = ActionChains(browser)
    for _ in range(number_of_executions):
        action.double_click(element).send_keys(Keys.BACKSPACE).perform()


def clean_with_send(element, browser, text: str, **kwargs):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param browser: 浏览器对象
    :param text: 输入的内容
    """
    double_click_clean(element, browser, **kwargs)
    element.send_keys(text)

六、全选后替换「推荐」

众所周知全选的快捷键是Ctrl + A ,通过键盘输入全选快捷键,将输入框中的旧内容全部选中后直接输入替换,实现起来简单且又可靠,也不需要用到专门的动作链接口ActionChains

思路:
先对元素使用send_keys方法输入Ctrl + A 快捷键后,直接再使用send_keys方法输入我们想要的内容将其替换即可

def select_all_clean(element):
    """
    全选内容原理清除输入框中的内容
    :param element: 需要操作的元素
    """
    # 发送全选快捷键
    element.send_keys(Keys.CONTROL, "a")
    element.send_keys(Keys.BACKSPACE)


def clean_with_send(element, text: str):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param text: 输入的内容
    """
    select_all_clean(element)
    element.send_keys(text)

可以将其合并组合成一个函数,只需要短短两行即可实现

def clean_with_send(element, text: str):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param text: 输入的内容
    """
    # 发送全选快捷键
    element.send_keys(Keys.CONTROL, "a")
    element.send_keys(text)

七、自带清空元素的内容方法「推荐」

看完上面各种模拟行为清空输入框内容的方法,你一定会想难道Selenium就没有自带清空的方法吗,答案是肯定的,用起来也比较简单,webelement.clear()方法多用于输入框

想要注意的是,对于某些网页,此方法可以会失效,所以还是得用上面所讲的方法去实现

思路:
没什么特别的,就是清空再输入

def clean_with_send(element, text: str):
    """
    清空输入框并且输入内容
    :param element: 需要操作的元素
    :param text: 输入的内容
    """
    element.clear()
    element.send_keys(text)

八、总结

其实利用 Selenium.WebDriverWait 对页面进行模拟操作时,无非也是在模仿我们平时上网时的行为罢了,想要对页面进行模拟操作且没思路时,不妨想想要是自己会怎么去操作网页


参考资料💟

  • 书籍:
    • 异步图书 《Selenium 自动化测试完全指南 基于Python》
      这是一本2021年5月新出的书,各方面写的很全,对于学习爬虫或则自动化测试的同学一定不要错过
  • 官方手册

由衷感谢💖


相关博客😏