selenium 常见元素操作

852 阅读12分钟
  • 三大等待
  • 三大切换(iframe,window,alert)
  • 鼠标操作(ActionChains)
  • 键盘操作(Keys)
  • 下拉框(Select)
  • js操作(execute_script)
  • 页面操作
  • 文件上传

1.等待

1.1 强制等待:time.sleep()

必须等待固定时间后才可以继续运行

from selenium import webdriver
import time         

# 指定驱动器
driver = webdriver.Chrome()

# 访问网页
driver.get("http://www.baidu.com")
# 点击登录按钮
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()

# # 强制等待5秒,在进行下一步操作
time.sleep(10)
# 点击 用户名登录 按钮
driver.find_element_by_id("TANGRAM__PSP_10__footerULoginBtn").click()
# 强制等待5秒后关闭浏览器
time.sleep(10)
driver.quit()

1.2 隐性等待:implicitly_wait

隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步.注意这里有一个弊端,那就是程序会一直等待整个页面加载完成,也就是一般情况下你看到浏览器标签栏那个小圈不再转,才会执行下一步,但有时候页面想要的元素早就在加载完成了,但是因为个别js之类的东西特别慢,我仍得等到页面全部完成才能执行下一步,特点:

  • 全局设置一次(与显性等待不同)
  • 隐形等待元素不一定是可见的(与显性等待不同)
  • 智能等待的隐形等待:会话开始之后使用隐形等待,之后所有的找元素都会调用隐形等待,等待元素可见,等待命令执行
from selenium import webdriver

# 打开谷歌浏览器,建立会话。启动Chromedriver.exe  打开Chrome
driver = webdriver.Chrome()

# 智能等待的隐形等待:会话开始之后使用隐形等待,之后所有的找元素都会调用隐形等待,等待元素可见,等待命令执行
# implicitly_wait
driver.implicitly_wait(20)

# 访问百度首页
driver.get("http://www.baidu.com")
# 点击登录按钮
driver.find_element_by_xpath('//div[@id="u1"]//a[@name="tj_login"]').click()
# 点击 用户名登录 按钮
driver.find_element_by_id("TANGRAM__PSP_10__footerULoginBtn").click()
# 关闭浏览器
driver.quit()

1.3 显性等待

显性等待,WebDriverWait,配合该类的until()和until_not()方法,就能够根据判断条件而进行灵活地等待了.它主要的意思就是:程序每隔x秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException 与隐形等待的不同,隐形等待处理不了下面几种情况,显性等待可以:

  • 等待元素可见
  • 等待元素可用
  • 等待新窗口出现
  • 等待 url地址=xxx的时候
  • 等待 的上限是多少秒,每隔0.5秒去查看条件是否成立
  • 明确等到某个条件满足之后,再去执行下一步操作。
  • 程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到等待的元素可见
  • 超过设置的最长时间,然后抛出TimeoutException. --- .

1.3.1 WebDriverWait类:显性等待类

wait模块的WebDriverWait类是显性等待类,先看下它有哪些参数与方法:
_init_

driver: 传入WebDriver实例,即我们上例中的driver timeout: 超时时间,等待的最长时间(同时要考虑隐性等待时间) poll_frequency: 调用until或until_not中的方法的间隔时间,默认是0.5秒 ignored_exceptions: 忽略的异常,如果在调用until或until_not的过程中抛出这个元组中的异常,则不中断代码,继续等待,如果抛出的是这个元组外的异常,则中断代码,抛出异常。默认只有NoSuchElementException。

until

method: 在等待期间,每隔一段时间(__init__中的poll_frequency)调用这个传入的方法,直到返回值不是False message: 如果超时,抛出TimeoutException,将message传入异常
expected_conditions as EC 模块: 提供了一系列期望发生的条件。

until_not

与until相反,until是当某元素出现或什么条件成立则继续执行,
until_not是当某元素消失或什么条件不成立则继续执行,参数也相同,不再赘述。

**WebDriverWait(driver,等待时长,轮循周期).until(这个条件成立,才向下执行)/until_not(这个条件不成立,才向下执行) **

1.3.2 常用的等待判断

title_is/title_contains
验证title,验证传入的参数title是否等于或包含于driver.title

visibility_of_element_located/invisibility_of_element_located/visibility_of
三个条件验证元素是否可见,前两个传入参数是元组类型的locator,第三个传入WebElement[第一个和第三个其实质是一样的]

text_to_be_present_in_element/text_to_be_present_in_element_value
判断某段文本是否出现在某元素中,一个判断元素的text,一个判断元素的value

frame_to_be_available_and_switch_to_it
判断frame是否可切入,可传入locator元组或者直接传入定位方式:id、name、index或WebElement

alert_is_present
判断是否有alert出现

element_to_be_clickable
判断元素是否可点击,传入locator

element_to_be_selected/element_located_to_be_selected/element_selection_state_to_be/element_located_selection_state_to_be
判断元素是否被选中
第一个条件传入WebElement对象
第二个传入locator元组
第三个传入WebElement对象以及状态,相等返回True,否则返回False
第四个传入locator以及状态,相等返回True,否则返回False

staleness_of
判断一个元素是否仍在DOM中,传入WebElement对象,可以判断页面是否刷新了

new_window_is_opened(window_handles)
判断是否打开了新的页面(window_handles:为旧状态下的窗口句柄)

1.3.3 使用方法

使用之前,引入相关的库

from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

确定元素的定位表达式

web_ locator = 'XXXX'

调用webdriverWait类设置等待总时长、轮询周期。并调用期until、until_ not方法

WebDriverWait(webdriver对象名,等待总时长,轮询周期),until(判断条件)

使用expected_ conditions对 应的方法来生成判断条件

EC.类名((定位方式、定位表达式))
例: EC.presence_of_element_ located((By.CSS_ SELECTOR,web locator)))
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.XPATH, '//*[@id="su"]'))
    )
    text = driver.page_source
    print("text", text)
finally:
    driver.quit()

设置了隐性等待和显性等待,在其他操作中,隐性等待起决定性作用,在WebDriverWait..中显性等待起主要作用,但要注意的是:最长的等待时间取决于两者之间的大者,此例中为20,如果隐性等待时间>显性等待时间,则该句代码的最长等待时间等于隐性等待时间

2.切换

2.1 iframe切换

frame标签有frameset、frame、iframe三种,frameset跟其他普通标签没有区别,不会影响到正常的定位,而frame与iframe对selenium定位而言是一样的,selenium有一组方法对frame进行操作。

  • frameset不用切,frame需层层切!

2.1.1 切到指定frame中(switch_to.frame(reference))

reference:可以是下标/id/name/以及定位到的element

from selenium import webdriver
driver = webdriver.Edge()
driver.switch_to.frame(0)  # 1.用frame的index来定位,第一个是0
driver.switch_to.frame("frame1")  # 2.用id来定位
driver.switch_to.frame("myframe")  # 3.用name来定位
driver.switch_to.frame(driver.find_element_by_tag_name("iframe"))  # 4.用WebElement对象来定位
  • index从0开始,传入整型参数即判定为用index定位,传入str参数则判定为用id/name定位
  • WebElement对象,即用find_element系列方法所取得的对象,我们可以用tag_name、xpath等来定位frame对象

2.1.2 从frame中切回主文档(switch_to.default_content())

切到frame中之后,我们便不能继续操作主文档的元素,这时如果想操作主文档内容,则需切回主文档

2.1.3 嵌套frame的操作(switch_to.parent_frame())

  • 从frame1切到frame2
driver.switch_to.frame("frame1")
driver.switch_to.frame("frame2")
  • 从frame2再切回frame1[父frame]
driver.switch_to.parent_frame()
  • 从frame1切到frame3
driver.switch_to.frame("frame3")

2.2 窗口切换

在web操作,常常会点击某个链接会弹出一个新的窗口,要去操作新窗口中的元素,这时就需要主机切换到新窗口进行操作
窗口切换需要用到一个关键元素:句柄,每个窗口唯一的标识
WebDriver 提供了switchTo().window()方法可以实现在不同的窗口之间切换。

  • current_window_handle():获得当前窗口句柄
  • window_handles():返回的所有窗口的句柄到当前会话[最新的窗口句柄在列表中顺序最后]
  • switch_to_window():传入句柄的值,即可切换到对应的窗口
  • driver.title:获取当前标签名

2.3 alter切换(driver.switch_to.alert)

alter窗口:就是系统弹出的提示框[无法用selenium定位其中的元素]

  • alter = driver.switch_to.alert 返回一个弹窗对象
  • alter.text # 获取文本
  • alter.dismiss() # 取消
  • alter.accept() # 确定
  • alter.send_keys() # 输入框中输入内容[有输入框才能使用,否则报错]

3.鼠标操作

selenium通过ActionChains完成模拟鼠标操作

from selenium.webdriver.common.action_chains import ActionChains

3.1 ActionChains基本用法

两种调用方法:

  • 链式写法
menu = driver.find_element_by_css_selector(".nav")  # 定位元素
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") # 定位元素
ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform() # 鼠标操作
  • 分步写法
menu = driver.find_element_by_css_selector(".nav") # 定位元素
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1") # 定位元素
actions = ActionChains(driver) # 生成鼠标类
actions.move_to_element(menu) # 移动
actions.click(hidden_submenu) # 点击
actions.perform() # 提交命令

3.2 ActionChains方法列表

  • click(on_element=None) ——单击鼠标左键
  • click_and_hold(on_element=None) ——点击鼠标左键,不松开
  • context_click(on_element=None) ——点击鼠标右键
  • double_click(on_element=None) ——双击鼠标左键
  • drag_and_drop(source, target) ——拖拽到某个元素然后松开
  • drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开
  • key_down(value, element=None) ——按下某个键盘上的键
  • key_up(value, element=None) ——松开某个键
  • move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标
  • move_to_element(to_element) ——鼠标移动到某个元素
  • move_to_element_with_offset(to_element, xoffset, yoffset) ——移动到距某个元素(左上角坐标)多少距离的位置
  • perform() ——执行链中的所有动作
  • release(on_element=None) ——在某个元素位置松开鼠标左键
  • send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
  • send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素

3.3 ActionChains类行为控制

perform --- 执行所有准备好的Action
reset_actions --- 清空所有准备好的Action
pause --- 设置Action之间的动作时间间隔
** 当执行过perform后,需要再次执行鼠标动作时,需要重新创建ActionChains类,reset_actions清空Action无效 **

4.键盘操作

selenium通过Keys完成模拟鼠标操作

from selenium.webdriver.common.keys import Keys

4.1 Keys基本用法

from selenium import webdriver
import time

from selenium.webdriver.common.keys import Keys   # 键盘操作需要导入keys

driver = webdriver.Edge()

# 访问百度首页
driver.get("http://www.baidu.com")

# 输入电脑,按 回车键
driver.find_element_by_id("kw").send_keys("xxxxx", Keys.ENTER)
# 等待五秒,关闭浏览器
time.sleep(5)
driver.quit()

4.2 常用的键盘操作

引用方法对应键盘
send_keys(Keys.BACK_SPACE)删除键(BackSpace)
send_keys(Keys.SPACE)空格键(Space)
send_keys(Keys.TAB)制表键(Tab)
send_keys(Keys.ESCAPE)撤销键(Esc)
send_keys(Keys.ENTER)回车键(Enter)
send_keys(Keys.ALT)ALT键(Alt)
send_keys(Keys.CONTROL)Control键(Ctrl)
send_keys(Keys.CONTROL,'a')全选(Ctrl+A)
send_keys(Keys.CONTROL,'c')复制(Ctrl+C)
send_keys(Keys.CONTROL,'x')剪切(Ctrl+X)
send_keys(Keys.CONTROL,'v')粘贴(Ctrl+V)
send_keys(Keys.F1)键盘 F1
send_keys(Keys.F12)键盘 F12
send_keys(Keys.PAGE_UP)翻页键上(Page Up)
send_keys(Keys.PAGE_DOWN)翻页键下(Page Down)
send_keys(Keys.END)行尾键(End)
send_keys(Keys.HOME)行首键(Home)
send_keys(Keys.LEFT)方向键左(Left)
send_keys(Keys.UP)方向键上(Up)
send_keys(Keys.RIGHT)方向键右(Right)
send_keys(Keys.DOWN)方向键下(Down)
send_keys(Keys.INSERT)插入键(Insert)
send_keys(Keys.DELETE)删除键(Delete)
send_keys(Keys.NUMPAD0 ~ NUMPAD9)数字键1-9

5.下拉框

selenium通过Select完成下拉框选项选择

from selenium.webdriver.support.select import Select

5.1 常用的下拉框定位操作

  • Select选择方法
select_by_index(index) # 通过选项的顺序,第一个为 0
select_by_value(value) # 通过value属性
select_by_visible_text(text) # 通过选项可见文本
  • Select取消选择
deselect_by_index(index)
deselect_by_value(value)
deselect_by_visible_text(text)
deselect_all()
  • Select获取必要信息:
options # 提供所有的选项的列表,其中都是选项的WebElement元素
all_selected_options # 提供所有被选中的选项的列表,其中也均为选项的WebElement元素
first_selected_option # 提供第一个被选中的选项,也是下拉框的默认值                             

6.js操作

selenium运行JavaScript有两种形式,一种是接收JavaScript脚本语言,另一种是将WebElement传入JavaScript中执行脚本。

  • driver.execute_script("window.open('url')")
  • driver.execute_script('arguments[0].scrollIntoViewIfNeeded(true);',element)

7.页面操作

7.1 滚动页面至元素可见

7.1.1 js方法

ele.scrollIntoView()       滚动至元素ele可见
driver.execute_script("arguments[0].scrollIntoView();", ele)

7.1.2 selenium方法(location_once_scrolled_into_view)

#  滑动到跳转并提交这个元素可见
ele1 = driver.find_element(By.XPATH, "//button[text()='跳转式提交']") # 定位元素

# 滑动到元素可见
res = ele1.location_once_scrolled_into_view  # 返回的是元素在页面上的坐标位置

7.2 滚动页面元素(js)

7.2.1 滚动指定距离

window.scrollBy(0,500)    向下滚动500个像素
window.scrollBy(0,-500)   向上滚动500个像素
window.scrollBy(500,0)    向右滚动500个像素
window.scrollBy(-500,0)   向左滚动500个像素

driver.execute_script('window.scrollBy()')

7.2.2 滚动到浏览器顶部

  • window.scrollTo(0,0)
  • var q=document.documentElement.scrollTop=0

7.2.3 滚动到浏览器底部

  • var q=document.documentElement.scrollTop=10000
  • window.scrollTo(0,document.body.scrollHeight)

7.2.4 页面放大

  • document.body.style.zoom='1.7' # 1.7为放大倍数

7.2.5 页面缩小

  • document.body.style.zoom='0.5' # 0.5为缩小倍数

7.2.5 打开新页面

  • window.open(url)

8.文件上传

Web上本地上传图片,弹出的框Selenium是无法识别的,selenium本身没有直接的方法去实现上传本地文件,这里总结了两种上传文件的方式. 一种是input框,另外一种就比较复杂,直接操作windows弹框

8.1 input框文件上传

input标签.send_keys(path)

  • 单文件上传
    send_keys(r'"C:\课件\images\1595303640089.png"')

  • 多文件上传
    多文件上传就是在文件路径框里用引号括起单个路径,然后用逗号隔开多个路径
    send_keys(r'"C:\课件\images\1595303640089.png" "C:\课件\images\1587383433012.png"')
    但需要注意的是:只有多个文件在同一路径下,才能这样用,否则是会失败的(下面的写法是不可以的)
    send_keys(r'“C:\a.txt” “D:\b.txt”')

  • 例子

from selenium import webdriver

driver = webdriver.Edge()
driver.get('http://sahitest.com/demo/php/fileUpload.htm')
ele_input = driver.find_element_by_id('file')
ele_input.send_keys('d:\\baidu.py')  # send_keys
driver.quit()

8.2 非input型上传

8.2.1 pywinauto

pywinauto这个模式只能再windows环境中使用

from selenium.webdriver import Chrome
from pywinauto.keyboard import send_keys
import time

# 打开页面
driver = Chrome()
driver.implicitly_wait(10)
driver.get("https://www.layui.com/demo/upload.html")

# 点击上传图片的按钮
driver.find_element_by_id("test1").click()
# 输入文件的路径
time.sleep(1)
send_keys(r"C:\课件\images\1595303640089.png")
send_keys("{VK_RETURN}")

time.sleep(5)
driver.quit()
  • send_keys 键盘操作
按键名称对应符号
SHIFT+
CTRL
ALT%
SPACE{SPACE}
BACKSPACE{BACKSPACE} or {BS} or {BKSP}
BREAK{BREAK}
CAPS LOCK{CAPSLOCK}
DEL or DELETE{DELETE} or {DEL}
DOWN ARROW{DOWN}
END{END}
ENTER{ENTER} or ~
ESC{ESC}
HELP{HELP}
HOME{HOME}
INS or INSERT{INSERT} or {INS}
LEFT ARROW{LEFT}
NUM LOCK{NUMLOCK}
PAGE DOWN{PGDN}
PAGE UP{PGUP}
PRINT SCREEN{PRTSC}
RIGHT ARROW{RIGHT}
SCROLL LOCK{SCROLLLOCK}
TAB{TAB}
UP ARROW{UP}
+{ADD}
-{SUBTRACT}
*{MULTIPLY}
/{DIVIDE}

8.2.2 pyautogui

pyautogui:兼容window linux mac系统, 缺点:上传文件的路径中不能出现中文

from selenium.webdriver import Chrome
import pyautogui
import time

driver = Chrome()
driver.implicitly_wait(10)
driver.get("https://www.layui.com/demo/upload.html")

# 点击上传图片的按钮
driver.find_element_by_id("test2").click()
# 输入文件的路径
time.sleep(1)
pyautogui.write(r'C:\Users\MuSen\017CD1CE.gif')
pyautogui.press("enter", 2)  # 按键 按键次数

time.sleep(10)
driver.quit()
8.2.2.1 键盘操作
  • 输入普通字符串
pyautogui.typewrite('Hello, world!', 0.25)  # 0.25表示每输完一个字符串延时0.25秒
  • 输入特殊字符
代码按键
enter/return/\n回车
escESC键
shiftleft/shiftright左右SHIFT键
altleft/altright左右ALT键
ctrlleft/ctrlright左右CTRL键
tab/\tTAB键
backspace/deleteBACKSPACE/DELETE键
pageup/pagedownPAGE UP/PAGE DOWN键
home/endHOME/END键
up/down/left/right上下左右键
f1/f2/...F1/F2/...
volumemute/volumedown/volumeup??
pausePAUSE键
capslock/numlock/scrolllockCAPS LOCK/NUM LOCL/SCROLL LOCK键
insertINSERT键
printscreenPRINT SCREEN键
winleft/winright左右Win键
commandMac上的command键
  • 键盘的按下和释放
    keyDown(): 按下某个键
    keyUp(): 松开某个键
    press(): 一次完整的按键,前面两个函数的结合
  • 实例
# 如关闭某个窗口(ALT + F4)
pyautogui.keyDown('altleft')
pyautogui.press('f4')
pyautogui.keyUp('altleft')

# 或者直接使用热键函数
pyautogui.hotkey('altleft', 'f4')