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

news2025/3/10 16:07:27

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

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

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

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

相关文章

测试辅助工具(抓包工具)的使用1 之初识抓包工具(fiddler)

1.什么是抓包? 说明:客户端向服务器发送请求以及服务器响应客户端的请求,都是以数据包来传递的。 抓包(packet capture):通过工具拦截客户端与服务器交互的数据包。 抓包后可以修改数据包的内容 2.为什么要抓包&…

【洛谷P3366】【模板】最小生成树 解题报告

洛谷P3366 -【模板】最小生成树 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。 输入格式 第一行包含两个整数 N , M N,M N,M,表示该图共有 N N N 个结点和 M M M 条无向边。 接下…

解决js打开新页面百度网盘显示不存在方法:啊哦,你所访问的页面不存在了。

用js打开新页面open或window.location.href打开百度网盘后都显示:啊哦,你所访问的页面不存在了。 window.open(baidu_url); window.location.href baidu_url;在浏览器上,回车后网盘资源是可以打开的,刷新也是打开的。这是很奇怪…

IPv6知识点整理

IPv6:是英文“Internet Protocol Version 6”(互联网协议第6版)的缩写,是互联网工程任务组(IETF)设计的用于替代IPv4的下一代IP协议,其地址数量号称可以为全世界的每一粒沙子编上一个地址 。 国…

OkHttp框架源码深度剖析【Android热门框架分析第一弹】

OkHttp介绍 OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。Google在Android4.4以后开始将源码中的HttpURLConnection底层实现替换为OKHttp,同时现在流行的Retrofit框架底层同样是使用OKHttp的。 源码传送门 优点: 支持Http1、Http…

初学者的TensorFlow 2.0 开发环境安装 -《MCU嵌入式AI开发笔记》(第七集)

MCU嵌入式AI开发笔记 初学者的TensorFlow 2.0 开发环境安装 -《MCU嵌入式AI开发笔记》(第七集)。抖音、B站、视频号等站点搜索柔贝特三哥,《MCU嵌入式AI开发笔记》视频同步更新,视频详细讲解。 07 初学者的 TensorFlow 2.0 教程 …

【tomcat】tomcat系统架构以及核心启动流程

对于web后端开发工程师来说,tomcat作为一个应用服务器框架本质上就是一个HTTP服务Servlet容器。研究过spring、spring mvc源码的同学应该了解,spring mvc其实就是基于Servlet规范实现的请求的转发路由、转发处理。而Spring和SpringMVC就是通过web.xml文件…

DINO-DETR

DINO-DETR DETR收敛慢的问题1. Contrastive DeNoising Training(对比方法降噪训练)2. Mixed Query Selection(混合查询选择方法对锚点进行初始化)3. Look Forward Twice(两次前向方法)==DINO模型的传播过程,以及部分模块的改进==DETR收敛慢的问题 PnP-DETR(ICCV 2021) 改进了…

同时使用接口文档swagger和knife4j

项目场景: springboot项目中同时使用接口文档swagger和knife4j 问题描述 在实体类中设置了字段必填的属性,在访问接口文档时出现异常 实体类关键代码片段 /*** 部门表 sys_dept*/ public class SysDept extends BaseEntity {private static final lo…

大聪明教你学Java | 深入浅出聊 Kafka

前言 🍊作者简介: 不肯过江东丶,一个来自二线城市的程序员,致力于用“猥琐”办法解决繁琐问题,让复杂的问题变得通俗易懂。 🍊支持作者: 点赞👍、关注💖、留言&#x1f4…

2024年6月23日 十二生肖 今日运势

小运播报:2024年6月23日,星期日,农历五月十八 (甲辰年庚午月戊午日),法定节假日。今天国际奥林匹克日,坚不可摧的意志,披荆斩棘的豪情,永远值得拥有! 红榜生…

YOLOv8改进 | SPPF | 双通道特征处理的池化结构——SPPFCSPC【全网独家】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有40篇内容,内含各种Head检测头、损失函数Loss、…

LLM主流架构和模型

本文参考自https://github.com/HqWu-HITCS/Awesome-Chinese-LLM?tabreadme-ov-file和Huggingface中的ModelCard(https://huggingface.co/) LLM主要类别架构 LLM本身基于transformer架构。自2017年,attention is all you need诞生起&#x…

P1223 排队接水

题目描述 有 𝑛 个人在一个水龙头前排队接水,假如每个人接水的时间为 𝑇𝑖,请编程找出这 𝑛 个人排队的一种顺序,使得 𝑛个人的平均等待时间最小。 输入格式 第一行为一个整数 &a…

C++ | Leetcode C++题解之第169题多数元素

题目&#xff1a; 题解&#xff1a; class Solution { public:int majorityElement(vector<int>& nums) {int candidate -1;int count 0;for (int num : nums) {if (num candidate)count;else if (--count < 0) {candidate num;count 1;}}return candidate;…

根据状态转移写状态机-二段式

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 描述 题目描述&#xff1a; 如图所示为两种状态机中的一种&#xff0c;请根据状态转移图写出代码&#xff0c;状态转移线上的0/0等表示的意思是过程中data/flag的值。 要求&#xff1a; 1、 必须使用对应类型的状…

Django 条件判断模板标签

1&#xff0c;条件判断模板标签 1. 2 {% if %} 标签 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 --> {% endif %} 1. 3 {% if %} 与 {% else %} 组合 {% if variable %}<!-- 如果 variable 为 True&#xff0c;则渲染此处内容 -->…

Ubuntu使用 NVIDIA GPU 和 CUDA 设置 LLM 的训练、微调和推理

0.引言 近年来&#xff0c;人工智能领域取得了令人瞩目的进步&#xff0c;其核心是图形处理单元&#xff08;GPU&#xff09;和并行计算平台的强大组合。 大模型如 GPT、BER能够理解和生成具有前所未有的流畅性和连贯性的类人文本。然而&#xff0c;训练这些模型需要大量的数据…

外卖APP开发详解:从同城O2O系统源码开始

近期&#xff0c;从事软件开发的小伙伴们都在讨论外卖APP&#xff0c;热度非常之高&#xff0c;所以小编今天将与大家一同探讨同城O2O系统源码、外卖APP开发。 一、外卖APP开发的前期准备 了解目标用户的需求&#xff0c;分析竞争对手的优劣势&#xff0c;明确自身的市场定位。…

算法金 | 统计学的回归和机器学习中的回归有什么差别?

大侠幸会&#xff0c;在下全网同名「算法金」 0 基础转 AI 上岸&#xff0c;多个算法赛 Top 「日更万日&#xff0c;让更多人享受智能乐趣」 统计学中的回归 目标&#xff1a; 主要用于解释和推断自变量&#xff08;independent variables&#xff09;和因变量&#xff08;de…