python记录鼠标键盘操作自动执行重复工作

2023-10-29

系列文章目录


前言

github项目原地址

这个仓库仅是用来学习的, 项目不是个人写的!!!!!!!

1、记录用户的鼠标键盘操作,通过触发按钮自动执行之前记录的操作,可设定执行的次数。
2、在进行某些操作简单、单调重复的工作时,使用本软件就可以很省力了。自己只要做一遍,然后接下来就让电脑来做。

一、执行方法

执行文件如下:
在这里插入图片描述

python .\KeymouseGo.py 

在这里插入图片描述

二、python录制

1.Frame1.py

代码如下(示例):

#Boa:Frame:Frame1

import os
import sys
import wx
import time
import threading
import datetime
import json
import traceback

from pynput import mouse
from pynput import keyboard
from pynput.mouse import Button
from pynput.keyboard import Key, KeyCode

PY2 = PY3 = False
try:
    import StringIO
    from wx import TaskBarIcon as wxTaskBarIcon
    from wx import EVT_TASKBAR_LEFT_DCLICK
    PY2 = True
except:
    import io
    from wx.adv import TaskBarIcon as wxTaskBarIcon
    from wx.adv import EVT_TASKBAR_LEFT_DCLICK
    PY3 = True


# # anther way to resolve DPI Scaling on win10
# try:
#     import ctypes
#     ctypes.c_int()
#     ctypes.windll.shcore.SetProcessDpiAwareness(2)
# except Exception as e:
#     print(e)


wx.NO_3D = 0


KEYS = ['F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12']


def GetMondrianStream():
    if PY2:
        data = '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qIDATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
        stream = StringIO.StringIO(data)
    else:
        data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qIDATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82'
        stream = io.BytesIO(data)
    return stream


def GetMondrianBitmap():
    stream = GetMondrianStream()
    image = wx.ImageFromStream(stream)
    return wx.BitmapFromImage(image)


def GetMondrianIcon():
    icon = wx.EmptyIcon()
    icon.CopyFromBitmap(GetMondrianBitmap())
    return icon


def create(parent):
    return Frame1(parent)


[wxID_FRAME1, wxID_FRAME1BTRECORD, wxID_FRAME1BTRUN, wxID_FRAME1BTPAUSE, wxID_FRAME1BUTTON1, 
 wxID_FRAME1CHOICE_SCRIPT, wxID_FRAME1CHOICE_START, wxID_FRAME1CHOICE_STOP, 
 wxID_FRAME1PANEL1, wxID_FRAME1STATICTEXT1, wxID_FRAME1STATICTEXT2, 
 wxID_FRAME1STATICTEXT3, wxID_FRAME1STATICTEXT4, wxID_FRAME1STIMES, 
 wxID_FRAME1TEXTCTRL1, wxID_FRAME1TEXTCTRL2, wxID_FRAME1TNUMRD, 
 wxID_FRAME1TSTOP, wxID_FRAME1STATICTEXT5, wxID_FRAME1TEXTCTRL3,
] = [wx.NewId() for _init_ctrls in range(20)]


class Frame1(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME1, name='', parent=prnt,
              pos=wx.Point(506, 283), size=wx.Size(366, 201),
              style=wx.STAY_ON_TOP | wx.DEFAULT_FRAME_STYLE,
              title='Keymouse Go')
        self.SetClientSize(wx.Size(350, 205))

        self.panel1 = wx.Panel(id=wxID_FRAME1PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(350, 205),
              style=wx.NO_3D | wx.CAPTION)

        self.btrecord = wx.Button(id=wxID_FRAME1BTRECORD, label=u'\u5f55\u5236',
              name='btrecord', parent=self.panel1, pos=wx.Point(202, 12),
              size=wx.Size(56, 32), style=0)
        self.btrecord.Bind(wx.EVT_BUTTON, self.OnBtrecordButton,
              id=wxID_FRAME1BTRECORD)

        self.btrun = wx.Button(id=wxID_FRAME1BTRUN, label=u'\u542f\u52a8',
              name='btrun', parent=self.panel1, pos=wx.Point(274, 12),
              size=wx.Size(56, 32), style=0)
        self.btrun.Bind(wx.EVT_BUTTON, self.OnBtrunButton, id=wxID_FRAME1BTRUN)

        # 暂停/继续 功能不适合用按钮的形式来做,所以暂时隐去
        # self.btpause = wx.Button(id=wxID_FRAME1BTPAUSE, label=u'\u6682\u505c',
        #       name='btpause', parent=self.panel1, pos=wx.Point(274, 141),
        #       size=wx.Size(56, 32), style=0)
        # self.btpause.Bind(wx.EVT_BUTTON, self.OnBtpauseButton, id=wxID_FRAME1BTPAUSE)

        self.tnumrd = wx.StaticText(id=wxID_FRAME1TNUMRD, label=u'ready..',
              name='tnumrd', parent=self.panel1, pos=wx.Point(17, 175),
              size=wx.Size(100, 36), style=0)

        self.button1 = wx.Button(id=wxID_FRAME1BUTTON1, label=u'test',
              name='button1', parent=self.panel1, pos=wx.Point(128, 296),
              size=wx.Size(75, 24), style=0)
        self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
              id=wxID_FRAME1BUTTON1)

        self.tstop = wx.StaticText(id=wxID_FRAME1TSTOP,
              label=u'If you want to stop it, Press F12', name='tstop',
              parent=self.panel1, pos=wx.Point(25, 332), size=wx.Size(183, 18),
              style=0)
        self.tstop.Show(False)

        self.stimes = wx.SpinCtrl(id=wxID_FRAME1STIMES, initial=0, max=1000,
              min=0, name='stimes', parent=self.panel1, pos=wx.Point(206, 101),
              size=wx.Size(45, 18), style=wx.SP_ARROW_KEYS)
        self.stimes.SetValue(1)

        self.label_run_times = wx.StaticText(id=wxID_FRAME1STATICTEXT2,
              label=u'\u6267\u884c\u6b21\u6570(0\u4e3a\u65e0\u9650\u5faa\u73af)',
              name='label_run_times', parent=self.panel1, pos=wx.Point(203, 61),
              size=wx.Size(136, 26), style=0)

        self.textCtrl1 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL1, name='textCtrl1',
              parent=self.panel1, pos=wx.Point(24, 296), size=wx.Size(40, 22),
              style=0, value='119')

        self.textCtrl2 = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL2, name='textCtrl2',
              parent=self.panel1, pos=wx.Point(80, 296), size=wx.Size(36, 22),
              style=0, value='123')

        self.label_script = wx.StaticText(id=wxID_FRAME1STATICTEXT3,
              label=u'\u811a\u672c', name='label_script', parent=self.panel1,
              pos=wx.Point(17, 20), size=wx.Size(40, 32), style=0)

        self.choice_script = wx.Choice(choices=[], id=wxID_FRAME1CHOICE_SCRIPT,
              name=u'choice_script', parent=self.panel1, pos=wx.Point(79, 15),
              size=wx.Size(108, 25), style=0)

        self.label_start_key = wx.StaticText(id=wxID_FRAME1STATICTEXT1,
              label=u'\u542f\u52a8\u70ed\u952e', name='label_start_key',
              parent=self.panel1, pos=wx.Point(16, 63), size=wx.Size(56, 24),
              style=0)

        self.label_stop_key = wx.StaticText(id=wxID_FRAME1STATICTEXT4,
              label=u'\u7ec8\u6b62\u70ed\u952e', name='label_stop_key',
              parent=self.panel1, pos=wx.Point(16, 102), size=wx.Size(56, 32),
              style=0)

        self.choice_start = wx.Choice(choices=[], id=wxID_FRAME1CHOICE_START,
              name=u'choice_start', parent=self.panel1, pos=wx.Point(79, 58),
              size=wx.Size(108, 25), style=0)
        self.choice_start.SetLabel(u'')
        self.choice_start.SetLabelText(u'')
        self.choice_start.Bind(wx.EVT_CHOICE, self.OnChoice_startChoice,
              id=wxID_FRAME1CHOICE_START)

        self.choice_stop = wx.Choice(choices=[], id=wxID_FRAME1CHOICE_STOP,
              name=u'choice_stop', parent=self.panel1, pos=wx.Point(79, 98),
              size=wx.Size(108, 25), style=0)
        self.choice_stop.Bind(wx.EVT_CHOICE, self.OnChoice_stopChoice,
              id=wxID_FRAME1CHOICE_STOP)

        # ===== if use SetProcessDpiAwareness, comment below =====
        self.label_scale = wx.StaticText(id=wxID_FRAME1STATICTEXT5,
              label=u'\u5c4f\u5e55\u7f29\u653e', name='staticText5',
              parent=self.panel1, pos=wx.Point(16, 141), size=wx.Size(56, 32),
              style=0)
        self.text_scale = wx.TextCtrl(id=wxID_FRAME1TEXTCTRL3, name='textCtrl3',
              parent=self.panel1, pos=wx.Point(79, 138), size=wx.Size(108, 22),
              style=0, value='100%')
        # =========================================================

    def __init__(self, parent):

        self._init_ctrls(parent)
        
        self.SetIcon(GetMondrianIcon())
        self.taskBarIcon = TaskBarIcon(self) 
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_ICONIZE, self.OnIconfiy)
        
        if not os.path.exists('scripts'):
            os.mkdir('scripts')
        self.scripts = os.listdir('scripts')[::-1]
        
        self.choice_script.SetItems(self.scripts)
        self.scripts = list(filter(lambda s: s.endswith('.txt'), self.scripts))
        if self.scripts:
            self.choice_script.SetSelection(0)
                
        self.choice_start.SetItems(KEYS)
        self.choice_start.SetSelection(3)
        
        self.choice_stop.SetItems(KEYS)
        self.choice_stop.SetSelection(6)

        self.running = False
        self.recording = False
        self.record = []
        self.ttt = self.now_ts

        # for pause-resume feature
        self.paused = False
        self.pause_event = threading.Event()

        # =========== create mouse listener for record ===========
        def on_move(x, y):
            if not self.recording or self.running:
                return True

        def on_scroll(x, y, dx, dy):
            if not self.recording or self.running:
                return True

        def on_click(x, y, button, pressed):

            if not self.recording or self.running:
                return True

            # ===== if use SetProcessDpiAwareness, comment below =====
            try:
                scale = self.text_scale.GetValue()
                scale = scale.replace('%', '').replace('-', '').strip()
                scale = float(scale)
                scale = scale / 100.0
            except:
                scale = 1
            x = int(x / scale)
            y = int(y / scale)
            # =========================================================

            print('mouse click:', x, y, button.name, pressed)

            delay = self.now_ts - self.ttt
            self.ttt = self.now_ts
            if not self.record:
                delay = 0

            pos = (x, y)
            if button.name == 'left':
                message = 'mouse left '
            elif button.name == 'right':
                message = 'mouse right '
            else:
                return True
            if pressed:
                message += 'down'
            else:
                message += 'up'
            self.record.append([delay, 'EM', message, pos])
            text = self.tnumrd.GetLabel()
            text = text.replace(' actions recorded','')
            text = str(eval(text)+1)
            text = text + ' actions recorded'
            self.tnumrd.SetLabel(text)
            return True

        # =========== create keyboard listener for record ===========
        def key_event(key, is_press):
            if not self.recording or self.running:
                return True

            if is_press:
                print('keyboard press:', key)
                message = 'key down'
            else:
                print('keyboard release:', key)
                message = 'key up'

            if isinstance(key, Key):
                print('Key:', key.name, key.value.vk)
                name = key.name
            elif isinstance(key, KeyCode):
                print('KeyCode:', key.char, key.vk)
                name = key.char
            else:
                assert False


            delay = self.now_ts - self.ttt
            self.ttt = self.now_ts
            if not self.record:
                delay = 0

            self.record.append([delay, 'EK', message, name])

            text = self.tnumrd.GetLabel()
            text = text.replace(' actions recorded', '')
            text = str(eval(text) + 1)
            text = text + ' actions recorded'
            self.tnumrd.SetLabel(text)
            return True

        def on_press(key):
            return key_event(key, True)

        def on_release(key):
            print('=====',key)
            if not self.recording:
                # listen for start/stop script
                start_name = 'f6'
                stop_name = 'f9'
                start_index = self.choice_start.GetSelection()
                start_name = KEYS[start_index].lower()
                stop_index = self.choice_stop.GetSelection()
                stop_name = KEYS[stop_index].lower()

                print(start_name, stop_name, key)

                if not isinstance(key, Key):
                    return True

                if key.name == start_name and not self.running:
                    print('script start')
                    t = RunScriptClass(self, self.pause_event)
                    t.start()
                elif key.name == stop_name and self.running:
                    print('script stop')
                    self.tnumrd.SetLabel('broken')
            return key_event(key, False)

        self.mouse_listener = mouse.Listener(
            on_move=on_move,
            on_scroll=on_scroll,
            on_click=on_click
        )
        self.keyboard_listener = keyboard.Listener(
            on_press=on_press,
            on_release=on_release)
        
        self.mouse_listener.start()
        self.keyboard_listener.start()

    @property
    def now_ts(self):
        return int(time.time() * 1000)

    def get_script_path(self):
        i = self.choice_script.GetSelection()
        if i < 0:
            return ''
        script = self.scripts[i]
        path = os.path.join(os.getcwd(), 'scripts', script)
        print(path)
        return path
        
    def new_script_path(self):
        now = datetime.datetime.now()
        script = '%s.txt' % now.strftime('%m%d_%H%M')
        if script in self.scripts:
            script = '%s.txt' % now.strftime('%m%d_%H%M%S')
        self.scripts.insert(0, script)
        self.choice_script.SetItems(self.scripts)
        self.choice_script.SetSelection(0)
        return self.get_script_path()

    def OnHide(self, event):
        self.Hide()
        event.Skip()
        
    def OnIconfiy(self, event):
        self.Hide()
        event.Skip()
        
    def OnClose(self, event):
        try:
            self.mouse_listener.stop()
            self.keyboard_listener.stop()
        except:
            pass
        self.taskBarIcon.Destroy()
        self.Destroy()
        event.Skip()

    def OnButton1Button(self, event):
        event.Skip()

    def OnBtrecordButton(self, event):

        if self.recording:
            print('record stop')
            self.recording = False
            del self.record[-2]
            del self.record[-1]
            output = json.dumps(self.record, indent=1)
            output = output.replace('\r\n', '\n').replace('\r', '\n')
            output = output.replace('\n   ', '').replace('\n  ', '')
            output = output.replace('\n ]', ']')
            open(self.new_script_path(), 'w').write(output)
            self.btrecord.SetLabel(u'\u5f55\u5236')
            self.tnumrd.SetLabel('finished')
            self.record = []
        else:
            print('record start')
            self.recording = True
            self.ttt = self.now_ts
            status = self.tnumrd.GetLabel()
            if 'running' in status or 'recorded' in status:
                return
            self.btrecord.SetLabel(u'\u7ed3\u675f') # 结束
            self.tnumrd.SetLabel('0 actions recorded')
            self.choice_script.SetSelection(-1)
            self.record = []
        
        event.Skip()

    def OnBtrunButton(self, event):
        print('script start by btn')
        t = RunScriptClass(self, self.pause_event)
        t.start()
        event.Skip()

    def OnBtpauseButton(self, event):
        print('script pause button pressed')
        if self.paused:
            print('script is resumed')
            self.pause_event.set()
            self.paused = False
            self.btpause.SetLabel(u'\u6682\u505c') # 暂停
        else:
            print('script is paused')
            self.pause_event.clear()
            self.paused = True
            self.btpause.SetLabel(u'\u7ee7\u7eed') # 继续
        event.Skip()

    def OnChoice_startChoice(self, event):
        event.Skip()

    def OnChoice_stopChoice(self, event):
        event.Skip()


class RunScriptClass(threading.Thread):

    def __init__(self, frame: Frame1, event: threading.Event):
        self.frame = frame
        self.event = event
        self.event.set()
        super(RunScriptClass, self).__init__()

    def run(self):

        status = self.frame.tnumrd.GetLabel()
        if self.frame.running or self.frame.recording:
            return

        if 'running' in status or 'recorded' in status:
            return

        script_path = self.frame.get_script_path()
        if not script_path:
            self.frame.tnumrd.SetLabel('script not found, please self.record first!')
            return

        self.frame.running = True

        try:
            s = open(script_path, 'r').read()
            s = json.loads(s)
            steps = len(s)
            run_times = self.frame.stimes.Value

            running_text = '%s running..' % script_path.split('/')[-1].split('\\')[-1]
            self.frame.tnumrd.SetLabel(running_text)
            self.frame.tstop.Shown = True

            mouse_ctl = mouse.Controller()
            keyboard_ctl = keyboard.Controller()

            j = 0
            while j < run_times or run_times == 0:
                j += 1

                if self.frame.tnumrd.GetLabel() == 'broken' or self.frame.tnumrd.GetLabel() == 'finished':
                    self.frame.running = False
                    break
                
                for i in range(steps):
                    self.event.wait()
                    print(s[i])

                    # for old style script
                    if isinstance(s[i][0], str) and isinstance(s[i][3], int):
                        s[i].insert(0, s[i][3])

                    delay = s[i][0]
                    event_type = s[i][1]
                    message = s[i][2]
                    action = s[i][3]

                    message = message.lower()
                    
                    time.sleep(delay / 1000.0)
                    
                    if self.frame.tnumrd.GetLabel() == 'broken' or self.frame.tnumrd.GetLabel() == 'finished':
                        break
                            
                    text = '%s  [%d/%d %d/%d]' % (running_text, i+1, steps, j, run_times)
                    self.frame.tnumrd.SetLabel(text)

                    if event_type == 'EM':
                        x, y = action
                        mouse_ctl.position = (x, y)
                        if message == 'mouse left down':
                            mouse_ctl.press(Button.left)
                        elif message == 'mouse left up':
                            mouse_ctl.release(Button.left)
                        elif message == 'mouse right down':
                            mouse_ctl.press(Button.right)
                        elif message == 'mouse right up':
                            mouse_ctl.release(Button.right)
                        else:
                            print('unknow mouse event:', message)

                    elif event_type == 'EK':
                        key_name = action

                        if len(key_name) == 1:
                            key = key_name
                        else:
                            key = getattr(Key, key_name)

                        if message == 'key down':
                            keyboard_ctl.press(key)
                        elif message == 'key up':
                            keyboard_ctl.release(key)
                        else:
                            print('unknow keyboard event:', message)

            self.frame.tnumrd.SetLabel('finished')
            self.frame.tstop.Shown = False
            self.frame.running = False
            print('script run finish!')
            
        except Exception as e:
            print('run error', e)
            traceback.print_exc()
            self.frame.tnumrd.SetLabel('failed')
            self.frame.tstop.Shown = False
            self.frame.running = False


class TaskBarIcon(wxTaskBarIcon):
    ID_About = wx.NewId()
    ID_Closeshow = wx.NewId()

    def __init__(self, frame):
        wxTaskBarIcon.__init__(self)
        self.frame = frame
        self.SetIcon(GetMondrianIcon())
        self.Bind(EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarLeftDClick)
        self.Bind(wx.EVT_MENU, self.OnAbout, id=self.ID_About)
        self.Bind(wx.EVT_MENU, self.OnCloseshow, id=self.ID_Closeshow)

    def OnTaskBarLeftDClick(self, event):
        if self.frame.IsIconized():
            self.frame.Iconize(False)
        if not self.frame.IsShown():
            self.frame.Show(True)
        self.frame.Raise()

    def OnAbout(self, event):
        wx.MessageBox('https://github.com/taojy123/KeymouseGo', 'KeymouseGo')
        event.Skip()

    def OnCloseshow(self, event):
        self.frame.Close(True)
        event.Skip()

    def CreatePopupMenu(self):
        menu = wx.Menu()
        menu.Append(self.ID_About, 'About')
        menu.Append(self.ID_Closeshow, 'Exit')
        return menu


2.KeymouseGo.py

代码如下(示例):

#!/usr/bin/env python
#Boa:App:BoaApp

import Frame1
import wx
import time
import sys
import json

from pynput import mouse
from pynput import keyboard
from pynput.mouse import Button
from pynput.keyboard import Key, KeyCode


modules = {'Frame1': [1, 'Main frame of Application', u'Frame1.py']}


class BoaApp(wx.App):
    def OnInit(self):
        self.main = Frame1.create(None)
        self.main.Show()
        self.SetTopWindow(self.main)
        return True


def main():
    application = BoaApp(0)
    application.MainLoop()


def single_run(script_path, run_times=1):

    # python KeymouseGo.py scripts/0416_2342.txt 10
    # KeymouseGo.exe scripts\0416_2342.txt

    s = open(script_path, 'r').read()
    s = json.loads(s)
    steps = len(s)

    mouse_ctl = mouse.Controller()
    keyboard_ctl = keyboard.Controller()

    j = 0
    while j < run_times or run_times == 0:
        j += 1

        # Keep the same with Frame1.py:455, and remove code include `self`
        for i in range(steps):

            print(s[i])

            # for old style script
            if isinstance(s[i][0], str) and isinstance(s[i][3], int):
                s[i].insert(0, s[i][3])

            delay = s[i][0]
            event_type = s[i][1]
            message = s[i][2]
            action = s[i][3]

            message = message.lower()
            
            time.sleep(delay / 1000.0)

            if event_type == 'EM':
                x, y = action
                mouse_ctl.position = (x, y)
                if message == 'mouse left down':
                    mouse_ctl.press(Button.left)
                elif message == 'mouse left up':
                    mouse_ctl.release(Button.left)
                elif message == 'mouse right down':
                    mouse_ctl.press(Button.right)
                elif message == 'mouse right up':
                    mouse_ctl.release(Button.right)
                else:
                    print('unknow mouse event:', message)

            elif event_type == 'EK':
                key_name = action

                if len(key_name) == 1:
                    key = key_name
                else:
                    key = getattr(Key, key_name)

                if message == 'key down':
                    keyboard_ctl.press(key)
                elif message == 'key up':
                    keyboard_ctl.release(key)
                else:
                    print('unknow keyboard event:', message)

    print('script run finish!')


if __name__ == '__main__':

    print(sys.argv)

    if len(sys.argv) > 1:
        script_path = sys.argv[1]
        run_times = int(sys.argv[2]) if len(sys.argv) > 2 else 1
        single_run(script_path, run_times)
    else:
        main()


三、说明书

KeymouseGo v2.2

功能:记录用户的鼠标键盘操作,通过触发按钮自动执行之前记录的操作,可设定执行的次数,可以理解为 精简绿色版按键精灵

用途:在进行某些操作简单、单调重复的工作时,使用本软件就可以很省力了。自己只要做一遍,然后接下来就让电脑来做。

基本操作:

1、点击 录制 按钮,开始录制。

2、在计算机上进行任意操作,如点击鼠标、键盘输入,这部分的动作会被记录下来。

3、点击 结束 按钮,结束录制。

4、点击 启动 按钮,计算机会重复执行一遍第2步中所录制的动作。

提示:

1、可设置脚本重复执行的次数,如果为 0 即为无限循环。

2、默认启动热键为 F6,功能等同于 启动 按钮;默认终止热键为 F9,按下后将会停止正在运行的脚本。

3、录制时只记录鼠标点击动作和键盘动作,不记录鼠标移动轨迹。

4、每次录制结束后都会在 scripts 目前下生成一个新的脚本文件。

5、运行前可以在列表中选择一个需要执行的脚本。

6、scripts 下的脚本文件内容可以修改,修改时可参考如下所述 脚本格式说明

脚本格式说明:

[
 [3000, "EM", "mouse left down", [100, 200]], 
 [50,   "EM", "mouse left up", [100, 200]], 
 [1000, "EK", "key down", "f"], 
 [50,   "EK", "key up", "f"], 
 [2000, "EM", "mouse right down", [300, 400]], 
 [50,   "EM", "mouse right up", [300, 400]]
]

每一行代表一次动作:

  • 每行的第 1 个元素表示时间间隔,指的是本次动作与上一次动作之间相隔的时间,单位为毫秒。
  • 每行的第 2 个元素表示鼠标动作或是键盘动作:EM 为鼠标,EK 为键盘。
  • 每行的第 3 个元素表示动作的类型:mouse left down 为鼠标左键按下,mouse left up 为鼠标左键抬起,mouse right down 为鼠标右键按下,mouse right up 为鼠标右键抬起,key down 键盘按键按下,key up 键盘按键抬起。
  • 每行的第 4 个元素表示具体的动作参数,当为鼠标动作时,由两个子元素构成,分别为鼠标所在的屏幕位置的横纵坐标;键盘动作时为按下或抬起的按键名称。
  • 修改时请严格遵守格式,否则可能导致脚本无法运行,建议修改前先备份一下。

综上所述,示例中的脚本运行后的效果为:

  • 开始运行 3000ms 后,在屏幕坐标 (100,200)按下鼠标左键
  • 等待 50ms 后在相同位置 抬起鼠标左键
  • 等待 1000ms按下f键
  • 等待 50ms抬起f键
  • 等待 2000ms 后,在屏幕坐标 (300,400)按下鼠标左键
  • 等待 50ms 后在相同位置 抬起鼠标左键

使用命令行运行:

直接运行指定脚本:

> KeymouseGo.exe scripts/0314_1452.txt

运行指定脚本3次:

> KeymouseGo.exe scripts/0314_1452.txt 3

总结

分享:
人生,与其不断追求而无法满足,不如先沉淀自己,看清内心深处真正的需求。只要愿意打开封闭的心,去体会、去拥抱眼前的幸福,就会比别人活得更富足,更开心。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

python记录鼠标键盘操作自动执行重复工作 的相关文章

  • Spark 请求最大计数

    我是 Spark 的初学者 我尝试请求允许我检索最常访问的网页 我的要求如下 mostPopularWebPageDF logDF groupBy webPage agg functions count webPage alias cntW
  • 围绕 readline 构建的 python 批处理的触发器选项卡完成

    背景 我有一个 python 程序 它导入并使用 readline 模块来构建自制的命令行界面 我有第二个 python 程序 围绕 Bottle 一个 Web 微框架构建 充当该 CLI 的前端 第二个 python 程序向第一个程序打开
  • 从数据框中按索引删除行

    我有一个数组wrong indexes train其中包含我想从数据框中删除的索引列表 0 63 151 469 1008 要删除这些索引 我正在尝试这样做 df train drop wrong indexes train 但是 代码失败
  • Python Popen 与 psexec 挂起 - 不良结果

    我对 subprocess Popen 和我认为是管道的问题有疑问 我有以下代码块 从 cli 运行时 100 都不会出现问题 p subprocess Popen psexec serverName get cmd c ver echo
  • 我怎样才能更多地了解Python的内部原理? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我使用Python编程已经有半年多了 我对Python内部更感兴趣 而不是使用Python开发应用程序
  • Python模块可以访问英语词典,包括单词的定义[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个 python 模块 它可以帮助我从英语词典中获取单词的定义 当然有enchant 这可以帮助我检查该单词是否存在于英语中
  • Python逻辑运算符优先级[重复]

    这个问题在这里已经有答案了 哪个运算符优先4 gt 5 or 3 lt 4 and 9 gt 8 这会被评估为真还是假 我知道该声明3 gt 4 or 2 lt 3 and 9 gt 10 显然应该评估为 false 但我不太确定 pyth
  • 从零开始的 numpy 形状意味着什么

    好的 我发现数组的形状中可以包含 0 对于将 0 作为唯一维度的情况 这对我来说是有意义的 它是一个空数组 np zeros 0 但如果你有这样的情况 np zeros 0 100 让我很困惑 为什么这么定义呢 据我所知 这只是表达空数组的
  • Pandas 数据帧到 numpy 数组 [重复]

    这个问题在这里已经有答案了 我对 Python 很陌生 经验也很少 我已经设法通过复制 粘贴和替换我拥有的数据来使一些代码正常工作 但是我一直在寻找如何从数据框中选择数据 但无法理解这些示例并替换我自己的数据 总体目标 如果有人真的可以帮助
  • 如何解决使用 Spark 从 S3 重新分区大量数据时从内存中逐出缓存的表分区元数据的问题?

    在尝试从 S3 重新分区数据帧时 我收到一个一般错误 Caused by org apache spark SparkException Job aborted due to stage failure Task 33 in stage 1
  • Numpy 过滤器平滑零区域

    我有一个 0 及更大整数的 2D numpy 数组 其中值代表区域标签 例如 array 9 9 9 0 0 0 0 1 1 1 9 9 9 9 0 7 1 1 1 1 9 9 9 9 0 2 2 1 1 1 9 9 9 8 0 2 2 1
  • Seaborn Pairplot 图例不显示颜色

    我一直在学习如何在Python中使用seaborn和pairplot 这里的一切似乎都工作正常 但由于某种原因 图例不会显示相关的颜色 我无法找到解决方案 因此如果有人有任何建议 请告诉我 x sns pairplot stats2 hue
  • 在 pytube3 中获取 youtube 视频的标题?

    我正在尝试构建一个应用程序来使用 python 下载 YouTube 视频pytube3 但我无法检索视频的标题 这是我的代码 from pytube import YouTube yt YouTube link print yt titl
  • Pandas 根据 diff 列形成簇

    我正在尝试使用 Pandas 根据表示时间 以秒为单位 的列中的差异来消除数据框中的一些接近重复项 例如 import pandas as pd numpy as np df pd DataFrame 1200 1201 1233 1555
  • 如何在 python 中没有 csv.reader 迭代器的情况下解析单行 csv 字符串?

    我有一个 CSV 文件 需要重新排列和重新编码 我想跑 line line decode windows 1250 encode utf 8 在由 CSV 读取器解析和分割之前的每一行 或者我想自己迭代行 运行重新编码 并仅使用单行解析表单
  • 无法在 osx-arm64 上安装 Python 3.7

    我正在尝试使用 Conda 创建一个带有 Python 3 7 的新环境 例如 conda create n qnn python 3 7 我收到以下错误 Collecting package metadata current repoda
  • 无法在前端使用 JavaScript Fetch API 将文件上传到 FastAPI 后端

    我正在尝试弄清楚如何将图像发送到我的 API 并验证生成的token那是在header的请求 到目前为止 这就是我所处的位置 app post endreProfilbilde async def endreProfilbilde requ
  • 限制 django 应用程序模型中的单个记录?

    我想使用模型来保存 django 应用程序的系统设置 因此 我想限制该模型 使其只能有一条记录 极限怎么办 尝试这个 class MyModel models Model onefield models CharField The fiel
  • 如何读取Python字节码?

    我很难理解 Python 的字节码及其dis module import dis def func x 1 dis dis func 上述代码在解释器中输入时会产生以下输出 0 LOAD CONST 1 1 3 STORE FAST 0 x
  • 从 Twitter API 2.0 获取 user.fields 时出现问题

    我想从 Twitter API 2 0 端点加载推文 并尝试获取标准字段 作者 文本 和一些扩展字段 尤其是 用户 字段 端点和参数的定义工作没有错误 在生成的 json 中 我只找到标准字段 但没有找到所需的 user fields 用户

随机推荐

  • 数据分析回头看2——重复值检查/元素替换/异常值筛选

    0 前言 这部分内容是对Pandas的回顾 同时也是对Pandas处理异常数据的一些技巧的总结 不一定全面 只是自己在数据处理当中遇到的问题进行的总结 1 当数据中有重复行的时候需要检测重复行 方法 使用pandas中的duplicated
  • 提高Python编程效率的十个技巧

    1 模块化编程 将代码拆分为模块和函数 提高可重用性和可维护性 合理组织代码 使其易于阅读和理解 2 利用Python标准库 Python标准库提供了众多功能强大的模块和工具 如os re和datetime等 熟悉并善于使用标准库可以加快开
  • PAT C入门题目-7-30 念数字 (15 分)(关于string.h头文件)

    7 30 念数字 15 分 输入一个整数 输出每个数字对应的拼音 当整数为负数时 先输出fu字 十个数字对应的拼音如下 0 ling 1 yi 2 er 3 san 4 si 5 wu 6 liu 7 qi 8 ba 9 jiu 输入格式
  • linux -- 命令行中大于号、小于号的用法

    语法 命令 lt 文件 这是将文件作为命令输入 命令 lt 文件1 gt 文件2 将文件1输入到命令中 然后将结果输出到文件2中
  • tensorflow各版本下载地址

    https pypi org project tensorflow gpu 1 13 0 files 把13改对你想要的版本 转载于 https www cnblogs com xpylovely p 11609250 html
  • 2022 re:Invent 凌云驭势 重塑未来

    2022年11月29日 一年一度的亚马逊 re Invent全球大会在拉斯维加斯再度上演 这是亚马逊云科技第11年举办re Invent 来自全球的5万多客户和合作伙伴参加了此次线下盛会 还有超过30万人线上参会 在此次大会上 亚马逊云科技
  • 埃斯顿服务器上电无显示,埃斯顿伺服常见现象报警及排除

    用户在试用埃斯顿伺服电机时可能会遇见以下的问题 在此我整理一下 希望能帮助到大家 一 过载报警A04 1 伺服电机的配线有误或配线有漏 1 电机U V W相线接错 2 伺服电机侧连接器的插入是否不良 2 伺服驱动器与电机的型号不匹配 检查驱
  • Android 内存泄漏的原因以及解决方案

    内存泄漏是什么 内存泄漏即 ML Memory Leak 指 程序在申请内存后 当该内存不需再使用 但 却无法被释放 归还给 程序的现象 内存泄漏的原因以及解决方案 内存泄漏的原因归根到底就是当需要被回收变量的内存被其他变量引用持有 导致内
  • 光照 (4) 镜面光贴图示例

    通过使用镜面光贴图我们可以可以对物体设置大量的细节 比如物体的哪些部分需要有闪闪发光的属性 我们甚至可以设置它们对应的强度 镜面光贴图能够在漫反射贴图之上给予我们更高一层的控制 step1 对镜面光贴图使用一个不同的纹理单元 见纹理 在渲染
  • 软考高级之系统架构师之项目管理

    今天是2023年09月06日 距离软考高级只有58天 加油 概念 临时性 是指每一个项目都有一个明确的开始时间和结束时间 临时性也指项目是一次性的 风险 风险具有以下特性 客观性 偶然性 相对性 社会性 不确定性 风险的四要素 事件 原因
  • 邮件服务器测试方法

    邮件服务器测试方法一 测试是在问题邮件服务器上完成的 二 登陆问题邮件服务器 使用nslookup命令查看需测试的邮件服务器域名解析记录 找到测试端的DNS可以解析到的MX记录 三 通过TELNET命令进行测试 一 TELNET需注意的事项
  • 什么是爬虫?爬虫的具体作用?

    什么是爬虫 答 爬虫的官方名字 spider 爬虫又被称之为网络蜘蛛 网络机器人等 就是模拟客户端发送网络请求 接收请求响应 按照一定的规则自动的抓取互联网信息的程序 爬虫的具体作用 答 数据采集 搜索引擎 软件测试 短信轰炸等等 一般是用
  • Web前端面试指导(三十八):js延迟加载的方式有哪些?

    题目点评 主要考察对程序的性能方面是否有研究 程序的性能是一个项目不断地追求的 通常也是项目完成后需要长期做的一件事情 像腾讯QQ依然对程序的性能不断地做优化 让用户的体验更好 性能优化的核心思想就是快 可以预先准备数据 如缓存的使用 可以
  • 使用C++ 编写嵌入式应用程序

    大多数嵌入式工程师使用C语言来编写Cortex M系列MCU 的程序 大家总觉得C 是用来编写Windows 或者Linux 应用程序的 特别是硬件工程师 也许压根就没有使用C 来编写程序 当我们阅读Mbed OS 的代码时却发现 许多是使
  • mysql--备份/主从同步/安装

    1 编写脚本 支持让用户自主选择 使用mysqldump还是xtraback全量备份 bin bash date date F sock S data mysql mysql3306 socket mysql sock dbdir back
  • vue iframe 刷新保留在原来的页面

    公司有个需求 我们的项目是微服务项目 每个tab里面的内容都是 iframe 现在需求是点击刷新 F5 等刷新 iframe 还保留在原来的页面 1 iframe 子页面 router js 中监听路由变化 并存储当前页面的路由 route
  • 【Linux】Ubuntu基本使用与配置, 以及常见问题汇总(一)

    前言 大学期间 感觉很多时候学习课外知识都是被推着往前走 很多内容并没有深入去学习 知识的记录受限于所学比较片面 如今渐渐意识到似乎并没有建立起相关知识的体系架构 缺乏一个系统学习并整理的过程 本文将以Ubuntu系统为例 来整理一些Lin
  • R手册(Common)--R语言入门

    说明 本节中大部分内容摘自书籍 R语言实战 第2版 文章目录 RStudio Take control of your R code 数据处理一般流程 R 数据结构 R 运算符 概率函数 控制语句与循环语句 自定义函数 调试 拟合线性模型f
  • weex stream 方法封装

    1 封装 api js 配置API接口地址 const baseUrl http www kuitao8 com 引入 弹窗组件 var modal weex requireModule modal 引入 请求数据组件 var stream
  • python记录鼠标键盘操作自动执行重复工作

    系列文章目录 文章目录 系列文章目录 前言 github项目原地址 一 执行方法 二 python录制 1 Frame1 py 2 KeymouseGo py 三 说明书 KeymouseGo v2 2 基本操作 提示 脚本格式说明 使用命