- 三大等待
- 三大切换(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 | 回车 |
esc | ESC键 |
shiftleft/shiftright | 左右SHIFT键 |
altleft/altright | 左右ALT键 |
ctrlleft/ctrlright | 左右CTRL键 |
tab/\t | TAB键 |
backspace/delete | BACKSPACE/DELETE键 |
pageup/pagedown | PAGE UP/PAGE DOWN键 |
home/end | HOME/END键 |
up/down/left/right | 上下左右键 |
f1/f2/... | F1/F2/... |
volumemute/volumedown/volumeup | ?? |
pause | PAUSE键 |
capslock/numlock/scrolllock | CAPS LOCK/NUM LOCL/SCROLL LOCK键 |
insert | INSERT键 |
printscreen | PRINT SCREEN键 |
winleft/winright | 左右Win键 |
command | Mac上的command键 |
- 键盘的按下和释放
keyDown(): 按下某个键
keyUp(): 松开某个键
press(): 一次完整的按键,前面两个函数的结合 - 实例
# 如关闭某个窗口(ALT + F4)
pyautogui.keyDown('altleft')
pyautogui.press('f4')
pyautogui.keyUp('altleft')
# 或者直接使用热键函数
pyautogui.hotkey('altleft', 'f4')