IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> selenium之关于截图元素定位及只截取元素讲解 -> 正文阅读

[开发测试]selenium之关于截图元素定位及只截取元素讲解

一、前言

关于截取元素,这边有一个坑在mac,mac默认是二倍截图保存,会导致你元素定位没错,初始截图没错,但是在截取元素的时候老是截取不到你要的元素图,虽然网上有类似将坐标乘以2,同样放大两倍的方法去截取,但是如果在你不知道分别率被放大多少倍的时候,你又该如何去解决这个问题呢?下面有这方便的讲解

二、实战

1、mac的二倍截图问题解决代码

# coding:utf-8
from selenium import webdriver
from PIL import Image

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

driver.save_screenshot('button.png')
element = driver.find_element_by_id("su")
print(element.location)                # 打印元素坐标
print(element.size)                    # 打印元素大小

left = element.location['x'] * 2
top = element.location['y'] * 2
right = (element.location['x'] + element.size['width']) * 2
bottom = (element.location['y'] + element.size['height']) * 2


im = im.crop((left, top, right, bottom))
im.save('button.png')

这个是我们查了很多资料,知道二倍截图问题时候解决的问题,但是在我们不知道分别率是否被放大的时候,我们又该怎么办?

2、计算倍放大的分辨率倍数,再截取元素

# coding:utf-8
from selenium import webdriver
from PIL import Image
driver = webdriver.Chrome()
width = driver.get_window_size().get("width")
print(width)
driver.get('http://www.baidu.com/')

driver.save_screenshot('button.png')
element = driver.find_element_by_id("su")
print(element.location)                # 打印元素坐标
print(element.size)                    # 打印元素大小

left = element.location['x']
top = element.location['y']
right = (element.location['x'] + element.size['width'])
bottom = (element.location['y'] + element.size['height'])

im = Image.open('button.png')
i = im.size
p = i[0]
n = p / width
im = im.crop((left*n, top*n, right*n, bottom*n))
im.save('button.png')

这样就能截取到你想要的截图了:

3、如何截取高亮元素

def highlight(element, element_name=None, debug=True):
        '''
        debug 参数用来开关截图功能
        '''
    # 高亮元素
    def apply_style():
        driver.execute_script("arguments[0].style.border='6px solid red'", element)

    # 截图
    def screen_shot(screen_name):
        driver.save_screenshot(screen_name)

    if debug:
        try:
            screen_shot(str(element_name) + '_before.jpg')
            apply_style()
            screen_shot(str(element_name) + '_after.jpg')
        except Exception as e:
            return e

    apply_style()

?编写测试代码执行后的结果:

4、这边一个小插曲,就是我们在查找元素和判断元素是否存在的时候会比较麻烦,我们现在在这边做一个小封装:

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait



#  方法一,用 try...except...
def is_element_exsist(driver, locator):
    '''
    判断元素是否存在,存在返回 True,不存返回 False
    :param locator: locator 为元组类型,如("id", "yy") :return: bool 值,True or False
    '''
    try:
        driver.find_element(*locator)
        return True
    except Exception as msg:
        print("元素%s 找不到:%s" % (locator, msg))
        return False


# 方法二:用 elements 定义一组元素方法
def is_element_exsist1(driver, locator):
    '''
    判断元素是否存在,存在返回 True,不存返回 False
    :param locator: locator 为元组类型,如("id", "yy") :return: bool 值,True or False
    '''
    eles = driver.find_elements(*locator)
    if len(eles) < 1:
        return False
    else:
        return True


# 方法三,用WebDriverWait 和 expected_conditions
def is_element_exsist2(driver, locator):
    '''
    结合 WebDriverWait 和 expected_conditions 判断元素是否存在, 每间隔 1 秒判断一次,30s 超时,
    存在返回 True,不存返回 False :param locator: locator 为元组类型,
    如("id", "yy") :return: bool 值,True or False
    '''
    try:
        WebDriverWait(driver, 30, 1).until(EC.presence_of_element_located(locator))
        return True
    except:
        return False


# 查看元素的方法
def find(driver, locator, timeout=30):
    '''定位元素,参数 locator 是元祖类型, 如("id", "yy")'''
    element = WebDriverWait(driver, timeout, 1).until(EC.presence_of_element_located(locator))

?5、现在我们要做的是,竟然截屏标记元素和截取元素都完成了,我们是否可以将这两种截取元素的定位方法合并,并做开发在后台配置,下面就是我要处理的问题,以及看看我是怎么处理的:

5.1 先在config.yaml配置文件中做一个开关控制:

screenshot:
  is_highlight_ele_screenshot: True
  is_screenshot_ele: True

5.2 然后就可以在until中新建一个elementOperate.py,然后开始我们的封装和实现:

# -*- coding: utf-8 -*-

"""
@author: lucas
@Function:
@file: elementOperate.py
@time: 2021/10/17 3:42 下午
"""
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

import time
import os
from selenium import webdriver
from utils.config import REPORT_PATH, Config
from PIL import Image


#  方法一,用 try...except...
def is_element_exsist(driver, locator):
    '''
    判断元素是否存在,存在返回 True,不存返回 False
    :param locator: locator 为元组类型,如("id", "yy") :return: bool 值,True or False
    '''
    try:
        driver.find_element(*locator)
        return True
    except Exception as msg:
        print("元素%s 找不到:%s" % (locator, msg))
        return False


# 方法二:用 elements 定义一组元素方法
def is_element_exsist1(driver, locator):
    '''
    判断元素是否存在,存在返回 True,不存返回 False
    :param locator: locator 为元组类型,如("id", "yy") :return: bool 值,True or False
    '''
    eles = driver.find_elements(*locator)
    if len(eles) < 1:
        return False
    else:
        return True


# 方法三,用WebDriverWait 和 expected_conditions
def is_element_exsist2(driver, locator):
    '''
    结合 WebDriverWait 和 expected_conditions 判断元素是否存在, 每间隔 1 秒判断一次,30s 超时,
    存在返回 True,不存返回 False :param locator: locator 为元组类型,
    如("id", "yy") :return: bool 值,True or False
    '''
    try:
        WebDriverWait(driver, 30, 1).until(EC.presence_of_element_located(locator))
        return True
    except:
        return False


# 查看元素的方法
def find(driver, locator, timeout=30):
    '''定位元素,参数 locator 是元祖类型, 如("id", "yy")'''
    element = WebDriverWait(driver, timeout, 1).until(EC.presence_of_element_located(locator))
    return element


# 高亮元素
def highlight(driver, element, element_name=None, is_highlight_ele_screenshot=True, is_screenshot_ele=True):
    '''
    :param driver: 浏览器驱动
    :param element: 定位到的元素
    :param element_name: 元素名
    :param is_highlight_ele_screenshot: 是否要带有高亮元素的截屏,默认True是要,Flase是不要
    :param is_screenshot_ele: 是否要截取元素的图,默认True是要,Flase是不要
    :return: 预期的截屏图
    '''
    day = time.strftime('%Y%m%d', time.localtime(time.time()))
    screenshot_path = REPORT_PATH + '/screenshot_%s' % day
    tm = time.strftime('%H%M%S', time.localtime(time.time()))

    # 高亮元素
    def apply_style():
        driver.execute_script("arguments[0].style.border='6px solid red'", element)

    # 截图
    def screen_shot(screen_name):
        driver.maximize_window()
        if not os.path.exists(screenshot_path):
            os.makedirs(screenshot_path)
        filename = screenshot_path + '/%s_%s.png' % (screen_name, tm)
        driver.save_screenshot(filename)
        return filename

    # 截取元素
    def screenshot_element(file_name):
        # 获取初始截屏的分辨率宽度
        width = driver.get_window_size().get("width")
        # 获取元素坐标
        left = element.location['x']
        top = element.location['y']
        right = (element.location['x'] + element.size['width'])
        bottom = (element.location['y'] + element.size['height'])
        im = Image.open(file_name)
        # 获取图片宽度
        p = im.size[0]
        # 计算被放大的分辨率倍数
        n = p / width
        # 截取元素坐标
        im = im.crop((left * n, top * n, right * n, bottom * n))
        # 保存截取元素的截图
        im.save(screenshot_path + "/" + str(element_name) + '元素.png')

    if is_highlight_ele_screenshot:
        try:
            # 打开浏览器前的全屏截图
            screen_shot(str(element_name) + '_before')
            apply_style()
            # 高亮元素后的全屏截图
            file_name = screen_shot(str(element_name) + '_after')
            if is_screenshot_ele:
                # 截取的高亮元素图
                screenshot_element(file_name)
        except Exception as e:
            return e

    apply_style()


if __name__ == '__main__':
    # 读取配置文件控制截屏需求
    screenshot = Config().get('screenshot')
    is_open_1 = screenshot.get('is_highlight_ele_screenshot')
    is_open_2 = screenshot.get('is_screenshot_ele')
    # 启动驱动,打开浏览器地址
    driver = webdriver.Chrome()
    driver.get('http://www.baidu.com/')
    locator = ('id', 'su')
    # 判断元素是否存在
    exsist = is_element_exsist2(driver, locator)
    print("是否存在元素:", exsist)
    # 查找元素
    element = find(driver, locator, timeout=10)
    # 获取满足你需求的截图
    highlight(driver, element, 'su', is_open_1, is_open_2)
    driver.close()

我这边为了方便定位问题和查看元素的时间,我在截图的时候会带上文件夹和时间标识做区分,上面关于截图高亮元素全屏和截取高亮元素我的开关是全部打开了,查看下效果:

再看下截图的结果:

?

5.3 基于上述封装有个不好的地方就是每次执行一个函数都要启动一次驱动,极耗性能,所以我对方法做了改良:

# -*- coding: utf-8 -*-

"""
@author: lucas
@Function:
@file: browser.py
@time: 2021/9/10 4:53 下午
"""
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
import time
import os
from selenium import webdriver
from utils.config import REPORT_PATH, Config, DRIVER_PATH
from PIL import Image

# 可根据需要自行扩展
# 火狐浏览器驱动路径
FIREFOX_PATH = DRIVER_PATH + '/geckodriver'
# 谷歌浏览器驱动路径
CHROMEDRIVER_PATH = DRIVER_PATH + '/chromedriver'

TYPES = {'firefox': webdriver.Firefox, 'chrome': webdriver.Chrome}
EXECUTABLE_PATH = {'firefox': FIREFOX_PATH, 'chrome': CHROMEDRIVER_PATH}
day = time.strftime('%Y%m%d', time.localtime(time.time()))
screenshot_path = REPORT_PATH + '/screenshot_%s' % day
tm = time.strftime('%H%M%S', time.localtime(time.time()))


class UnSupportBrowserTypeError(Exception):
    pass


class Browser(object):
    def __init__(self, browser_type='firefox'):
        self._type = browser_type.lower()
        if self._type in TYPES:
            self.browser = TYPES[self._type]
        else:
            raise UnSupportBrowserTypeError('仅支持%s!' % ', '.join(TYPES.keys()))
        self.driver = None

    def get(self, url, maximize_window=True, implicitly_wait=30):
        self.driver = self.browser(executable_path=EXECUTABLE_PATH[self._type])
        self.driver.get(url)
        if maximize_window:
            self.driver.maximize_window()
        self.driver.implicitly_wait(implicitly_wait)
        return self

    # 查看元素
    def find(self, locator, timeout=30):
        '''定位元素,参数 locator 是元祖类型, 如("id", "yy")'''
        element = WebDriverWait(self.driver, timeout, 1).until(EC.presence_of_element_located(locator))
        return element

    # 是否存在元素
    def is_element_exsist2(self, locator):
        try:
            self.find(locator, timeout=30)
            return True
        except:
            return False

    # 截屏
    def screen_shot(self, screen_name):
        self.driver.maximize_window()

        if not os.path.exists(screenshot_path):
            os.makedirs(screenshot_path)
        filename = screenshot_path + '/%s_%s.png' % (screen_name, tm)
        self.driver.save_screenshot(filename)
        return filename

    # 截取元素
    def screenshot_element(self, element, element_name, file_name):
        # 获取初始截屏的分辨率宽度
        width = self.driver.get_window_size().get("width")
        # 获取元素坐标
        left = element.location['x']
        top = element.location['y']
        right = (element.location['x'] + element.size['width'])
        bottom = (element.location['y'] + element.size['height'])
        im = Image.open(file_name)
        # 获取图片宽度
        p = im.size[0]
        # 计算被放大的分辨率倍数
        n = p / width
        # 截取元素坐标
        im = im.crop((left * n, top * n, right * n, bottom * n))
        # 保存截取元素的截图
        print(str(element))
        im.save(screenshot_path + "/" + str(element_name) + '元素.png')

    # 高亮元素
    def highlight(self, element, element_name=None, is_highlight_ele_screenshot=True, is_screenshot_ele=True):
        '''
        :param element: 定位到的元素
        :param element_name: 元素名
        :param is_highlight_ele_screenshot: 是否要带有高亮元素的截屏,默认True是要,Flase是不要
        :param is_screenshot_ele: 是否要截取元素的图,默认True是要,Flase是不要
        :return: 预期的截屏图
        '''

        # 高亮元素
        def apply_style():
            self.driver.execute_script("arguments[0].style.border='6px solid red'", element)

        # 截图
        if is_highlight_ele_screenshot:
            try:
                # 打开浏览器前的全屏截图
                self.screen_shot(element_name + '_before')
                apply_style()
                # 高亮元素后的全屏截图
                file_name = self.screen_shot(str(element_name) + '_after')
                if is_screenshot_ele:
                    # 截取的高亮元素图
                    self.screenshot_element(str(element_name), file_name)
            except Exception as e:
                return e

        apply_style()

    def close(self):
        self.driver.close()

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


if __name__ == '__main__':
    # 读取配置文件控制截屏需求
    screenshot = Config().get('screenshot')
    is_open_1 = screenshot.get('is_highlight_ele_screenshot')
    is_open_2 = screenshot.get('is_screenshot_ele')
    b = Browser('chrome').get('http://www.baidu.com')
    locator = ('id', 'su')
    exsist = b.is_element_exsist2(locator)
    print("是否存在元素:", exsist)
    # 查找元素
    element = b.find(locator, timeout=10)
    print(element)
    b.highlight(element, 'su', is_open_1, is_open_2)
    b.quit()

最后效果同上

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-10-20 12:47:09  更:2021-10-20 12:47:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 2:49:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码