Skip to content

使用 Python 构建UI自动化脚本

颜色处理篇

py
import pyautogui


def compare_color(color1: tuple[int, int, int], color2: tuple[int, int, int], sim: float) -> bool:
    """
    对比两个BGR颜色
    """
    ar = color1[2]
    ag = color1[1]
    ab = color1[0]

    br = color2[2]
    bg = color2[1]
    bb = color2[0]

    fz = 10000 - sim * 10000
    return ((ar - br) * (ar - br) + (ag - bg) * (ag - bg) + (ab - bb) * (ab - bb)) <= fz


def cv_color(color: str) -> tuple[int, int, int]:
    b = int(color[0:2], 16)
    g = int(color[2:4], 16)
    r = int(color[4:6], 16)
    return b, g, r


def get_color(x: int, y: int, screen=None, ) -> tuple[int, int, int]:
    """
    返回CV图像指定坐标的颜色(BGR)
    """
    if screen is None:
        rgb = pyautogui.pixel(x, y)
        return rgb[2], rgb[1], rgb[0]
    else:
        return screen[y, x]


def is_color(pos: tuple[int, int], color: str, sim: float, screen=None, ) -> bool:
    """
    颜色判定
    :param screen:截图
    :param pos:坐标(x,y)
    :param color:颜色
    :param sim:相似度
    """
    screen_color = get_color(pos[0], pos[1], screen)
    return compare_color(cv_color(color), screen_color, sim)

图像匹配篇(opencv)

py
import cv2
import numpy
import pyautogui


def image_search(template, mask = None):
    target = pyautogui.screenshot()
    target = numpy.array(target)
    target = cv2.cvtColor(target, cv2.COLOR_RGB2BGR)

    # 获得模板图片的高宽尺寸
    t_height, t_width = template.shape[:2]

    # 执行模板匹配,采用的匹配方式cv2.TM_SQDIFF_NORMED
    result = cv2.matchTemplate(target, template, cv2.TM_SQDIFF_NORMED, mask=mask)
    # 归一化处理
    # cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
    # 寻找矩阵(一维数组当做向量,用Mat定义)中的最大值和最小值的匹配结果及其位置
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
    # 匹配值转换为字符串
    # 对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趋近与0匹配度越好,匹配位置取min_loc
    # 对于其他方法max_val越趋近于1匹配度越好,匹配位置取max_loc
    str_min_val = str(min_val)
    # 绘制矩形边框,将匹配区域标注出来
    # min_loc:矩形定点
    # (min_loc[0]+t_width,min_loc[1]+t_height):矩形的宽高
    # (0,0,225):矩形的边框颜色;2:矩形边框宽度
    # cv2.rectangle(target, min_loc, (min_loc[0] + t_width, min_loc[1] + t_height), (0, 0, 225), 2)
    # cv2.imshow("MatchResult----MatchingValue=" + str_min_val, target)
    # cv2.waitKey()
    return min_loc, min_val

按键监听篇

鼠标

py
from pynput import mouse


# 鼠标click监听
def on_click(x, y, button, pressed):
    # print(f'Click position: ({x}, {y})')
    if pressed:
        print(f'Click button: {button}')
    # print(f'Click state: {"Pressed" if pressed else "Release"}')


with mouse.Listener(on_click=on_click) as listener:
    listener.join()

键盘

py
def on_press(key):
    if hasattr(key, 'char'):
        pass
    elif key == k.Key.esc:
        pass

with k.Listener(on_press=on_press) as listener:
    listener.join()

记一种线程强制中断方式

py
def _async_raise(tid, exctype):
    """raises the exception, performs cleanup if needed"""
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        # """if it returns a number greater than one, you're in trouble,
        # and you should call it again with exc=NULL to revert the effect"""
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")


def stop_thread(thread):
    try:
        _async_raise(thread.ident, SystemExit)
    except SystemError:
        pass

关于 pyautogui 按键延迟的问题

可通过 PAUSE 调整按键之间的延迟。

py
pyautogui.PAUSE = 0

最后编辑时间:

Version 4.1 (framework-1.1.4)