自动化脚本里想模拟键盘输入——听着简单,一遇到中文、遇到 Citrix / RDP / 游戏窗口,坑就一个接一个来。列一下常用方案和各自适用场景。
方案对比
| 库 | 优点 | 缺点 |
|---|---|---|
pyautogui | 跨平台、简单 | 中文经常挂、后台窗口不响应 |
keyboard | 全局事件、监听热键 | Windows 常需管理员、后台无效 |
pywin32 | 支持后台 WM_CHAR | 某些程序(浏览器、游戏)不响应 WM_CHAR |
ctypes + WinAPI | 无依赖、最底层 | 需要处理 scan code、代码稍长 |
| 剪贴板 + Ctrl+V | 中文、长文本最稳 | 会覆盖用户剪贴板 |
最简单:pyautogui
import pyautogui, time
time.sleep(3) # 3 秒切窗口
pyautogui.write("hello world") # 输入英文
pyautogui.press("enter") # 按键
pyautogui.hotkey("ctrl", "c") # 组合键
interval 参数控制打字间隔:
pyautogui.write("hello", interval=0.05)
中文乱码怎么办
pyautogui.write("你好") 本质是把字符串拆成一个个按键事件。中文没有对应的物理按键,很多环境(尤其 Citrix、RDP、游戏、浏览器某些输入框)会输入乱码或干脆吞掉。
最稳的做法是 走系统剪贴板 + Ctrl+V:
import pyperclip, pyautogui, time
pyperclip.copy("你好世界,长文本也行")
time.sleep(2) # 切窗口
pyautogui.hotkey("ctrl", "v")
优点:
- 支持中文 / emoji / 特殊字符
- 支持超长文本(比逐字模拟快百倍)
- 兼容大多数远程桌面 / Citrix
缺点:
- 会覆盖用户当前剪贴板(可以备份再还原)
- 需要目标窗口支持
Ctrl+V
带备份还原的完整版本:
import pyperclip, pyautogui, time
def paste_text(text):
backup = pyperclip.paste()
pyperclip.copy(text)
time.sleep(0.1)
pyautogui.hotkey("ctrl", "v")
time.sleep(0.1)
pyperclip.copy(backup)
后台发送到指定窗口
前台切换太打扰人,想在不抢焦点的情况下往某个窗口发内容:
import win32gui, win32api, win32con
hwnd = win32gui.FindWindow(None, "记事本")
for ch in "hello":
win32api.SendMessage(hwnd, win32con.WM_CHAR, ord(ch), 0)
局限:
- 浏览器 / 游戏 / Citrix / 远程桌面通常不响应
WM_CHAR(安全考虑) - 只对纯 Win32 原生窗口有效
不响应的目标只能回到”抢焦点 + 真实按键”路线。
Citrix 里传大数据
场景:本机 → Citrix → 内网服务器,想把一个几 MB 的文件传过去,只能靠键盘输入。
技巧:
- 本机 base64 编码文件(比 hex 省一半体积)
- 分块用
pyautogui.write发(每块 4 KB 左右) - 内网服务器上再解码
import pyautogui, base64, time
with open("payload.bin", "rb") as f:
data = base64.b64encode(f.read()).decode()
time.sleep(3) # 切到 Citrix 窗口
CHUNK = 4096
for i in range(0, len(data), CHUNK):
pyautogui.write(data[i:i + CHUNK], interval=0.001)
time.sleep(0.1)
pyautogui.press("enter")
内网服务器上有 Python / Bash 就 base64 -d 还原。
监听全局热键
想按 F8 触发某个动作:
import keyboard
keyboard.wait("f8")
print("触发")
Windows 上需要管理员运行才能读到全局键盘事件。
一句话总结
英文短文本用 pyautogui.write;中文和长文本用剪贴板 + Ctrl+V;Citrix/RDP 传大数据用 base64 + 分块 write。后台无焦点发送只对纯 Win32 窗口有效。
