PyAutoGUI实现对LoadRunner报告自动化截图

news2024/11/16 5:32:08

一、前言

对系统压测后,需要编写汇总报告。LoadRunner场景生成的Analysis报告,要截图保存部分图片。
每次几个功能,每个功能几个并发场景,每个场景有4张左右图片。太多重复性工作了,费时费力。

思考:怎么使用程序自动化截图
查资料:
pynput、pygetwindow和pyautogui是Python中用于鼠标和键盘控制的三个不同的库。
pynput库:提供了控制键盘和鼠标的功能。它可以监听和控制键盘的按键事件,以及移动鼠标和执行鼠标点击操作。它的特点是灵活性和控制选项更多,可以实现对键盘和鼠标的高级操作。
pygetwindow库:提供了管理和控制窗口的功能。它可以获取当前打开的窗口列表,并提供对窗口的操控和属性获取。它的特点是可以通过窗口的标题等属性来查找和操作指定的窗口。
pyautogui库:是一个自动化测试工具,用于模拟鼠标、键盘和屏幕的操作。它可以控制鼠标的移动、点击和拖放,模拟键盘按键和组合键,并可以对屏幕截图、识别图像等。它的特点是简单易用,适合于自动化任务和GUI测试。
最终选择了pyautogui,满足点击、截图等需求。

二、学习使用pyautogui库

查询pyautogui库方面的文章:
https://blog.csdn.net/hfy1237/article/details/127960423
https://blog.csdn.net/m0_57236802/article/details/129197537在这里插入图片描述

坐标的距离通过像素计算,如果你的屏幕分辨率是1920 x 1080,右下角的像素将是1919, 1079(因为坐标从0开始,而不是1)。

常用函数列表
函数名功能
基本pyautogui.size()返回包含分辨率的元组
pyautogui.PAUSE每个函数的停顿时间,默认0.1s
pyautogui.FAILSAFE是否开启防故障功能,默认True
键盘pyautogui.press('键盘字符')按下并松开指定按键
pyautogui.keyDown('键盘字符')按下指定按键
pyautogui.keyUp('键盘字符')松开指定按键
pyautogui.hotkey('键盘字符1', '键盘字符2')按下多个指定键
鼠标pyautogui.position()返回当前鼠标当前位置的元组
pyautogui.moveTo(x,y,duration=1)   按绝对位置移动鼠标并设置移动时间
pyautogui.moveRel(x_rel,y_rel,duration=4)  按相对位置移动鼠标并设置移动时间
pyautogui.dragTo(x, y, duration=1)   按绝对位置拖动鼠标并设置移动时间
pyautogui.dragRel(x_rel, y_rel, duration=4)  按相对位置拖动鼠标并设置移动时间
pyautogui.click(x, y) 鼠标点击指定位置,默认左键
pyautogui.click(x, y, button='left')鼠标单击左键
pyautogui.click(x, y, button='right')鼠标单击右键
pyautogui.click(x, y, button='middle')  鼠标单击中间,即滚轮
pyautogui.doubleClick(10,10) 鼠标左键双击指定位置
pyautogui.rightClick(10,10)鼠标右键双击指定位置
pyautogui.middleClick(10,10) 鼠标中键双击指定位置
pyautogui.scroll(10) 鼠标滚轮向上滚动10个单位

press(), keyDowm(),keyUp(),hotKey()支持的有效字符串列表如下:

类别
字母'a', 'b', 'c', 'd', 'e','f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
数字'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
符号'\t', '\n', '\r', ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', , ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~',
F键'f1', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20', 'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',
数字键盘'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6', 'num7', 'num8', 'num9', 
其他'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace', 'browserback', 'browserfavorites', 'browserforward', 'browserhome', 'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear', 'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete', 'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja', 'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail', 'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack', 'nonconvert', , 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn', 'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn', 'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator', 'shift', 'shiftleft', 'shiftright', 'sleep', 'space', 'stop', 'subtract', 'tab', 'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen', 'command', 'option', 'optionleft', 'optionright'

三、实现

需求:一个文件夹内有很多Analysis报告,需要打开每一个报告,对summary report、Hits per Second、Average Transaction Response Time、Transactions per Second等页面进行截图保存。
思路
1、获取文件夹内Analysis报告的路径
2、打开Analysis软件
3、打开指定报告
4、截图、保存
5、重复3、4过程
6、关闭软件
实现

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import pyautogui
import pyperclip    #复制粘贴 文本复制到剪贴板
import subprocess   #管理子进程
import time
import os
import sys
import re
from PIL import Image
'''
功能:输入路径,扫描路径下2级目录中.lra文件,打开文件进行指定页面截图操作,截图保存在\image中。
设置:max_depth=2设置扫描目录深度,报告要默认有summary report、Hits per Second、Average Transaction Response Time页面,
    没有Transactions per Second页面可以新增。
    页面按钮位置与显示器分辨率有关,在cut()中调整。待匹配图片必须使用pyautogui.screenshot截取,才能匹配到。

'''

# pyautogui.screenshot('sa.png', region=(490,630,760,30)) #截取图标left,top,width,height
# sys.exit()

class lr_cut():

    def __init__(self,folder_path):
        '''
        获取报告路径、名称
        '''
        self.folder_path=folder_path                        # 设置报告文件夹路径
        max_depth=2                                         # 设置遍历文件深度
        self.file_paths=[]                                  # 全部报告路径
        self.file_names=[]                                  # 全部报告名称
        self.file_name=''                                   # 当前报告名称
        self.image_number=0                                 # 已截图报告数量
        for root, dirs, files in os.walk(folder_path, topdown=True):    # 遍历文件夹及其子文件夹中的.lra文件
            depth=root[len(folder_path):].count(os.sep)
            if depth > max_depth:                           # 深度超过限制,不继续递归
                del dirs[:]
            for file in files:
                if file.endswith('.lra'):                   # 条件筛选.lra
                    file_path=os.path.join(root, file)
                    self.file_paths.append(file_path)
        self.count=len(self.file_paths)                     # 统计报告数量
        if self.count == 0:
            print('扫描完成----------没有发现.lra格式的Analysis文件')
            sys.exit()                                      # 没有发现报告,程序退出
        else:
            print(f'扫描完成----------发现{self.count}个Analysis文件')
            pattern=r'[^\\]+(?=\.lra$)'                     # 提取路径中报告名称
            for file_path in self.file_paths:
                match=re.search(pattern, file_path)
                file_name=match.group()
                self.file_names.append(file_name)


    def number_one(self):
        '''
        打开软件,窗口最大化,截图
        '''
        # 打开LoadRunner软件(两种方式)
        # pyautogui.press('win')                            #[1]win搜索Analysis
        # pyautogui.typewrite('Analysis', 0.1)
        # pyautogui.press('enter')
        # pyautogui.press('enter')
        subprocess.Popen(['start', '', self.file_paths[0]], shell=True)  # [2]确保文件关联的程序能够正确打开.lra文件

        time.sleep(9)                                       # 等待LoadRunner启动
        self.file_name=self.file_names[0]                   # 文件名称

        screen_width, screen_height=pyautogui.size()        # 获取屏幕尺寸
        move_distance_x=screen_width // 2
        move_distance_y=screen_height // 2
        pyautogui.click(move_distance_x, move_distance_y)   # 确保文件打开窗口获得焦点
        pyautogui.hotkey('win', 'up')                       # 最大化窗口
        # pyautogui.hotkey('alt', 'space')
        # pyautogui.press('x')
        time.sleep(1)
        self.cut()


    def number_two(self,number):
        '''
        第二次打开文件(软件内打开文件),截图
        '''
        pyautogui.hotkey('ctrl', 'o')
        pyperclip.copy(self.file_paths[number])         # 将路径复制到剪贴板
        time.sleep(1)
        pyautogui.hotkey('ctrl', 'v')                   # 粘贴路径       绕过无法输入中文路径的问题
        pyautogui.press('enter')
        time.sleep(3)
        self.file_name=self.file_names[number]
        self.cut()


    def cut(self):
        '''
        对文件截图,保存在\image中。
        截图命名:报告名称-截图页面.png
        summary report界面匹配事务行数,调整截图高度
        tps截图时,没有tps则添加
        '''
        pyautogui.click(115, 150)  # 点击summary report 截图
        time.sleep(1)
        button_1=pyautogui.locateCenterOnScreen('sa.png', grayscale=True)   #匹配事务行数
        x, y=button_1
        y-=640
        k=351 + y
        name=f'image\\{self.file_name}-summary.png'
        pyautogui.screenshot(name, region=(488, 225, 762, k))       # 截图    每行高度20
        self.resize_screenshot(name)

        pyautogui.click(110, 200)  # 点击Hits per Second 截图
        time.sleep(1)
        name=f'image\\{self.file_name}-Hits.png'
        pyautogui.screenshot(name, region=(480, 100, 1412, 521))    # 截图
        self.resize_screenshot(name)

        k=521 + y
        pyautogui.click(165, 246)  # 点击Average Transaction Response Time 截图
        time.sleep(1)
        name=f'image\\{self.file_name}-Average.png'
        pyautogui.screenshot(name, region=(480, 100, 1412, k))      # 截图
        self.resize_screenshot(name)

        # tps截图,没有tps则添加
        button_position=pyautogui.locateCenterOnScreen('Transactions per Second.png', grayscale=True)  # 定位按钮图片的中心位置
        if button_position == None:
            pyautogui.hotkey('ctrl', 'a')       #添加tps图片
            time.sleep(1)
            button_position2=pyautogui.locateCenterOnScreen('Transactions.png', grayscale=True)
            pyautogui.doubleClick(button_position2)
            time.sleep(1)
            button_position=pyautogui.locateCenterOnScreen('Transactions per Second2.png')
            pyautogui.doubleClick(button_position)
            time.sleep(1)
            pyautogui.hotkey('alt', 'f4')
        pyautogui.click(button_position)
        time.sleep(1)
        name=f'image\\{self.file_name}-tps.png'
        pyautogui.screenshot(name, region=(480, 100, 1412, k))  # 截图
        self.resize_screenshot(name)

        #保存报告
        pyautogui.hotkey('ctrl', 's')
        time.sleep(1)
        self.image_number+=1            #截图报告数统计


    def resize_screenshot(self,name):
        '''
        调整图片大小
        '''
        screenshot=Image.open(name)        # 打开截图
        new_width=696                      # 缩小后的大小
        new_height=348
        resized_screenshot=screenshot.resize((new_width, new_height))       # 缩小截图
        resized_screenshot.save(name)      # 保存缩小后的截图


    def over(self):
        '''
        关闭软件,使用taskkill命令,避免出错后f4关闭其它软件
        '''
        # try:
        #     pyautogui.hotkey('alt', 'f4')
        # except Exception as e:
        #     print(f"pyautogui关闭失败,taskkill强制关闭")
        # finally:
        subprocess.run(["taskkill", "/im", "AnalysisUI.exe", "/f"])  # 使用taskkill命令终止指定的程序。/im参数指定终止程序名称,/f参数强制关闭程序
        print(f'应截报告{self.count}个,已截取报告{self.image_number}个')


    def main(self):
        '''
        1、打开软件,进行第一次截图
        2、在已打开软件内,循环打开文件、截图
        3、关闭软件
        '''
        try:
            self.number_one()
            if self.count > 1:                  # 报告数量>1,循环截图
                for i in range(1, self.count):
                    self.number_two(i)
            else:
                print('报告小于两个,已结束')
        except Exception as e:
            print(f"{self.file_name}--------截取中断:{e.__class__.__name__}")
        finally:
            self.over()



if __name__ == "__main__":
    folder_path = r'C:\Users\feng\Desktop'
    my_instance = lr_cut(folder_path)
    my_instance.main()
    #将鼠标移动到左上角将引发一个 pyautogui.FailSafeException 从而中断程序

效果
所有报告截图,图片存放在\image中。
鼠标移动到左上角,程序中断。
在这里插入图片描述

在这里插入图片描述
踩坑
开始编写代码移动鼠标,运行鼠标没有反应,百度后是权限问题。要管理员身份运行pycharm。

pyautogui.locateCenterOnScreen一直匹配不到按钮截图。百度后发现同样问题,解决方法:不能使用微信等截图工具,要使用pyautogui.screenshot(‘sa.png’, region=(490,630,760,30)),使用pyautogui自带的截图语句,好像是像素点不匹配。

所以要用上面代码的话,要自己根据屏幕分辨率设置点击坐标,重新使用pyautogui.screenshot截取按钮图片。
链接:https://pan.baidu.com/s/1YDy-x9U8sRL0tiza9SNMLA?pwd=a9d6
提取码:a9d6

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/738091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

神码融信金融SBG交付二部VP李先林受邀为第十二届中国PMO大会演讲嘉宾

神码融信金融SBG交付二部VP李先林先生受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;多项目管理的心得体会。大会将于8月12-13日在北京举办&#xff0c;敬请关注&#xff01; 议题简要&#xff1a; 在后疫情时代&#xff0c;金融科技…

pytorch里torch.gather()和torch.Tensor.scatter()解析

torch.Tensor.scatter() 类似 gather 的反向操作&#xff08;gather是读出数据&#xff0c;scatter是写入数据&#xff09;&#xff0c;所以这里只解析torch.gather()。 gather()这个操作在功能上较为反人类&#xff0c;即使某段时间理解透彻了&#xff0c;过了几个月不碰可能又…

【java】LocalDate获取前一天日期

//获取前一天日期//写法一LocalDate yesterday2 LocalDate.now().minusDays(1);System.out.println(yesterday2);//写法二LocalDate yes1 LocalDate.now().plusDays(-1);System.out.println(yes1);//输入当前日期的年 月 日System.out.println(LocalDate.now().getYear());…

基于AidLux的自动驾驶智能预警应用方案

1. 自动驾驶感知算法及AidLux相关方案介绍 1.1自动驾驶 自动驾驶汽车&#xff0c;又称无人驾驶车、电脑驾驶车、无人车、自驾车&#xff0c;是一种需要驾驶员辅助驾驶或者完全不需要操控的车辆。作为自动化载具&#xff0c;自动驾驶汽车可以不需要人类操作即能感知环境及导航…

dvwa靶场通关(九)

第九关&#xff1a;Weak Session IDs&#xff08;弱会话IDs&#xff09; 当用户登录后&#xff0c;在服务器就会创建一个会话(session)&#xff0c;叫做会话控制&#xff0c;接着访问页面的时候就不用登录&#xff0c;只需要携带 Sesion去访问。 sessionID作为特定用户访问站…

领导力指南:高效带领产品设计团队,成就卓越绩效!

产品设计团队负责创造功能性、用户友好性和视觉吸引力的产品。产品设计过程是产品设计师和他们的团队遵循的一系列阶段&#xff0c;以帮助履行他们的角色和责任。在本文中&#xff0c;我们将探讨产品设计团队应该做些什么。 1、定义产品的愿景 创造一个成功产品的第一步是定义产…

prometheus监控Nacos

Nacos监控 &#x1f4da;概述 Nacos 0.8.0版本完善了监控系统&#xff0c;支持通过暴露metrics数据接入第三方监控系统监控Nacos运行状态&#xff0c;目前支持prometheus、elastic search和influxdb&#xff0c;下面结合prometheus和grafana如何监控Nacos&#xff0c;官网gra…

Java设计模式之创建型-单例模式(UML类图+案例分析)

目录 一、基础概念 二、UML类图 三、角色分析 四、案例分析 1、饿汉模式 2、懒汉模式&#xff08;线程不安全&#xff09; 3、懒汉模式&#xff08;线程安全&#xff09; 4、双重检索模式 5、静态内部类 6、枚举 五、总结 一、基础概念 单例模式确保一个类只有一个…

工厂能源管控系统

随着现代工业的发展&#xff0c;工厂能源消耗不断增加&#xff0c;能源成本成为企业生产经营的重要组成部分。为了降低能源消耗、提高生产效率和降低成本&#xff0c;越来越多的企业开始采用工厂能源管控系统。本文将从多个方面介绍工厂能源管控系统的全面内容。 一、工厂能源管…

增值税高,怎么办?节省税款的小技巧必知!

增值税高&#xff0c;怎么办&#xff1f;节省税款的小技巧必知&#xff01; 《税筹顾问》专注于园区招商、企业税务筹划&#xff0c;合理合规助力企业节税&#xff01; 增值税是所有企业必须要去缴纳的一种税种&#xff0c;它对于企业来说十分熟悉。而企业增值税高的问题也不是…

两部搞定Pytorch 安装与配置(小白也能搞定!!!)

Pytorch 安装与配置 NVIDIA系统管理界面查看 nvidia-smi 进入NVIDIA系统管理界面 对应的详细解释看下图 参考博文 (53条消息) nvidia-smi命令详解和一些高阶技巧介绍_Chaos_Wang_的博客-CSDN博客 CUDA 查看 CUDA 有两类&#xff1a;其中一类是驱动API(Driver API)&#xff…

拥抱“Zero ETL”未来,亚马逊云科技助力乐城堡加速数据分析

获得全球三千五百多万用户的认可的移动游戏企业乐城堡希望通过数据分析为游戏业务提供更好的决策支撑。乐城堡在亚马逊云科技上利用Amazon Redshift等服务构建属于自己的云上游戏数据分析平台&#xff0c;实现复杂查询&#xff0c;保证游戏运营人员能快速、近实时地获取所需的数…

Python-opcua 编程(3)历史数据读写

历史数据就是将opcua 信息模型中的某一些变量保存起来&#xff0c;以便Client 端程序能够读取历史数据&#xff0c;作各种数据处理。 Opcua 标准指出历史数据的读写&#xff0c;主要包括&#xff1a; 属性 Historizing 当设置为True 时&#xff0c;该变量支持历史数据读写 …

kafka主题支持路由功能

背景&#xff1a; 我们知道rabbitmq是支持消息路由的功能的&#xff0c;但是当我们统一消息中间件到kafka后&#xff0c;有一些旧的应用依然想要使用消息路由的功能时&#xff0c;我们可以怎么让kafka也支持消息路由的功能呢&#xff1f; 技术实现&#xff1a; 为了不影响ka…

web实现小米商城首页选择内容

一、需求&#xff1a;实现如下图所示的web内容 二、实现结果 三、代码展示 <!DOCTYPE html> <html> <head><title>小米商场</title><style>body {display: flex;flex-direction: column;align-items: center;justify-content: center;he…

阿里云轻量应用服务器使用教程(以建站为例)

阿里云轻量应用服务器怎么使用&#xff1f;阿里云轻量应用服务器使用教程&#xff1a;轻量应用服务器购买、重置密码、远程连接、宝塔面板的Web环境搭建、WordPress网站程序安装到网站上线&#xff0c;阿里云服务器网分享轻量应用服务器从购买、配置建站环境、轻量服务器应用服…

【SLAM】Ceres优化库超详细解析

Ceres是由Google开发的开源C通用非线性优化库&#xff0c;与g2o并列为目前视觉SLAM中应用最广泛的优化算法库。 对于任何一个优化问题&#xff0c;我们首先需要对问题进行建模&#xff0c;之后采用合适的优化方法&#xff0c;进行求解。在求解的过程中&#xff0c;往往需要进行…

用 Nginx 禁止国外 IP 访问我的网站...

先来说说为啥要写这篇文章&#xff0c;之前看了下 Nginx 的访问日志&#xff0c;发现每天有好多国外的 IP 地址来访问我的网站&#xff0c;并且访问的内容基本上都是恶意的。因此我决定禁止国外 IP 来访问我的网站。 想要实现这个功能有很多方法&#xff0c;下面我就来介绍基于…

(动态规划) 132. 分割回文串 II ——【Leetcode每日一题】

❓ 132. 分割回文串 II 难度&#xff1a;困难 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1&#xff1a; 输入&#xff1a;s “aab” 输出&#xff1a;1 解释&#xff1a;只需一次分割就…

Vision Transformer (ViT)介绍

paper&#xff1a;An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 摘要 把transformer直接应用于图像块序列&#xff0c;也可以在图像分类任务上表现很好。通过在大数据集上预训练&#xff0c;然后迁移到中等规模和小规模数据集上&#xff0c;…