frame嵌套页面元素定位+多窗口跳转(句柄)+警告弹框+上传文件+js操作(滚动条操作、时间控件赋值)+截图 + 多浏览器

时间:2024-02-29 17:06:27

1. 多窗口处理

1.1 多窗口的概念 

    selenium里面如何处理多窗口场景

  • 多窗口识别
  • 多窗口之间的切换

    点击某个链接,会重新打开一个窗口,这种情况,想在新页面上操作,就得先切换窗口

    selenium里面如何处理frame

  • 多个frame识别
  • 多个frame之前切换

    获取窗口的唯一标识句柄,切换句柄,即可实现多页面的灵活切换

1.2 多窗口的处理步骤

  1. 首先获取当前窗口句柄(driver.current_window_handle)
  2. 再获取所有窗口句柄(driver.window_handles)
  3. 判断是否是想要的操作窗口,如果是,就可以对窗口操作,如果不是,就切换窗口(driver.switch_to_window)操作

      案例

  1. 打开百度
  2. 点击登录
  3. 弹框中点击"立即注册",输入账户和密码
  4. 返回登录页,点击登录
  5. 输入用户名密码,点击登录
from selenium import webdriver

class setupTeardown:
    def setup(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(5)
        self.driver.maximize_window()

    def teardown(self):
        self.driver.quit()
setupTeardown
from time import sleep
from UI.SetupTeardown import setupTearwodn


class TestWindows(setupTearwodn):
    def test_windows(self):
        self.driver.get(\'https://www.baidu.com/\')
        print(self.driver.window_handles)
        print(self.driver.current_window_handle)
        self.driver.find_element_by_xpath(\'//*[@id="u1"]/a[2]\').click()
        self.driver.find_element_by_link_text(\'立即注册\').click()
        print(self.driver.current_window_handle)
        print(self.driver.window_handles)
        sleep(1)
        windows = self.driver.window_handles
        self.driver.switch_to.window(windows[1])
        self.driver.find_element_by_xpath(\'//*[@name="userName"]\').send_keys(\'hi\')
        sleep(1)
        self.driver.switch_to.window(windows[0])
        self.driver.find_element_by_id(\'TANGRAM__PSP_11__footerULoginBtn\').click()
        self.driver.find_element_by_name(\'userName\').send_keys(\'hi\')
        sleep(1)
baidu_switchto_windows

2. frame

     在web自动化中,如果一个元素定位不到,很大可能是在iframe中

2.1 什么是iframe?

      frame是HTML中的框架,在html中,所谓的框架就是可以在同一个浏览器中显示不止一个页面

      基于HTML的框架,又分为垂直框架和水平框架(cols,rows)

2.2 frame 分类

  • frame标签包含:frameset frame iframe三种
  • frameset和普通的标签一样,不会影响定位,可以使用index、id、name、webelement任意方式定位frame
  • 而frame与iframe对selenium定位而言是一样的,selenium有一组方法对frame进行操作

    https://www.w3school.com.cn/tiy/t.asp?f=html_frame_cols

     

     

2.3. 多frame切换

frame存在两种:嵌套的,和未嵌套的

处理未嵌套的iframe

  • driver.switch_to_frame("frame的 id")
  • driver.switch_to_frame("frame-index") frame无ID时依据索引来处理,索引从0开始 driver.switch_to_frame(0)

处理嵌套的iframe

  • 对于嵌套的先进入到iframe的父节点,再进入子节点,然后对子节点里的对象进行处理
  • driver.switch_to.frame("节点")

切换frame

  • driver.switch_to.frame()  # 根据元素id或者index切换frame
  • driver.switch_to.default_content()   #切换到默认frame

2.4 frame嵌套页面元素定位实战

案例:在Frame.html文件种定位搜狗搜索页面,进行搜索操作

#/usr/bin python
#-*- coding:UTF-8 -*-
#####################嵌套框架#####################
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
#设置网页文件路径,r代表转译
filr_path = r\'E:\study\python\我要自学网-python+selenium\脚本与课件\4-22~4-32 Script\Frame.html\'
driver.get(filr_path)

#切换到frame页面内,search 为嵌套页面的id
driver.switch_to.frame(\'search\')

#定位到搜索框按钮输入关键词
driver.find_element_by_id(\'query\').send_keys(\'selenium 官网\')
driver.find_element_by_css_selector(\'#stb\').click()
sleep(3)

driver.quit()

Frame.xml文件内容

<html>
<head>
<title>Frame_test</title>
</head>

<body>
    <div>
        <iframe id="search" src="http://www.sogou.com" width="800" height="500">
    </div>
</body>

<html>

switch_to_frame() 默认可以直接取表单的 id 或 name 属性进行切换。
那么如果 iframe 没有可用的 id 和 name 可以通过下面的方式进行定位:

……
#先通过 xpth 定位到 iframe
xf = driver.find_element_by_xpath(\'//*[@class="if"]\')
#再将定位对象传给 switch_to_frame()方法
driver.switch_to_frame(xf) ……
driver.switch_to_default_content()

如果完成了在当前表单上的操作可以通过 switch_to_default_content()方法返回到上一层表单。该方法不用指定某个表单的返回,默认对应与它最近的 switch_to_frame()方法。

2.5 多窗口切换操作 

  案例:打开我要自学网Selenium课程主页,然后打开4-14课程详情页面,再回到课程主页打开4-15课程详情页面

#/usr/bin python
#-*- coding:UTF-8 -*-
######################多窗口切换操作######################
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()

#打开selenium课程页面  51自学网由于不能保存,暂且切换为百度
driver.get(\'http://www.baidu.com/list.aspx?page=3&cid=615\')
# 获取课程主页的窗口句柄 (通过窗口句柄来找到浏览器窗口)
selenium_index = driver.current_window_handle

sleep(2)
driver.find_element_by_partial_link_text(\'4-14\').click()
sleep(2)
#切换到主页窗口
driver.switch_to.window(selenium_index)
sleep(2)
driver.find_element_by_partial_link_text(\'4-15\').click()
sleep(2)

driver.quit()

 

#encoding=utf-8
import unittest
import time
import chardet
from selenium import webdriver

class VisitSogouByIE(unittest.TestCase):

    def setUp(self):
        # 启动chrome浏览器
        self.driver = webdriver.Chrome()

    def test_operateWindowHandle(self):
        url = "http://www.baidu.com"
        self.driver.get(url)
        # 获取当前窗口句柄
        now_handle = self.driver.current_window_handle
        # 打印当前获取的窗口句柄
        print(now_handle)
        # 百度搜索输入框中输入“selenium”
        self.driver.find_element_by_id("kw").send_keys("w3cschool")
        # 点击搜索按钮
        self.driver.find_element_by_id("su").click()
        # 导入time包
        import time
        # 等待3秒,以便网页加载完成
        time.sleep(3)
        # 点击w3school在线教育链接
        self.driver.find_element_by_xpath(\'//*[@id="2"]/h3/a\').click()
        time.sleep(5)
        # 获取所有窗口句柄
        all_handles = self.driver.window_handles
        print("++++", self.driver.window_handles[-1])
        # 循环遍历所有新打开的窗口句柄,也就是说不包括主窗口
        for handle in all_handles:
            if handle != now_handle:
                # 切换窗口
                self.driver.switch_to.window(handle)
                # 点击HTML5链接
                self.driver.find_element_by_link_text(\'HTML5\').click()
                time.sleep(3)
                # 关闭当前的窗口
                self.driver.close()
        time.sleep(3)
        # 打印主窗口句柄
        print(now_handle)
        # 返回主窗口
        self.driver.switch_to.window(now_handle)
        time.sleep(2)
        self.driver.find_element_by_id("kw").clear()
        self.driver.find_element_by_id("kw").send_keys(u"光荣之路自动化测试培训")
        self.driver.find_element_by_id("su").click()
        time.sleep(5)


    def tearDown(self):
        # 退出IE浏览器
        self.driver.quit()

if __name__ == \'__main__\':
    unittest.main()

3. 警告弹框的处理 

     在页面上操作中有事会遇到JS所生成的alert、confirm、以及prompt弹框,可以使用switch_to.alert()定位到,然后使用text/accept/dismiss/send_keys等方法进行操作

  • div : 也是一个弹框,但是上面会有一个复杂的操作,比如百度首页->登录的弹框
  • alert: 简单的弹框,一般只有确定和取消按钮,   比如在console中输入 window.alert(\'你好呀\')
  • window: 新的窗口,  比如百度首页点击新闻打开一个新的窗口

     操作alert的常用方法:

  • switch_to.alert() : 获取当前页面上的警告框
  • text:返回alert、confirm、以及prompt的文字信息
  • accept(): 接受现有的警告框
  • dismiss():取消现有的告警框
  • send_keys(keysToSend): 方文本到警告框

     代码示范:https://github.com/fanpl-sourse/all_study_practice/blob/master/myUIautotest/test_frame.py

  案例:点击百度首页设置按钮,然后进入搜索设置页面,点击保存设置恢复默认按钮,处理警告弹窗窗口

#/usr/bin python
#-*- coding:UTF-8 -*-
#####################警告弹窗处理#####################
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get(\'https://www.baidu.com/\')

##点击设置按钮
driver.find_element_by_link_text(\'设置\').click()
sleep(2)
##点击搜索设置按钮
# driver.find_element_by_link_text(\'搜索设置\').click()
driver.find_element_by_class_name(\'setpref\').click()  #这个元素在火狐浏览器定位更清晰一些
sleep(3)

##点击保存设置
# driver.find_element_by_css_selector(\'.prefpanelgo\').click()
##点击恢复设置
driver.find_element_by_link_text(\'恢复默认\').click()
sleep(2)

##处理警告窗口
alert = driver.switch_to.alert.accept()
sleep(2)
driver.quit()

 

4. 上传文件

input标签可以直接使用send_keys(本地文件地址)上传文件

用法:

  • e = driver.find_element(By.XPATH,"上传按钮XPATH")
  • e.send_keys(\'文件路径+文件名\')
#/usr/bin python
#-*- coding:UTF-8 -*-
####################上传文件####################
from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
driver.get(\'https://www.baidu.com/\')

driver.find_element_by_css_selector(".soutu-btn").click()
sleep(3)
driver.find_element_by_css_selector(".upload-pic").send_keys(r"E:\study\python\我要自学网-python+selenium\脚本与课件\4-22~4-32 Script\shuiyin.png")
sleep(3)
driver.quit()

 5. 执行js脚本

5.1 js简介

     selenium能执行js,使得selenium拥有更强大的能力,既然能执行js,那么js能做的事情,selenium大部分也可以做

  •     直接使用js操作页面,能解决很多click()不生效的问题
  •     页面滚动到底部,顶部
  •     处理富文本,时间控件的输入

5.2  js用法

    js代码示例

      windows.alert(\'弹出一个框\')  : 在当前页面弹出一个框

      document.title:获取当前页面的标题

      json.stringify(performance.timing) : 获取当前页面的性能数据

      a = document.getElementById(\'kw\').value

      document.documentElement.scroll=10000   :  滚动到页面底部

        

5.3 selenium调用js

  • execute_script() : 执行js               
  • return: 可以返回js的返回结果        
  • execute_script: arguments传参

      driver.execute_script(\'windows.alert("谈个框")\')

      driver.execute_script(a = document.getElementById(\'kw\').value)

      driver.execute_script(\'return document.getElementById(\'kw\').value\')

 场景一: 页面元素太多需要滑倒底部进行查看

    滚动条操作控制 

  案例:打开我要自学网页面,然后将滚动条拖到最底部,然后再拖到顶部

#/usr/bin python
#-*- coding:UTF-8 -*-
####################滚动条####################

from selenium import webdriver
from time import sleep

driver = webdriver.Chrome()
# driver.get(\'https://www.baidu.com/\')  网址由51自学改为 百度
driver.get("http://www.baidu.com/")
sleep(2)
#将滚动调拖到最底部
js="var action=document.documentElement.scrollTop=10000"
driver.execute_script(js)
sleep(3)

#将滚动条拖到最顶部
js="var action=document.documentElement.scrollTop=0"
driver.execute_script(js)
sleep(3)

driver.quit()

一般用到操作滚动条的会两个场景:

  •   注册时的法律条文的阅读,判断用户是否阅读完成的标准是:滚动条是否拉到最下方。
  •   要操作的页面元素不在视觉范围,无法进行操作,需要拖动滚动条。

用于标识滚动条位置的代码

……
<body onload= "document.body.scrollTop=0 ">
<body onload= "document.body.scrollTop=100000 "> ……

document.body.scrollTop网页被卷去的高。scrollTop 设置或获取滚动条与最顶端之间的距离。如果想让滚动条处于顶部,那么可以设置 scrollTop 的值为 0,如果想让滚动条处于最底端,可以将这个值设置的足够大,大个窗口的高度即可。scrollTop 的值以像素为单位。

#将页面滚动条拖到底部
js="var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)
sleep(3)

#将滚动条移动到页面的顶部
js_="var q=document.documentElement.scrollTop=0"
driver.execute_script(js_)
sleep(3)

    场景二:时间控件

      大部分时间控件是readonly属性,需要手动选择对应的时间,手工测试很容易做到,自动化中对控件的操作可以用js来实现

      操作思路:

  •  取消日期的readonly属性
  •  给value赋值
  • 写js代码来实现以上两点,再webdriver对js处理

      

# -*- coding: utf-8 -*-
# @Time    : 2020/10/21 10:00
# @Author  : 饭盆里
# @File    : test_js.py
# @Software: PyCharm
# @desc    : js相关操作
from time import sleep

from selenium import webdriver
from selenium.webdriver import TouchActions
from selenium.webdriver.common.by import By


class TestJs():
    def setup(self):
        option = webdriver.ChromeOptions()
        option.add_experimental_option(\'w3c\',False)
        self.driver = webdriver.Chrome(options=option)

    def teardown(self):
        self.driver.quit()

    def test_js_scroll(self):
        self.driver.get(\'https://www.baidu.com/\')
        searchelement = self.driver.find_element(By.ID,\'kw\')
        searchelement.send_keys(\'selenium官网\')
        self.driver.find_element(By.ID,\'su\').click()
        sleep(2)

        """
        # 功能同js
        action = TouchActions(self.driver)
        action.scroll_from_element(searchelement,0,10000)
        action.perform()
        sleep(2)
        """
        js = \'document.documentElement.scroll=10000\'
        self.driver.execute_script(js)

        self.driver.find_element(By.XPATH,\'//*[@id="page"]//a[last()]\').click()
        sleep(2)

    def test_js_time(self):
        """
        对时间控件进行赋值
        :return:
        """
        self.driver.get(\'https://www.12306.cn/index/\')
        sleep(2)
        js = \'a = document.getElementById("train_date"), a.value = "2020-10-06"\'

        self.driver.execute_script(js)

        sleep(2)

定位不到的4个原因:
1. 层级没找对,             解决办法:从上一个层级进行定位,一层一层定

 

2.没等加载出来就定位,解决办法:sleep(2)
3.嵌套了iframe               解决办法:switch_to_frame()

4.动态生成的        

6. 多浏览器

import os
from time import sleep
from selenium import webdriver

class Test_browser():
    def setup(self):
        browser = os.getenv(\'browser\')
        if browser == \'firefox\':
            self.driver = webdriver.Firefox()
        elif browser == \'headless\':
            self.driver = webdriver.PhantomJS()
        else:
            self.driver = webdriver.Chrome()
        self.driver.maximize_window()
        self.driver.implicitly_wait(5)

    def teardown(self):
        self.driver.quit()

    def test_baidu(self):
        self.driver.get(\'https://www.baidu.com/\')
        sleep(2)

命令行运行:browser=\'Chrome\' pytest test_browser.py