定位表达式在浏览器上能够定位到,放到代码中定位不到的原因:
- 因为,目前大多数Web应用程序都是使用Ajax和Javascript开发的;每次加载一个网页,就会加载各种HTML标签、JS文件
- 但是,加载肯定有加载顺序,大型网站很难说一秒内就把所有东西加载出来,不仅如此,加载速度也受网络波动影响
- 因此,当我们要在网页中做元素定位的时候,有可能我们打开了网页但元素未加载出来,这个时候就定位不到元素,就会报错
- 所以,我们需要设置元素等待,意思就是:等待指定元素已被加载出来之后,我们才去定位该元素,就不会出现定位失败的现象了
等待方式:
1、强制等待:
- time.sleep(2):代码强制等待2s中后再往下继续运行
- 但是缺点就是:如果指定的时间过长,即使元素已被加载出来了,但还是要继续等,这样会浪费很多时间
2、隐式等待:
通过driver.implicitly_wait()方法设置隐式等待的时间,设置一次对driver的整个生命周期生效。等待元素出现再往下执行,如果元素超过了设置的最大等待时间还未出现会报错:等待超时。
注:隐式等待的作用域是全局,所以一般设置在整局代码的头几行。
3、显示等待: - 需要定位某个元素的时候,但元素可能不可见,这个时候针对这个元素就可以使用显式等待了
- 显式等待和隐式等待最大的不同就是:你可以它看成是局部变量,作用于指定元素
显式等待的优势
- 相比隐式等待,显式等待只对指定元素生效,不再是在整个WebDriver生命周期内生效【仅对元素生效】
- 可以根据需要定位的元素来设置显式等待,无需等待页面完全加载,节省大量因加载无关紧要文件而浪费掉的时间【针对元素设置,无需等待页面加载完成,节省加载时间】
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('http://www.baidu.com')
# 定位表达式
loc = (By.XPATH, '//*[@id="su"]')
# 创建一个等待条件的对象,传入定位表达式
ec = EC.presence_of_element_located(loc)
# 创建一个等待对象,需要传入三个参数:
# 参数1:driver对象、参数2:等待的最大时间、参数3:执行间隔,默认0.5s
wt = WebDriverWait(driver, 10, 0.5)
# 调用等待对象的until()方法传入等待的条件
wt.until(ec)
# 一行代码
# WebDriverWait(driver, 10, 0.5).until(EC.presence_of_element_located(By.XPATH, '//*[@id="su"]'))
七种常用的等待条件
序号 | 方法名 | 含义 |
---|---|---|
1 | presence_of_element_located | 判断某个元素是否被加到了dom树里,并不代表该元素一定可见 |
2 | visibility_of _element_located | 判断某个元素是否被加到了dom树里并且可见,宽和高都大于0 |
3 | element_to_be_clickable | 判断某个元素中是否可见且是enable的,代表可点击 |
4 | title_contains | 判断title,是否包含某些字符 |
5 | new_window_is_opened | 等待新窗口出现 |
6 | frame_to_be_available_and_switch_to_it | 判断该iframe是否可以switch进去 |
7 | alert_is_present | 判断页面上是否存在alert |
iframe切换
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.implicitly_wait(3)
driver.get('http://www.baidu.com')
# 定位表达式
loc_news = (By.XPATH, '//a[text()="新闻"]')
loc_js = (By.XPATH, '//ul[@class="clearfix lavalamp"]//a[text()="军事"]')
old_win = driver.current_window_handle
print("点击之前的窗口句柄:", old_win)
# 点击新闻
driver.find_element(*loc_news).click()
# 确保代码稳定性,打开新窗口之前最好加个判断
WebDriverWait(driver, 10, 0.5).until(EC.new_window_is_opened(driver.window_handles))
# 切换到打开的新窗口
wins = driver.window_handles
driver.switch_to.window(wins[-1])
print("点击之前的窗口句柄:", driver.window_handles)
# 点击军事
driver.find_element(*loc_js).click()
# 在切换到之前的窗口
driver.switch_to.window(old_win)
iframe标签切换:
方式一:通过iframe标签的name属性
driver.switch_to.frame(‘login_frame’)
方式二:先定位iframe标签再进行切换
loc_ifr = (By.ID, ‘login_frame’)
iframe_ele = driver.find_element(*loc_ifr)
driver.switch_to.frame(iframe_ele)
切换到主页面中:
driver.switch_to.default_content()
切换到上一层的iframe中:
driver.switch_to.parent_frame()
获取到alert弹框:
alert = driver.switch_to.alert
# 点击确定
alert.accept()
# 点击取消
alert.dismiss()
获取弹框的提示文本:
content = alert.text