Python 模拟键盘输入:中文乱码和 Citrix 场景的应对

自动化脚本里想模拟键盘输入——听着简单,一遇到中文、遇到 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 的文件传过去,只能靠键盘输入。

技巧:

  1. 本机 base64 编码文件(比 hex 省一半体积)
  2. 分块用 pyautogui.write 发(每块 4 KB 左右)
  3. 内网服务器上再解码
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 窗口有效。