Python自动化(2)——键盘模拟

Python自动化(2)——键盘模拟

前台键盘模拟

前台键盘模拟和后台键盘模拟的区别在于,是否绑定窗口。即前台模拟是只模拟键盘操作,例如按下按键a,如果聚焦在一个文本文档的编辑区,那么就会把这个a输入进去。但如果是聚焦到了浏览器上的百度翻译编辑区,同样会把a输入进去
下图分别是循环输入10个a的结果(浏览器下建议先将输入法改成英文,否则有可能无反应或者是触发了什么快捷键):
在这里插入图片描述
在这里插入图片描述

实现:
先上代码

import time
import win32api
import win32con
import pyautogui
import pyperclip
 
class FrontstageKeyBoard():
    def __init__(self):
        self.key_map = {
            "0": 49, "1": 50, "2": 51, "3": 52, "4": 53, "5": 54, "6": 55, "7": 56, "8": 57, "9": 58,
            'F1': 112, 'F2': 113, 'F3': 114, 'F4': 115, 'F5': 116, 'F6': 117, 'F7': 118, 'F8': 119,
            'F9': 120, 'F10': 121, 'F11': 122, 'F12': 123, 'F13': 124, 'F14': 125, 'F15': 126, 'F16': 127,
            "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74,
            "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84,
            "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90,
            'BACKSPACE': 8, 'TAB': 9, 'TABLE': 9, 'CLEAR': 12,
            'ENTER': 13, 'SHIFT': 16, 'CTRL': 17,
            'CONTROL': 17, 'ALT': 18, 'ALTER': 18, 'PAUSE': 19, 'BREAK': 19, 'CAPSLK': 20, 'CAPSLOCK': 20, 'ESC': 27,
            'SPACE': 32, 'SPACEBAR': 32, 'PGUP': 33, 'PAGEUP': 33, 'PGDN': 34, 'PAGEDOWN': 34, 'END': 35, 'HOME': 36,
            'LEFT': 37, 'UP': 38, 'RIGHT': 39, 'DOWN': 40, 'SELECT': 41, 'PRTSC': 42, 'PRINTSCREEN': 42, 'SYSRQ': 42,
            'SYSTEMREQUEST': 42, 'EXECUTE': 43, 'SNAPSHOT': 44, 'INSERT': 45, 'DELETE': 46, 'HELP': 47, 'WIN': 91,
            'WINDOWS': 91, 'NMLK': 144,
            'NUMLK': 144, 'NUMLOCK': 144, 'SCRLK': 145,
            '[': 219, ']': 221, '+': 107, '-': 109}
        print('FrontstageKeyBoard init')

    # 模拟一次按键的输入,间隔值默认0.1S
    def pressKey(self, key: str, interval=0.1):
        self.keyDown(key)
        time.sleep(interval)
        self.keyUp(key)

    # 模拟一次组合键的输入,间隔值默认0.1S
    def pressKeys(self, keys, interval=0.1):
        for i in range (0,len(keys),1):
            self.keyDown(keys[i], False)
        time.sleep(interval)
        for i in range (0,len(keys),1):
            self.keyUp(keys[i])
 
    # 模拟一个按键的按下
    def keyDown(self, key: str):
        print('keyDown: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.keybd_event(key_code, win32api.MapVirtualKey(key_code, 0), win32con.KEYEVENTF_EXTENDEDKEY, 0)
 
    # 模拟一个按键的弹起
    def keyUp(self, key: str):
        print('keyUp: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.keybd_event(key_code, win32api.MapVirtualKey(key_code, 0), win32con.KEYEVENTF_KEYUP, 0)

    # 模拟输入一段文本,只能输入英文或字母
    def inputText(self, text: str, interval=0.05):
        print('input text: ' + text)
        pyautogui.typewrite(text, interval)

    # 模拟输入一段文本,支持中文,但是实现的方法是通过复制粘贴
    def inputChineseText(self, text: str):
        print('input text: ' + text)
        pyperclip.copy(text)
        pyautogui.hotkey('Ctrl','v')

这里使用win32api.keybd_event实现键盘模拟按下的操作,实际上前台模拟键盘操作还可以用pykeyboard库、pyautogui库、keyboard库

后台键盘模拟

与前台模拟键盘不同,后台键盘模拟是绑定窗口的,绑定的是窗口句柄,是基于win32api库实现的。后台键盘模拟能做到绑定窗口实现模拟,并且不需要聚焦窗口,简单来说就是不影响正常使用电脑。

先上代码:

import time
import win32api
import win32con
import win32gui
 
class BackstageKeyBoard():
    def __init__(self):
        self.key_map = {
            "0": 49, "1": 50, "2": 51, "3": 52, "4": 53, "5": 54, "6": 55, "7": 56, "8": 57, "9": 58,
            'F1': 112, 'F2': 113, 'F3': 114, 'F4': 115, 'F5': 116, 'F6': 117, 'F7': 118, 'F8': 119,
            'F9': 120, 'F10': 121, 'F11': 122, 'F12': 123, 'F13': 124, 'F14': 125, 'F15': 126, 'F16': 127,
            "A": 65, "B": 66, "C": 67, "D": 68, "E": 69, "F": 70, "G": 71, "H": 72, "I": 73, "J": 74,
            "K": 75, "L": 76, "M": 77, "N": 78, "O": 79, "P": 80, "Q": 81, "R": 82, "S": 83, "T": 84,
            "U": 85, "V": 86, "W": 87, "X": 88, "Y": 89, "Z": 90,
            'BACKSPACE': 8, 'TAB': 9, 'TABLE': 9, 'CLEAR': 12, 'ENTER': 13, 'SHIFT': 16, 'CTRL': 17,
            'CONTROL': 17, 'ALT': 18, 'ALTER': 18, 'PAUSE': 19, 'BREAK': 19, 'CAPSLK': 20, 'CAPSLOCK': 20, 'ESC': 27,
            'SPACE': 32, 'SPACEBAR': 32, 'PGUP': 33, 'PAGEUP': 33, 'PGDN': 34, 'PAGEDOWN': 34, 'END': 35, 'HOME': 36,
            'LEFT': 37, 'UP': 38, 'RIGHT': 39, 'DOWN': 40, 'SELECT': 41, 'PRTSC': 42, 'printSCREEN': 42, 'SYSRQ': 42,
            'SYSTEMREQUEST': 42, 'EXECUTE': 43, 'SNAPSHOT': 44, 'INSERT': 45, 'DELETE': 46, 'HELP': 47, 'WIN': 91,
            'WINDOWS': 91, 'NMLK': 144,
            'NUMLK': 144, 'NUMLOCK': 144, 'SCRLK': 145,
            '[': 219, ']': 221, '+': 107, '-': 109}
        print('BackstageKeyBoard init')
 
    def bind(self, hwnd):
        self.hwnd = hwnd

    # 后台模拟方法1——使用SendMessage(默认)  ############################################

    # 模拟一次按键的输入,间隔值默认0.1S
    def pressKey(self, key: str, interval=0.1):
        self.keyDown(key)
        time.sleep(interval)
        self.keyUp(key)

    # 模拟一次组合键的输入,间隔值默认0.1S
    def pressKeys(self, keys, interval=0.1):
        for i in range (0,len(keys),1):
            self.keyDown(keys[i])
        time.sleep(interval)
        for i in range (0,len(keys),1):
            self.keyUp(keys[i])
 
    # 模拟一个按键的按下
    def keyDown(self, key: str):
        print('keyDown: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.SendMessage(self.hwnd, win32con.WM_KEYDOWN, key_code, 0)
 
    # 模拟一个按键的弹起
    def keyUp(self, key: str):
        print('keyUp: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.SendMessage(self.hwnd, win32con.WM_KEYUP, key_code, 0)

    # 模拟输入一段文本
    def inputText(self, text: str):
        print('input text: ' + text)
        for ch in text:
            win32gui.SendMessage(self.hwnd, win32con.WM_CHAR, ord(ch), 0)
            time.sleep(0.05)

    # 后台模拟方法2——使用PostMessage  ############################################

    # 模拟一次按键的输入,间隔值默认0.1S
    def pressKey_2(self, key: str, interval=0.1):
        self.keyDown_2(key)
        time.sleep(interval)
        self.keyUp_2(key)

    # 模拟一次组合键的输入,间隔值默认0.1S
    def pressKeys_2(self, keys, interval=0.1):
        for i in range (0,len(keys),1):
            self.keyDown_2(keys[i])
        time.sleep(interval)
        for i in range (0,len(keys),1):
            self.keyUp_2(keys[i])

    # 模拟一个按键的按下
    def keyDown_2(self, key: str):
        print('keyDown_2: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.PostMessage(self.hwnd, win32con.WM_KEYDOWN, key_code, 0)
 
    # 模拟一个按键的弹起
    def keyUp_2(self, key: str):
        print('keyUp_2: ' + str(key))
        key_code = self.key_map[key.upper()]
        win32api.PostMessage(self.hwnd, win32con.WM_KEYUP, key_code, 0)

    # 模拟输入一段文本
    def inputText_2(self, text: str):
        print('input_2 text: ' + text)
        for ch in text:
            win32gui.PostMessage(self.hwnd, win32con.WM_CHAR, ord(ch), 0)
            time.sleep(0.05)

上面的代码中,有使用SendMessage和PostMessage来实现的键盘模拟,其中,SendMessage是会等待函数执行后再返回,而PostMessage发送消息后会立即返回。一般情况下,这两种方法并无太大区别。

SendMessage方法的函数原型:
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。
PostMessage方法的函数原型与SendMessage基本一致,不同的是PostMessage的返回值为BOOL类型。
使用后台键盘模拟,需要绑定窗口句柄,关于窗口句柄的获取,可以看看下面这篇文章:
Python自动化(1)——获取窗口句柄

完整自动化工程代码:https://gitee.com/chj-self/PythonRobotization

大佬们找到问题欢迎拍砖~

  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值