zoukankan      html  css  js  c++  java
  • 32 web页面-页面操作(元素等待、三大切换)

    目录

    一、元素等待(70节44min)

    1.强制等待

    2.隐性等待

    3.显性等待

    二、三大切换

    1.窗口切换

    2.iframe切换

    3.alert弹框切换

    正文

    一、元素等待

    元素等待的3种方式:

    1.强制等待:time.sleep

    2.隐性等待

    3.显性等待(重点)

    灵魂一问:为什么要进行元素等待?

    CPU的运行速度远远大于网页的页面加载速度,会导致定位不到元素,所以要进行元素等待。

    背景实操:

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.get("http://www.baidu.com")
    e = driver.find_element_by_id("kw")
    e.send_keys("python")

    运行结果:在输入框中有输入python,但是并没有查询结果,因为没有点击“百度一下”

     下面添加“百度一下”的点击操作

    先定位百度一下:id=su

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    #打开百度
    driver.get("http://www.baidu.com")
    #定位输入框,用i属性
    e = driver.find_element_by_id("kw")
    #输入框中输入python
    e.send_keys("python")
    
    #定位 百度一下
    e = driver.find_element_by_id("su")
    e.click()

    在“百度一下”以后的页面中定位一个link_text的超链接文本:www.python.org/

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    #打开百度
    driver.get("http://www.baidu.com")
    #定位输入框,用i属性
    e = driver.find_element_by_id("kw")
    #输入框中输入python
    e.send_keys("python")
    
    #定位 百度一下
    e = driver.find_element_by_id("su")
    e.click()
    #定位 text
    e = driver.find_element_by_link_text("www.python.org/")

    运行结果:定位不到该元素

    当进行“百度一下”的操作,有个网页加载的过程,页面渲染可能快,可能慢,(python的运行程序很快)所以进行text定位的时候,会出现定位不到的情况。所以:加入元素等待时间。

    要等页面加载完成,才能执行e = driver.find_element_by_link_text("www.python.org/")

    1.强制等待

    上面的例子中加入强制等待时间(黄底代码)

    import time
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    #打开百度
    driver.get("http://www.baidu.com")
    #定位输入框,用i属性
    e = driver.find_element_by_id("kw")
    #输入框中输入python
    e.send_keys("python")
    
    #定位 百度一下
    e = driver.find_element_by_id("su")
    e.click()
    
    #强制等待 time.sleep(
    2) #定位 text e = driver.find_element_by_link_text("www.python.org/")

    强制等待总结:

    方法:time.sleep(),单位是秒
    使用方法:time.sleep(X),等待X秒后,进行下一步操作。无论条件成立与否,都要等待到时间截至,才能进行下一步操作
    缺点:不能准确把握需要等待的时间(有时操作还未完成,等待就结束了,导致报错;有时操作已经完成了,但等待时间还没有到,浪费时间),如果在用例中大量使用,会浪费不必 要的等待时间,影响测试用例的执行效率。-------时间不好控制(不够灵活)
    优点:使用简单,可以在调试时使用。

    智能等待:给定超时时间,在超时时间内,能够找到元素,就直接返回元素。如果在给你的超时时间内没有定位到元素,直接报错找不到元素。

    举例:给定超时时间20s,在第5s的时候可以找到元素,就直接返回。超过20s没有找到,就直接报错找不到元素。

    2.隐性等待-----全局作用域

    打开浏览器后,设置隐性等待的超时时间:driver.implicitly_wait()。设置这一次,所有的元素查找都能够生效。比如,设置了隐性等待的超时时间为5s,查找第一个元素会等待5s,查找第二个也会等待5s,.。。。。。。。(超过超时时间找不到元素,报错,noSuchElementException)

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    #打开百度
    driver.get("http://www.baidu.com")
    driver.implicitly_wait(2)
    
    #定位输入框,用i属性
    e = driver.find_element_by_id("kw")
    #输入框中输入python
    e.send_keys("python")
    
    #定位 百度一下
    e = driver.find_element_by_id("su")
    e.click()
    
    #定位 text
    e = driver.find_element_by_link_text("www.python.org/")

    隐性等待总结:

    隐形等待:只能等待元素加载,查找元素是否存在。------只能等待元素被查找到
    全局作用域:会话期间全局设置一次,所有元素查询都通用
    使用方法:设置超时时间:driver.implicitly_wait(X),在X时间内,页面加载完成,进行下一步操作。超过超时时间,报NoSuchElementException
                      设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间结束,然后执行下一步操作。
    缺点:使用隐式等待,程序会一直等待整个页面加载完成,才会执行下一步操作;只能等待元素被查到,其他的等待,无法使用。----------不够灵活
    优点:隐性等待对整个driver的周期都起作用,所以只要设置一次即可。

    来看下   implicitly_wait()函数的源码:只能等待一个元素,其他的它等不了。---如果要去等元素被点击、元素可见、等待窗口被打开等等,隐性等待就不起作用了。

    举例:一个元素能够被找到,不一定该元素能够点击。

    3.显性等待  (71节  13min)-----每次等待都要单独设置,这一点同强制等待一样

    显性等待,就是解决隐性等待解决不了的问题。

     ---等待某个元素被点击

    ---等待某个元素可见

    ---等待某个窗口被打开

    显性等待的步骤

    设置定时器wait

    wait = WebDriverWait()

    WebDriverWait是selenium.webdriver.support.wait中的一个类

    下面看下WebDriverWait类的源码:

    传入的参数有driver(浏览器对象)、timeout(超时时间)、poll_frequency(轮询时间,每隔多久查询一次,比如设置1s,每隔1s查询一次,第1s查询,查到就返回,查不到等待下一次即第2s再查询一次,以此类推)

    ②设置满足的条件:wait.until()

    until()中设置一个预期条件:expected_conditions <------------(from selenium.webdriver.support  import  expected_conditions)

    expected_conditions下,封装的条件很多,下面介绍几个常用的条件:

    1).等待元素出现:presence_of_element_located

        等待元素出现,到底等待那个元素出现呢???----传入locator参数

    presence_of_element_located()方法的源码:

     locator是个元组,元组里面是定位元素的方式,加表达式

    locator提前写好:locator = ("xpath",'//*[text() = "www.python.org/"]')

    完整语句:

    wait.until(expected_conditions.presence_of_element_located(locator=("xpath",'//*[text()= "www.python.org/"]')))#locator是个元组

    代码:

    """显性等待"""
    
    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    #初始化一个浏览器对象:driver
    driver = webdriver.Chrome()
    #打开浏览器
    driver.get("http://www.baidu.com")
    
    #定位百度输入框
    e = driver.find_element_by_id("kw")
    e.send_keys("柠檬班")
    
    #定位百度一下,查询python
    driver.find_element_by_id("su").click()
    
    #设置显性等待时间wait
    wait = WebDriverWait(driver,20,poll_frequency=0.5)#poll_frequency的默认值就是0.5
    
    #设置满足的条件
    locator = ('xpath','//*[text() = "lemon.ke.qq.com/"]')
    elem = wait.until(expected_conditions.presence_of_element_located(locator=locator))#locator是个元组
    print(elem.text)  #结果打印:lemon.ke.qq.com/

    2)元素是否可见:visibility_of_element_located(locator = locator)

    3)元素是否被点击:element_to_be_clickable(locator=locator)

    什么场景用什么方式?

    需要点击某个元素:用element_to_be_clickable

    需要查看某个元素:优先选用visibility_of_element_located

    元素可见用不了,再换用presence_of_element_located

    显性等待方法----封装

    def wait_element_clikable(locator,driver,timeout = 20,poll = 0.5):
        """等待元素被点击"""
        wait = WebDriverWait(driver, timeout=timeout, poll_frequency=poll)
        elem = wait.until(expected_conditions.element_to_be_clickable(locator=locator))
        return elem
    
    def wait_elemet_presence(locator,driver,timeout = 20,poll = 0.5):
        """等待元素出现"""
        wait = WebDriverWait(driver, timeout=timeout, poll_frequency=poll)
        elem = wait.until(expected_conditions.presence_of_element_located(locator=locator))
        return elem
    
    def wait_elemet_visiable(locator,driver,timeout = 20,poll = 0.5):
        """等待元素可见"""
        wait = WebDriverWait(driver, timeout=timeout, poll_frequency=poll)
        elem = wait.until(expected_conditions.visibility_of_element_located(locator=locator))
        return elem

    显性等待如果还是找不到元素怎么办???----报错:TimeoutException

    面试题:等待方式的选择

    1.优先:隐性等待:全局设置,等待查找元素

    2.再:显性等待:等待元素可以被点击,可见(如果隐性的等待可以找到元素,就不需要再进行显性等待)

    3.最后:强制等待:上面2个等待都用不了,就用强制等待;用在多个系统交互的地方,就要用强制等待。

    总结:

    1.元素等待

    首先用find_element()进行查找,看看是不是要进行元素等待。(有些元素不需要动态加载的,是不用等待的),如果找不到,用隐性等待。隐性等待找不到,换用现性等待;

    现性等待找不到的话,要记得切换条件(presence、visible、clickable);还是找不到再用强制等待。

    2.元素定位不到的原因有哪些?nosuchelement

    ①检查 元素定位的方式是否正确

    ②没有加元素等待  (调试的时候直接用强制等待,效果比较明显。’具体的业务逻辑按照上面的方式)

    ③检查 有没有在这个页面上:有没有在这个窗口上;是不是在iframe中

    二、三大切换 --71节41min

     为什么需要切换窗口?---因为selenium不会自动进行页面的跳转动作

    举例:如下在百度页面定位的超链接文本lemon.ke.qq.com/,点击进入该页面,打印出来的current_url是百度页面的url,不是跳转后的url

    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    #初始化浏览器对象
    driver = webdriver.Chrome()
    
    #打开百度
    driver.get("http://www.baidu.com")
    
    #定位百度输入框input
    elem = driver.find_element_by_id("kw")
    elem.send_keys("柠檬班")
    
    #定位“百度一下”
    elem=driver.find_element_by_id("su")
    elem.click()
    
    ####定位到查链接文本:图片
    #先进行等待--这里用显性等待
    #设置定时器wait
    wait = WebDriverWait(driver,timeout=5,poll_frequency=0.5)
    
    #设置满足的条件
    locator= ('xpath','//*[text()="lemon.ke.qq.com/"]')
    elem = wait.until(expected_conditions.element_to_be_clickable(locator=locator))
    elem.click()
    
    print(driver.current_url)

    结果如下:(不是lemon.ke.qq.com)

    页面切换后,才能进行新页面的元素定位。

    1.窗口切换

    1)窗口切换的函数:driver.switch_to.window(参数) 

              参数就是窗口句柄:window_handle

    首先获取所有的窗口句柄:driver.window_handles

     web自动化测试中,常用的就是切换到最新跳转的页面,即driver.window_handles[-1]

     代码:

    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    #初始化浏览器对象
    driver = webdriver.Chrome()
    
    #打开百度
    driver.get("http://www.baidu.com")
    
    #定位百度输入框input
    elem = driver.find_element_by_id("kw")
    elem.send_keys("柠檬班")
    
    #定位“百度一下”
    elem=driver.find_element_by_id("su")
    elem.click()
    
    ####定位到查链接文本:图片
    #先进行等待--这里用显性等待
    #设置定时器wait
    wait = WebDriverWait(driver,timeout=5,poll_frequency=0.5)
    
    #设置满足的条件
    locator= ('xpath','//*[text()="lemon.ke.qq.com/"]')
    elem = wait.until(expected_conditions.element_to_be_clickable(locator=locator))
    elem.click()
    
    print(driver.current_url)
    
    #窗口切换
      #获取所有的窗口句柄
    print(driver.window_handles)
    driver.switch_to.window(driver.window_handles[-1])
    print(driver.current_url)

    结果:

    2.iframe切换  ---71节50min

     1)如何确认当前页面中有没有iframe?

       -------F12,看当前页面下面的bar,是否有2个html

     

     如果页面中有iframe,定位元素是定位不到的。必须进行iframe切换。

     语法:driver.switch_to.frame()

     首先看下frame()的源码:

    2). iframe切换有3中方式:

    1.通过iframe的name属性进行定位切换:driver.switch_to.frame('frame_name') <-----------提供name属性的情况下

    2.通过iframe的索引进行切换:driver.switch_to.frame(1)---0表示第一个,1表示第二个 (这个方法基本不用)

    3.通过查询所有iframe元素,再进行索引(返回的是个webelement对象):driver.switch_to.frame(driver.find_elements_by_tag_name("iframe")[0]) <-------没有name属性的情况下

     实操:

    首先:自己写个带有iframe的页面,如下,iframe是百度首页

     要定位iframe中的百度input输入框,就要进行iframe切换。代码如下:

    from selenium import webdriver
    
    #初始化driver浏览器对象
    driver = webdriver.Chrome()
    
    #访问有iframe的页面
    driver.get("http://localhost:63342/study/lesson_32/iframe_why.html?_ijt=tpfqjvn2hv7su44vb95lke4q0l") 
    
    #带有iframe,进行定位
    ##首先找到要切换的iframe ----通过xpath找到iframe
    frame_elem = driver.find_element_by_xpath('//iframe[@src]')
    ##进行iframe切换
    driver.switch_to.frame(frame_elem)
    #定位返回的事webelement对象
    elem=driver.find_element_by_id("kw")
    print(elem)

    结果:

    注:上面的get中的url,每次要重新将写的HTML网页重新打开,用最新的url地址。

    72节

    3)要定位主页面的元素-------------------已经在iframe中,怎么定位iframe外的页面的元素?

    语法:driver.switch_to.default_content()

    带有iframe网页的HTML:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>title</title>
    </head>
    <body>
        <div>
            <ol>
                <li>胡歌</li>
                <li>彭于晏</li>
            </ol>
        </div>
    
        <iframe src="http://www.baidu.com"></iframe><br>
    
        <div>
            <p id="hello">python</p>
        </div>
    </body>
    </html>
    from selenium import webdriver
    
    #初始化driver浏览器对象
    driver = webdriver.Chrome()
    
    #访问有iframe的页面
    driver.get("http://localhost:63342/study/lesson_32/iframe_why.html?_ijt=fkgd5gchk67oah046kkqr8vats")
    
    #带有iframe,进行定位
    ##首先找到要切换的iframe ----通过xpath找到iframe
    frame_elem = driver.find_element_by_xpath('//iframe[@src]')
    ##进行iframe切换
    driver.switch_to.frame(frame_elem)
    #定位返回的事webelement对象
    elem=driver.find_element_by_id("kw")
    print(elem)
    
    #定位主页面的元素
    ##先切换回主页面
    driver.switch_to.default_content()
    elem = driver.find_element_by_id("hello")
    print(elem)

    4)如果主页面中有一个iframe,iframe中还套有iframe,怎么办?

     先通过xpath找第一次的iframe,再通过xpath找第二层iframe,以此类推。。。。。。。。。。。

    5)在多层iframe中,如何退回到主页面?

    通过parent_frame()一层一层退出来。

    语法:switch_to.parent_frame()

    ※特殊情况:

    iframe等待:不能用隐性等待(因为隐性等待只能等元素,等待了iframe的元素,但是不能等待iframe这个页面)

    所以iframe基本上都是用显性等待。

    代码实现:

    frame_to_be_available_and_switch_to_it:直到等待有效frame,再切换。可以实现2步操作的类(在第一个轮循时间内没有等待到,再进入下一个轮循时间)

    等待不到,报NoSuchFrameException

    from selenium import webdriver
    
    #初始化driver浏览器对象
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    driver = webdriver.Chrome()
    
    #访问有iframe的页面
    driver.get("http://localhost:63342/study/lesson_32/iframe_why.html?_ijt=elih8hfpjrq3j99ucucuhu5cod")
    
    ##首先找到要切换的iframe ----通过xpath找到iframe
    frame_elem = driver.find_element_by_xpath('//iframe[@src]')
    
    #iframe切换结合显性等待 WebDriverWait(driver,timeout=20,poll_frequency=0.5).until( expected_conditions.frame_to_be_available_and_switch_to_it(frame_elem)) #frame中定位id elem=driver.find_element_by_id("kw") print(elem) #定位主页面的元素 ##先切换回主页面 driver.switch_to.default_content() elem = driver.find_element_by_id("hello") print(elem)

    附上frame_to_be_available_and_switch_to_it类的源码:

    class frame_to_be_available_and_switch_to_it(object):
        """ An expectation for checking whether the given frame is available to
        switch to.  If the frame is available it switches the given driver to the
        specified frame.
        """
        def __init__(self, locator):
            self.frame_locator = locator
    
        def __call__(self, driver):
            try:
                if isinstance(self.frame_locator, tuple):
                    driver.switch_to.frame(_find_element(driver,
                                                         self.frame_locator))
                else:
                    driver.switch_to.frame(self.frame_locator)
                return True
            except NoSuchFrameException:
                return False

    3.alert弹框切换

    先写个带有alert弹窗的html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>alert</title>
    </head>
    <body>
        <p>selenium python autotest</p>
        <p id="leain" onclick="alertMe()"> learn python</p>
    
        <script>
            function alertMe(){
                alert("this is a alert window!")
            }
        </script>
    
    </body>
    </html>

    页面显示如下:

     出现弹框alert以后,就无法对主页面进行元素定位(主页面被alert遮盖,无法操作。)

    所以在出现弹框后,要对主页面进行元素定位,必须先将alert关闭---》点击alert弹窗的【确定】按钮,关闭弹窗。

    (1).语法:

    ①切换到alert弹框,alert是属性(源码的方法上加了@property)

    ②alert中的确定按钮,alert_elem.accept()

                     取消按钮:alert_elem.dismiss()

    代码实现:

    from selenium import webdriver
    
    #初始化driver浏览器对象
    driver = webdriver.Chrome()
    driver.get("http://localhost:63342/study/%E5%85%83%E7%B4%A0%E7%AD%89%E5%BE%85/alert.html?_ijt=pbds0nqdgd9ighds0bdgdfeo8p")
    
    #id 定位元素learn python,并点击
    driver.find_element_by_id("learn").click()
    #切换到alert
    alert_elem = driver.switch_to.alert
    #点击确定
    alert_elem.accept()

    (2)alert等待的条件----alert_is_present()

    alert_is_present():不需要传参数

    源码如下,__init__(self)没有参数需要传递,直接调用call方法

    class alert_is_present(object):
        """ Expect an alert to be present."""
        def __init__(self):
            pass
    
        def __call__(self, driver):
            try:
                alert = driver.switch_to.alert
                return alert
            except NoAlertPresentException:
                return False

    现性等待后切换到alert页面,代码如下

    from selenium import webdriver
    from selenium.webdriver.support.wait import WebDriverWait
    from selenium.webdriver.support import expected_conditions
    
    #初始化driver浏览器对象
    driver = webdriver.Chrome()
    driver.get("http://localhost:63342/study/%E5%85%83%E7%B4%A0%E7%AD%89%E5%BE%85/alert.html?_ijt=t00ugtfhr0mvvdj7017ec14i66")
    
    #id 定位元素learn python,并点击
    driver.find_element_by_id("learn").click()
    
    # #切换到alert
    # alert_elem = driver.switch_to.alert
    
    #显性等待alert并切换
    alert_elem = WebDriverWait(driver,timeout=20,poll_frequency=0.5).until(expected_conditions.alert_is_present())
    
    #点击确定
    alert_elem.accept()

     总结:

    1.窗口切换,iframe切换需要加参数,alert切换不需要加参数,的原因?

    一个页面只可能有一个alert,但是iframe可能存在多个。

  • 相关阅读:
    ural 1146. Maximum Sum(动态规划)
    ural 1119. Metro(动态规划)
    ural 1013. K-based Numbers. Version 3(动态规划)
    Floyd算法
    杭电21题 Palindrome
    杭电20题 Human Gene Functions
    杭电15题 The Cow Lexicon
    杭电三部曲一、基本算法;19题 Cow Bowling
    杭电1002 Etaoin Shrdlu
    Qt 学习之路 2(37):文本文件读写
  • 原文地址:https://www.cnblogs.com/ananmy/p/13369766.html
Copyright © 2011-2022 走看看