selenium之三大等待与三大切换

  1. 三大等待(强制等待,隐形等待,显性等待)
  2. 三大切换(iframe(内嵌),window,alert(弹框))
  3. 详解三大等待
    3.1 三大等待之强制等待
    sleep(s秒) 让程序死等s秒,无论发生任何事情,s秒后继续执行后续代码
    当我们的操作带来了页面的变化,那么一定需要等待(否则代码的稳定性很差)

    1
    2
    3
    4
    5
    6
    from selenium import webdriver
    from time import sleep
    # 浏览器会话的开始
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com')
    sleep(3) # 傻傻等3

    3.2 三大等待之隐形等待
    隐形等待:如果你10秒出现啦,我就开始下一步操作,设置上限:30秒,超时就报错:TimeoutException
    设置最长的等待时间,可以自主判断,整个driver会话周期,设置一次,全局可用 (driver.get()—driver.quite())
    implicitly_wait(s秒) driver会话周期:开始调用浏览器(浏览器会话的开始)—浏览器会话的结束(关闭浏览器则关闭了chromedriver)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from selenium import webdriver
    # 浏览器会话的开始
    driver = webdriver.Chrome()
    # 设置全局等待
    driver.implicitly_wait(30) # 所有存在find_element_by_XX(都会自动调用全局等待设置的时间)
    driver.get('https://ke.qq.com')
    driver.find_element_by_id('js_login').click()
    driver.close() # 关闭当前的窗口
    driver.quite() # 关闭浏览器则关闭了chromedriver

    3.3 三大等待之显性等待

    1. 明确的条件:(元素可见,窗口存在…) 等待+条件
    2. 引入相应的库,明确等到某一条件满足后,再去执行下一步操作。程序每隔XX秒看一眼,
      如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,则抛出TimeoutException
    3. WebDriverWait类:显性等待类
      WebDriverWait(driver,等待时长,轮询周期).until()/until_not()(直到条件成立..才/直到条件不成立….才)
    4. expected_conditions模块:提供一系列期望发生的条件
      presence_of_element_located: 元素存在
      visibility_of_element_located: 元素可见
      element_to_be_clickable: 元素可点击
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # 方法一
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    # 元素存在: 在HTML里面存在,能找到,可以定位到
    # 元素可见: 存在并且可见,看得见大小,宽高,可见才可以操作
    # 元素可用: 前提:可见(只读,不可点击都不可用)可见之后,才有可用的可能性
    # 等待表达式:lacator=(定位类型定位表达式)
    locator = (By.ID ,'TANGRAM__PSP_10__footerULoginBtn')
    # 条件:EC.visibility_of_element_located(locator)
    # 等待元素可见
    WebDriverWait(driver,30,1).until(EC.visibility_of_element_located(locator))
    辅助---0.5秒 提高速度
    sleep(0.5)
    # 点击元素
    driver.find_element_by_id("TANGRAM__PSP_10__footerULoginBtn").click()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 方法二
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium import webdriver
    driver = webdriver.Chrome() # 浏览器会话开启
    driver.implicitly_wait(20) # 设置全局等待时间
    driver.get('https://www.baidu.com') # 加载静态界面
    driver.find_element_by_id('kw').clear() # 清除输入文本框
    driver.find_element_by_id('kw').send_keys('柠檬班')
    driver.find_element_by_id('su').click()

    # 等待(有个小技巧)
    locator = (By.XPATH,"//a[text()='_腾讯课堂']")
    WebDriverWait(driver,30,1).until(EC.visibility_of_element_located(locator))
    sleep(0.5) # 辅助 提高代码速度
    driver.find_element(*locator).click() # 解包 小技巧,减少代码的重复性
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    封装操作等待的方法
    def common_wait(element):
    locator = (By.XPATH,element)
    try:
    WebDriverWait(driver,30,1).until(EC.visibility_of_element_located(locator))
    except TimeoutException:
    print('没有找到该元素!')
    else:
    # 没有异常,走else下面的代码
    return driver.find_element(*locator)

  4. 详解三大切换
    4.1 三大切换之iframe
    iframe:frame切换有2种方法

    1. driver.switch_to.frame(frame_reference)
      frame_reference的值有3种:
      1. iframe的下标(在当前页面中第几个iframe)
      2. iframe的name的属性
      3. iframe的WebElement对象
    2. frame_to_be_available_and_switch_to_it(frame_reference)
      判断iframe是否可用,并且自动切换到iframe新的html页面中
      frame_reference取值同方法一:
    3. 退出iframe回到默认的页面
      driver.switch_to.default_content()
    4. 返回到上一个父iframe页面
      driver.switch_to.parent_frame()
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      第一种方法:
      操作使用账号密码登录腾讯课堂
      driver.switch_to.frame(下标索引)
      driver.switch_to.frame('name属性值')
      driver.switch_to.frame(WebElement对象)

      from selenium import webdriver
      driver = webdriver.Chrome()
      driver.get('https://ke.qq.com')
      sleep(2)
      common_wait("//a[@id='js_login']",driver).click()
      common_wait("//a[text()='QQ登录']",driver).click()
      driver.switch_to.frame(4) # 方法1.1
      driver.switch_to.frame("login_frame_qq") # 方法1.2 --->常用
      driver.switch_to.frame(driver.find_element_by_xpath('//iframe[@name="login_frame_qq"]')) # 方法1.3
      # 进入了iframe里面的html页面,主页面了。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    第二种方法:iframe可用然后切进iframe  等待+切换
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium import webdriver

    driver = webdriver.Chrome()
    driver.get('https://ke.qq.com')
    sleep(2)
    common_wait("//a[@id='js_login']",driver).click()
    common_wait("//a[text()='QQ登录']",driver).click()
    WebDriverWait(driver,20).until(EC.frame_to_be_available_and_switch_to_it(4)) # 方法2.1
    WebDriverWait(driver,20).until(EC.frame_to_be_available_and_switch_to_it(login_frame_qq)) # 方法2.2---》常用
    WebDriverWait(driver,20).until(EC.frame_to_be_available_and_switch_to_it(driver.find_element_by_xpath('//iframe[@name="login_frame_qq"]'))) # 方法2.3
    # 进入了iframe里面的html页面,主页面了。

    4.2 三大切换之window
    window:窗口切换 有2种方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    第一种方法:
    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(20)

    driver.get('https://www.baidu.com') # 加载静态界面
    driver.find_element_by_id('kw').clear() # 清空文本输入框
    driver.find_element_by_id('kw').send_keys('柠檬班') # 输入柠檬班
    driver.find_element_by_id('su').click() # 点击百度一下的按钮
    # 等待
    locator = (By.XPATH,"//a[text()='_腾讯课堂']")
    WebDriverWait(driver,20,1).until(EC.visibility_of_element_located(locator))
    driver.find_element(*locator)

    # 点击柠檬班_腾讯课堂
    打开新的窗口
    1. 获取所有的窗口(handle:句柄,唯一的id值)
    handles = driver.window_handles # 按照窗口出现的顺序,最后一个就是最近打开的窗口
    print('所有的句柄是:{}'.format(handles)) # 得到的是列表
    current_handle = driver.current_window_handle
    print('当前的窗口的句柄是:{}'.format(current_handle))

    2. 切换新的窗口,点击课程
    driver.switch_to.window(handles[-1])
    print('切换之后的窗口为:{}'.format(driver.current_window_handle))

    # 在新的窗口中,点击课程
    # 页面之中,等待
    locator = (By.XPATH,"//section[@class='section-main']//h2[contains(text(),'课程')]")
    WebDriverWait(driver,20,1).until(EC.visibility_of_element_located(locator))
    driver.find_element(*locator).click()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    方法二:
    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(20)

    driver.get('https://www.baidu.com') # 加载静态界面
    driver.find_element_by_id('kw').clear() # 清空文本输入框
    driver.find_element_by_id('kw').send_keys('柠檬班') # 输入柠檬班
    driver.find_element_by_id('su').click() # 点击百度一下的按钮
    # 等待
    locator = (By.XPATH,"//a[text()='_腾讯课堂']")
    WebDriverWait(driver,20,1).until(EC.visibility_of_element_located(locator))

    # 点击柠檬班_腾讯课堂
    # step1:获取窗口数
    handles = driver.window_handles # 只有一个窗口(因为上一步没有点击操作)
    # step2: 执行打开新窗口的操作
    driver.find_element(*locator).click() # 本操作带来了新的窗口---2个
    # step3: 确认新的窗口出现了,再去操作它,等待新窗口出现(只是确认啦新窗口,没有切换)
    WebDriverWait(driver,20,1).until(EC.new_window_is_opened(handles)) # 确认新窗口的出现
    # step4: 再次获取,窗口的handles
    handles = driver.www
    # step5: 切换到新窗口
    driver.switch_to.window(handles[-1])

    # 在新的窗口中,点击课程
    # 页面之中,等待
    locator = (By.XPATH,"//section[@class='section-main']//h2[contains(text(),'课程')]")
    WebDriverWait(driver,20,1).until(EC.visibility_of_element_located(locator))
    driver.find_element(*locator)

4.3 三大切换之alert
弹出框有2种:

1. 页面弹出框---》html页面元素 DOM
   1. 执行触发操作后,等待弹出框出现
   2. 再定位弹出框的元素并操作
2. alert弹出框---Alert类--html页面上无法定位(不是html元素)
   切换--》接收 switch_to.alert--》alert是属性
   1. 浏览器弹出框,使用switch_to.alert方法切换到浏览器弹出框(driver.switch_to.alert)
   2. alert提供一系列操作方法:
      1. click()---->点击操作
      2. accept()---->点击确定按钮
      3. dismiss()---->点击取消按钮
      4. text()---->获取弹出框里面的内容
      5. send_keys()---->向弹出框输入文本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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()
# 操作 导致alert弹出出现
driver.find_element_by_xpath('定位代码').click()
# 点击页面元素,导致触发alert弹框出现
......
# 1. 等待弹框
# 2. 从html切换到alert---->实例化一个Alert类
# 3. 获取alert文本内容
# 4. 点击弹框中确定/取消,来关闭弹框(使弹出消失)
alert_is_present()--》是一个类,等待弹框出现
WebDriverWait(driver,20).until(EC.alert_is_present())
alert = driver.switch_to.alert
text = alert.text
alert.accept()
# alert.dismiss()
# # 进行后续的其它元素操作。

图形验证码:

1. 主动屏蔽
2. 找开发 配置万能验证码
3. 验证码一般会入库,可以直接去数据库查询入库的验证码,然后输入即可