zoukankan      html  css  js  c++  java
  • 第 4 章 WebDriver API

    4.9 多表单切换

    在 Web 应用中经常会遇到 frame/iframe 表单嵌套页面的应用,WebDriver 只能在一个页面上对元素进行识别和定位,无法直接定位 frame/iframe 表单内嵌页面上的元素,这时就需要通过 switch_to.frame()方法将当前定位的主体切换为 frame/iframe 表单的内嵌页面。这里以 126 邮箱登录为例,登录框结构如下。

    通过 switch_to.frame()方法切换表单。

    9_more_frame.py

    """
    *  switch_to.frame()  进入表单
    *  switch_to.default_content()  退出表单至根页面
    """
    from selenium import webdriver
    from time import sleep
    
    driver = webdriver.Chrome()
    driver.get("http://www.126.com")
    sleep(2)
    
    login_frame = driver.find_element_by_css_selector('iframe[id^="x-URS-iframe"]')
    driver.switch_to.frame(login_frame)
    driver.find_element_by_name("email").send_keys("username")
    driver.find_element_by_name("password").send_keys("password")
    driver.find_element_by_id("dologin").click()
    driver.switch_to.default_content()
    
    driver.quit()

    switch_to.frame()默认可以直接对表单的 id 属性或 name 属性传参,因而可以定位元素的对象。在这个例子中,表单的 id 属性后半部分的数字(1553484417298.5217)是随机变化的,在 CSS 定位方法中,可以通过「^=」匹配 id 属性为以「x-URS-iframe」开头的元素。

    最后,通过 switch_to.default_content()回到最外层的页面。

    4.10 多窗口切换

    在页面操作过程中,有时单击某个链接会弹出新的窗口,这时就需要切换到新打开的窗口中进行操作。WebDriver 提供的 switch_to.window()方法可以实现在不同的窗口间切换。
    ● current_window_handle:获得当前窗口句柄。
    ● window_handles:返回所有窗口的句柄到当前会话。
    ● switch_to.window():切换到相应的窗口。

    以百度首页和账号注册页为例,在两个窗口之间的切换如图 4-4 所示。

    """
    *  switch_to.window()  切换窗口
    *  current_window_handle 获得当前窗口的句柄
    *  window_handles:返回所有窗口的句柄到当前会话
    """
    from selenium import webdriver
    import time
    
    driver = webdriver.Chrome()
    driver.implicitly_wait(10)
    driver.get("http://www.baidu.com")
    
    # 获得百度搜索窗口句柄
    search_windows = driver.current_window_handle
    
    driver.find_element_by_link_text('登录').click()
    driver.find_element_by_link_text("立即注册").click()
    
    # 获得当前所有打开的窗口的句柄
    all_handles = driver.window_handles
    
    # 进入注册窗口
    for handle in all_handles:
        if handle != search_windows:
            driver.switch_to.window(handle)
            print(driver.title)
            driver.find_element_by_name("userName").send_keys('username')
            driver.find_element_by_name('phone').send_keys('138xxxxxxx')
            time.sleep(2)
            # ……
            # 关闭当前窗口
            driver.close()
    
    
    # 回到搜索窗口
    driver.switch_to.window(search_windows)
    print(driver.title)
    
    driver.quit()

    脚本的执行过程:首先打开百度首页,通过 current_window_handle 获得当前窗口句柄,并赋值给变量 search_handle。接着打开登录弹窗,在登录弹窗上单击「立即注册」链接,从而打开新的注册窗口。通过 window_handles 获得当前所有窗口句柄(包含百度首页和账号注册页),并赋值给变量 all_handles。
    循环遍历 all_handles,如果 handle 不等于 search_handle,那么一定是注册窗口,因为在脚本执行过程中只打开了两个窗口。然后,通过 switch_to.window()切换到账号注册页。

    4.11 警告框处理

    在 WebDriver 中处理 JavaScript 生成的 alert、confirm 和 prompt 十分简单,具体做法是,首先使用 switch_to.alert()方法定位,然后使用 text、accept、dismiss、send_keys 等进行操作。

    ● text:返回 alert、confirm、prompt 中的文字信息。
    ● accept():接受现有警告框。
    ● dismiss():解散现有警告框。
    ● send_keys():在警告框中输入文本(如果可以输入的话)。
    可以使用 switch_to.alert()方法为百度搜索设置弹窗,如图 4-5 所示。

    """
    * text:返回 alert/confirm/prompt 中的文字信息。
    * accept():接受现有警告框。
    * dismiss():解散现有警告框。
    * send_keys(keysToSend): 发送文本至警告框。
    """
    from selenium import webdriver
    from time import sleep
    
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com')
    
    # 打开搜索设置
    link = driver.find_element_by_link_text('设置').click()
    driver.find_element_by_link_text("搜索设置").click()
    sleep(2)
    
    # 保存设置
    driver.find_element_by_class_name("prefpanelgo").click()
    
    # 获得警告框
    alert = driver.switch_to.alert
    
    # 获得警告框提示信息
    alert_text = alert.text
    print(alert_text)
    
    # 接受警告框
    alert.accept()
    
    driver.quit()

    这里以百度搜索设置为例,打开百度搜索设置,设置完成后单击「保存设置」按钮,弹出保存确认警告框。通过 switch_to.alert 方法获取当前页面上的警告框,text 用于获取警告框提示信息,accept()用于接受警告框。

    4.12 下拉框处理

    下拉框是 Web 页面常见功能之一,WebDriver 提供了 Select 类来处理下拉框。

    ● Select 类:用于定位 <select> 标签。
    ● select_by_value():通过 value 值定位下拉选项。
    ● select_by_visible_text():通过 text 值定位下拉选项。
    ● select_by_index():根据下拉选项的索引进行选择。第一个选项为 0,第二个选项为 1。

    以百度搜索设置为例,下拉框代码如下。

    通过 WebDriver 代码操作下拉框。

    """
    * Select  操作select标签的下拉框。
    * select_by_value()  选择value属性选择。
    * select_by_visible_text() 通过选项名称选择。
    * select_by_index() 通过索引选择
    """
    from selenium import webdriver
    from selenium.webdriver.support.select import Select
    from time import sleep
    
    driver = webdriver.Chrome()
    driver.get('https://www.baidu.com')
    
    # 打开搜索设置
    link = driver.find_element_by_link_text('设置').click()
    driver.find_element_by_link_text("搜索设置").click()
    sleep(2)
    
    # 搜索结果显示条数
    sel = driver.find_element_by_xpath("//select[@id='nr']")
    
    # value="20"
    Select(sel).select_by_value('20')
    sleep(2)
    
    # <option>每页显示50条</option>
    Select(sel).select_by_visible_text("每页显示50条")
    sleep(2)
    
    # 根据选项的索引选择
    Select(sel).select_by_index(0)
    sleep(2)
    
    driver.quit()

    4.13 上传文件

    上传文件是比较常见的 Web 功能之一,但 WebDriver 并没有提供专门用于上传的方法,实现文件上传的关键在于思路。
    在 Web 页面中,文件上传操作一般需要单击「上传」按钮后打开本地 Windows 窗口,从窗口中选择本地文件进行上传。因为 WebDriver 无法操作 Windows 控件,所以对于初学者来说,一般思路会卡在如何识别 Windows 控件这个问题上。

    在 Web 页面中一般通过以下两种方式实现文件上传。
    ● 普通上传:将本地文件路径作为一个值放在 input 标签中,通过 form 表单将这个值提交给服务器。
    ● 插件上传:一般是指基于JavaScript 或 Ajax 等技术实现的上传功能。
    对于通过 input 标签实现的上传功能,可以将其看作一个输入框,即通过 send_keys()指定本地文件路径的方式实现文件上传。

    通过浏览器打开 upfile.html 文件,效果如图 4-6 所示。

    """
    * send_keys() 指定文件上传路径。
    """
    from selenium import webdriver
    import os
    
    file_path = os.path.abspath('./files/')
    
    driver = webdriver.Chrome()
    upload_page = 'file:///' + file_path + 'upfile.html'
    driver.get(upload_page)
    
    # 定位上传按钮,添加本地文件
    driver.find_element_by_id("file").send_keys(file_path + 'test.txt')
    # ……

    这里测试的页面(upfile.html)和上传的文件(test.txt)位于与当前程序同目录的 files/目录下。
    通过这种方式上传,就避免了操作 Windows 控件。如果能找到上传的 input 标签,那么基本可以通过 send_keys()方法输入一个本地文件路径实现上传。
    对于插件上传,我们可以使用 AutoIt 来实现,由于超出本书范围,这里不再介绍。

    4.14 下载文件

    WebDriver 允许我们设置默认的文件下载路径,也就是说,文件会自动下载并且存放到设置的目录中,不同的浏览器设置方式不同。
    下面以 Firefox 浏览器为例,演示文件的下载。

    firefox浏览器实现下载

    """
    firefox浏览器实现下载
    """
    import os
    from selenium import webdriver
    
    fp = webdriver.FirefoxProfile()
    
    fp.set_preference("browser.download.folderList", 2)
    fp.set_preference("browser.download.dir", os.getcwd())
    fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "binary/octet-stream")
    
    driver = webdriver.Firefox(firefox_profile=fp)
    driver.get("https://pypi.org/project/selenium/#files")
    driver.find_element_by_partial_link_text("selenium-3.141.0.tar.gz").click()
    View Code

    为了能在 Firefox 浏览器中实现文件的下载,我们需要通过 FirefoxProfile()对其做一些设置

    设置为 0,表示文件会下载到浏览器默认的下载路径;设置为 2,表示文件会下载到指定目录

    用于指定下载文件的目录。通过 os.getcwd()方法获取当前文件的所在位置,即下载文件保存的目录

     

    指定要下载文件的类型,即 Content-type 值,「binary/octet-stream」用于表示二进制文件。
    HTTP Content-type 常用对照表参见 http://tool.oschina.net/commons

    可以通过在 Firefox 浏览器地址栏输入「about:config」进行参数的设置,如图 4-7 所示。
    在调用 WebDriver 的 Firefox 类时将所有设置选项作为 firefox_profile 参数传递给 Firefox 浏览器。Firefox 浏览器在下载时会根据这些设置将文件下载到当前脚本目录下。

    图 4-7 Firefox 参数设置

    chrome浏览器实现下载

    """
    chrome浏览器实现下载
    """
    import os
    from selenium import webdriver
    
    options = webdriver.ChromeOptions() 
    prefs = {'profile.default_content_settings.popups': 0,
             'download.default_directory': os.getcwd()}
    options.add_experimental_option('prefs', prefs) 
    
    driver = webdriver.Chrome(chrome_options=options) 
    driver.get("https://pypi.org/project/selenium/#files")
    driver.find_element_by_partial_link_text("selenium-3.141.0.tar.gz").click()
    View Code

    Chrome 浏览器在下载时默认不会弹出下载窗口,这里主要想修改默认的下载路径。

    设置为 0,表示禁止弹出下载窗口。

    设置文件下载路径,使用 os.getcwd()方法获取当前脚本的目录作为下载文件的保存位置

    部分内容来自于学习编程期间收集于网络的免费分享资源和工作后购买的付费内容。
  • 相关阅读:
    下载MATLAB硬件支持包的方法
    chromium 编译源码里面的单一模块 测试用例
    cc/animation
    raster 像素化
    Property Trees & DispalyItem
    Charles的HTTPS抓包
    git 修改.gitignore后未生效
    Word2Vec原理详解
    Pytorch中的Embedding
    在mac m1上安装tensorflow报错“zsh: illegal hardware instruction”
  • 原文地址:https://www.cnblogs.com/MarlonKang/p/12426265.html
Copyright © 2011-2022 走看看