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

一、前言

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

思考:怎么使用程序自动化截图
查资料:
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/129197537PyAutoGUI实现对LoadRunner报告自动化截图_第2张图片

坐标的距离通过像素计算,如果你的屏幕分辨率是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中。
鼠标移动到左上角,程序中断。
PyAutoGUI实现对LoadRunner报告自动化截图_第3张图片

PyAutoGUI实现对LoadRunner报告自动化截图_第4张图片
踩坑
开始编写代码移动鼠标,运行鼠标没有反应,百度后是权限问题。要管理员身份运行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

你可能感兴趣的:(python,自动化,运维)