• 五、元素等待/三大切换


    元素等待

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

    一、强制等待

    time.sleep( )   单位:秒

    缺点:时间不好控制

    需要等待的时候加time.sleep( ),等待n秒后进行下一步操作。无论条件成立与否,都要等待到时间后才能进行下一步操作

    import time
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.get("http://www.baidu.com")
    e = driver.find_element_by_id("kw")
    e.send_keys("柠檬班")
    # 点击百度一下
    driver.find_element_by_id("su").click()
    # 强制等待元素加载0.5秒
    time.sleep(0.5)
    driver.find_element_by_link_text("lemon.ke.qq.com/").click()

    二、隐形等待

    给一个超时时间,如果在超时时间之内能够找到,就直接返回元素,如果超时了,就报错

    --全局设置,设置一次就行

    --设置超时时间

    --只能用来等待元素

    --找不到元素报错:NoSuchElement

    import time
    from selenium import webdriver
    driver = webdriver.Chrome()
    
    # 隐式等待超时时间,全局设置。每次查找自动设置超时20秒
    driver.implicitly_wait(20)
    
    driver.get("http://www.baidu.com")
    e = driver.find_element_by_id("kw")
    e.send_keys("柠檬班")
    # 点击百度一下
    driver.find_element_by_id("su").click()
    driver.find_element_by_link_text("lemon.ke.qq.com/").click()

    三、显性等待

    --等待某个元素被点击

    --等待某个元素可见

    --等待某个窗口被打开

    不是全局的,每次等待都要单独设置

    找不到元素时报错:TimeoutException 

    显性等待几个重要的条件:

    1.presence_of_element_located(locator)  元素是否出现

    2.visibility_of_element_located(locator)   元素是否可见

    3.element_to_be_clickable(locator)          元素是否可以被点击

    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")
    e = driver.find_element_by_id("kw")
    e.send_keys("柠檬班")
    # 点击百度一下
    driver.find_element_by_id("su").click()
    
    # 显性等待
    # 第一步:设置定时器(每隔0.5秒查询一次,直到找到元素。poll_frequency可省略-默认是0.5)
    wait = WebDriverWait(driver,timeout=20,poll_frequency=0.5)
    
    # 第二步:设置满足的条件(可以是任意条件,需要返回True,如果是False进入下一轮询,直至超时)
    locator=('xpath','//*[text()="lemon.ke.qq.com/"]')
    elem = wait.until(expected_conditions.presence_of_element_located(locator=locator))
    print(elem.text)

    封装(等待元素被点击)

    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

    等待方式的选择

    --隐式等待:全局设置,等待查找元素(第一顺位)

    --显性等待:等待元素可以被点击、可见等(第二顺位)

    --强制等待:多个系统交互的地方

    四、总结

    1)元素等待

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

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

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

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

    ②没有加元素等待  (调试的时候直接用强制等待,效果比较明显)

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

    窗口切换

    selenium不会自动进行页面的跳转动作,需要手动进行页面切换后,才能进行新页面的元素定位

    一、窗口切换

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

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

    切换到最新跳转的页面:driver.window_handles[-1]

    from selenium import webdriver
    driver = webdriver.Chrome()
    driver.implicitly_wait(5)
    driver.get("http://www.baidu.com")
    e = driver.find_element_by_id("kw")
    e.send_keys("柠檬班")
    # 点击百度一下
    driver.find_element_by_id("su").click()
    driver.find_element_by_link_text("lemon.ke.qq.com/").click()
    
    # 获取现在的url
    print(driver.current_url)
    # 窗口句柄
    print(driver.window_handles)
    # 窗口切换
    driver.switch_to.window(driver.window_handles[-1])
    print(driver.current_url)

    二、iframe切换

    判断有没有iframe:看下面的bar,有没有iframe,或者两个html

    iframe切换语法:driver.switch_to.frame()

    切换到父级iframe:switch_to.parent.frame( )

    带iframe的页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <p>hello</p>
        </div>
        <iframe src="http://www.baidu.com" height="600" width="1300"></iframe>
        <div>
            <p>world</p>
        </div>
    </body>
    </html>

    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(5)
    driver.get("http://localhost:63342/study/Lemon/demohtml.html?_ijt=i5m09icq2rq7g6e7pgfthgcq5b")
    
    # 先找到要切换的iframe
    iframe_elem = driver.find_element_by_xpath('//iframe[@src]')
    driver.switch_to.frame(iframe_elem)
    
    # 定位iframe中百度当中的input kw
    input_elem = driver.find_element_by_id("kw")
    input_elem.send_keys("柠檬班")
    # 点击百度一下
    driver.find_element_by_id("su").click()
    
    # 定位主页面的元素,必要切回主页面
    driver.switch_to.default.content()
    driver.find_element_by_id("hello")

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

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

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

    • 通过parent_frame()一层一层退出来。witch_to.parent_frame()

    扩展:iframe等待

    不能使用隐形等待,因为隐形等待只能等待元素,不能等待页面

    强制等待时间不好控制

    可以使用显性等待(自动切换到iframe,不需要手动切换到iframe)

    WebDriverWait(driver,timeout=10,poll_frequency=0.5).until(
        expected_conditions.frame_to_be_available_and_switch_to_it(iframe_elem)
    )

    三、alert切换

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <p id="hello" onclick="alertMe()"> hello world </p>
    <script> function alertMe(){ alert("this is a alert window!") } </script> </div> </body> </html>

     

    import time
    from selenium import webdriver
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(5)
    driver.get("http://localhost:63342/study/Lemon/demohtml.html?_ijt=3mm3fi2qatf20a9rongkmg4it3")
    driver.find_element_by_id("hello").click()
    
    # 切换到alert,点击确定按钮
    e = driver.switch_to.alert
    time.sleep(5)
    e.accept()

    alert等待的条件:alert_is_present()

    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/Lemon/demohtml.html?_ijt=3mm3fi2qatf20a9rongkmg4it3")
    
    #id 定位元素learn python,并点击
    driver.find_element_by_id("hello").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()

    总结:

    iframe切换需要加参数,alert切换不需要加参数:一个页面只可能有一个alert,但是iframe可能存在多个

  • 相关阅读:
    通过字符串调用函数
    First,FirstOrDefault和Single,SingleOrDefault 的区别
    asp循环例子
    将il文件和资源文件生成dll工具
    C# 修改资源文件工具ResourceNet4
    北京ip
    实验1、Mininet 源码安装和可视化拓扑工具
    实验2:Mininet 实验——拓扑的命令脚本生成
    ajax post data 获取不到数据,注意 contenttype的设置 、post/get
    调试提示:当前不会命中断点
  • 原文地址:https://www.cnblogs.com/zhangjx2457/p/13796440.html
Copyright © 2020-2023  润新知