一:3种等待方式
在实际工作中,使用selenium时,经常会遇到由于页面元素渲染速度不够快,导致定位元素失败,所以需要添加一个等待的过程。
在selenium中,常用的等待分为:
- sleep(): 强制等待,设置固定休眠时间。 python 的 time 包提供了休眠方法 sleep() , 导入 time 包后就可以使用 sleep(),进行脚本的执行过程进行休眠。
- implicitly_wait():隐式等待,也叫智能等待,是 webdirver 提供的一个超时等待。等待一个元素被发现,或一个命令完成。如果超出了设置时间的则抛出异常。
- WebDriverWait():显式等待,同样也是 webdirver 提供的方法。在设置时间内,默认每隔一段时间检测一次当前页面元素是否存在,如果超过设置时间检测不到则抛出异常。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException
1、强制等待sleep()
第一种等待方式是最简单粗暴的方法,直接使用强制等待sleep(X),强制让浏览器等待X秒。
X秒后不管当前是否可以进行下一步操作,都会运行其后的代码。如果时间设置的太长了,容易造成时间浪费,如果设置的太短又可能会造成规定时间内操作还没有完成就执行下一步会报错。由于等待时间无法确定,不建议使用这种方式。
from selenium import webdriver
import time
if __name__=="__mian__":
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
time.sleep(3) # 强制等待,注意需导入time
driver.quit()
2、隐性等待implicitly_wait()
implicitly_wair(X),给其设置了一个最长的等待时间X秒。在X秒时间内,只要页面加载完成,就进行下一步操作,否则一直等待到时间结束。如果超出了设置时间的则抛出异常。隐形等待对整个driver的周期都起作用,只需要设置一次即可。
使用隐形等待时,会一直等待到整个页面加载完成。但有时我们需要的元素早就已经加载完成了,一直等待整个页面加载完成是浪费时间的,所以可以采用下面的显性等待方式WebDriverWait。
from selenium import webdriver
if __name__=="__mian__":
driver = webdriver.Chrome()
driver.implicitly_wait(3) # 隐性等待,最长等待时间为3秒
driver.get('http://www.baidu.com')
driver.quit()
3、显性等待WebDriverWait()
WebDriverWait,显性等待一般需要配合该类的until()和until_not()方法一起用,表示程序每隔一定时间就检查一遍条件是否成立,如果成立了就执行下一步,否则就继续等。直到超过设置的最长时间,然后抛出超时错误TimeoutException。默认检测频率为0.5s,默认抛出异常为:NoSuchElementException
导入模块:
from selenium.webdriver.support.wait import WebDriverWait
表达式分为两种:
1):
使用expected_conditions类函数,使用此函数,需要导入模块:
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.by import By
栗子:
WebDriverWait(driver,10,0.5).until(expected_conditions.presence_of_element_located((By.ID,"kw"),message=""))
- 10表示在10秒内
- 0.5表示每隔0.5秒检测一次,默认是0.5,可以不写
- until(method,message=") 当某元素出现或什么条件成立则继续执行,message可以不写
- until_not(method,message=")当某元素消失或什么条件不成立则继续执行
- expected_conditions表示类函数
- presence_of_element_located表示判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
expected_conditions类提供的预期条件判断的方法
2):
自定义等待条件
WebDriverWait(driver,10).until(lambda diver:driver.find_element_by_id('kw'),message='没有此元素,定义超时')
二:异常处理try except
有时候不知道某个元素或者alter是否存在,但为了程序更加健壮性,需要对元素做出是否存在的判断,以分别做出不同的操作。因为每当发生让python不知所措时,它都会创建一个异常对象,使用try-except时,即便出现异常,程序也能继续运行
selenium是没有默认的方法或函数的,但是我们可以通过try except 捕获异常来自己封装函数:
有时会遇到这样的情况:
初始化函数中设置了隐式等待self.driver.implicitly_wait(15)
self.driver.find_element_by_css_selector('button.btn').click() # 点击登录按钮
self.driver.find_element_by_css_selector('div.v-data-footer__icons-after button:nth-child(2)').click() #点击登录后页面的某个按钮
结果发现没有等待15就报错,开始以为是隐性等待出问题了,结果仔细一看,发现错误信息中有ElementClickInterceptedException,是点击出问题
也就是说,该元素找到了,只是还不能点击
那么此时,解决方案为:
导入:from selenium.common.exceptions import ElementClickInterceptedException
while True:
try:
self.driver.find_element_by_css_selector('div.v-data-footer__icons-after button:nth-child(2)').click()
break
except ElementClickInterceptedException as e: #如果遇到ElementClickInterceptedException则except执行下面代码
pass
此刻问题是解决了,那么接下来优化代码的方案有两种
一是直接封装在该类里面
二是封装函数到webelement里面
封装到webelement的好处是要使用,直接“点”就能使用该函数,说白了,就类似于.click()
三:isElementPresent
判断界面中某一元素是否已经呈现,多用于断言
四:下拉框select模块
select操作方法:
导入新的模块:from selenium.webdriver.support.select import Select
select有以下操作方法:
方法 | 说明 |
---|---|
select_by_index() | 通过索引定位(0开始) |
select_by_value() | 通过value值定位(属性值) |
select_by_visible_text() | 通过文本值定位(下拉框的值) |
deselect_all() | 取消所有选项 |
deselect_by_index() | 取消对应index选项 |
deselect_by_value() | 取消对应value选项 |
deselect_by_visible_text() | 取消对应文本选项 |
first_selected_option() | 返回第一个选项 |
all_selected_options() | 返回所有的选项 |
options() | 返回所有的选择项 |
all_selected_options() | 返回所以已选中的选择项 |
first_selected_option() | 返回选中的第一个选择项 |