Python實(shí)現(xiàn)Windows鍵盤(pán)鼠標(biāo)自動(dòng)化模擬器
本文介紹一個(gè)基于Python的Windows鍵盤(pán)鼠標(biāo)自動(dòng)化模擬器,適合自動(dòng)化測(cè)試、游戲輔助等場(chǎng)景。代碼通過(guò)ctypes調(diào)用Windows API實(shí)現(xiàn)底層輸入模擬。
實(shí)測(cè)案例:bongo cat刷點(diǎn)擊

1. 主要功能
模擬鍵盤(pán)按鍵(按下、釋放、完整按鍵)
模擬鼠標(biāo)點(diǎn)擊(左鍵、右鍵,可指定坐標(biāo))
支持絕對(duì)坐標(biāo)定位
可自定義點(diǎn)擊間隔和范圍
2. 代碼結(jié)構(gòu)
2.1 InputSimulator類(lèi)
負(fù)責(zé)封裝所有輸入模擬相關(guān)方法。
class InputSimulator:
def __init__(self):
self.user32 = ctypes.WinDLL('user32', use_last_error=True)
# ... 定義各種常量 ...
主要方法
press_key(key_code):模擬按鍵按下release_key(key_code):模擬按鍵釋放key_press(key_code, duration=0.1):完整按鍵(按下+延時(shí)+釋放)click_mouse(x=None, y=None):模擬鼠標(biāo)左鍵點(diǎn)擊(可指定坐標(biāo))right_click_mouse(x=None, y=None):模擬鼠標(biāo)右鍵點(diǎn)擊(可指定坐標(biāo))
2.2 結(jié)構(gòu)體定義
使用ctypes定義Windows API所需的結(jié)構(gòu)體:
class MOUSEINPUT(ctypes.Structure):
_fields_ = (
("dx", wintypes.LONG),
("dy", wintypes.LONG),
("mouseData", wintypes.DWORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", ctypes.POINTER(wintypes.ULONG))
)
# 還有 KEYBDINPUT 和 INPUT 結(jié)構(gòu)體
2.3 示例用法
主程序部分演示了如何自動(dòng)點(diǎn)擊:
if __name__ == "__main__":
import keyboard
import random
simulator = InputSimulator()
print("程序已啟動(dòng),按Q鍵退出...")
while True:
if keyboard.is_pressed('q'):
print("檢測(cè)到Q鍵,程序退出")
break
x = random.randint(1000, 1100)
y = random.randint(700, 800)
simulator.click_mouse(x, y)
time.sleep(random.uniform(0.05, 0.1))
- 隨機(jī)生成點(diǎn)擊坐標(biāo)
- 按Q鍵可隨時(shí)退出
3. 技術(shù)要點(diǎn)
ctypes調(diào)用user32.dll:實(shí)現(xiàn)底層輸入模擬
支持絕對(duì)坐標(biāo):通過(guò)65535縮放映射屏幕坐標(biāo)
結(jié)構(gòu)體封裝:與Windows API參數(shù)完全兼容
可擴(kuò)展性強(qiáng):可根據(jù)需要添加更多輸入事件
4. 注意事項(xiàng)
僅支持Windows系統(tǒng)
需管理員權(quán)限
請(qǐng)勿在重要操作界面誤用
5. 應(yīng)用場(chǎng)景
- 自動(dòng)化測(cè)試
- 游戲腳本
- 重復(fù)性辦公自動(dòng)化
- 系統(tǒng)集成測(cè)試
完整代碼見(jiàn)下方:
import ctypes
import time
from ctypes import wintypes
class InputSimulator:
def __init__(self):
self.user32 = ctypes.WinDLL('user32', use_last_error=True)
# Windows API 常量
self.INPUT_MOUSE = 0
self.INPUT_KEYBOARD = 1
self.KEYEVENTF_KEYUP = 0x0002
self.KEYEVENTF_UNICODE = 0x0004
self.MOUSEEVENTF_LEFTDOWN = 0x0002
self.MOUSEEVENTF_LEFTUP = 0x0004
self.MOUSEEVENTF_RIGHTDOWN = 0x0008
self.MOUSEEVENTF_RIGHTUP = 0x0010
self.MOUSEEVENTF_MOVE = 0x0001
self.MOUSEEVENTF_ABSOLUTE = 0x8000
def press_key(self, key_code):
"""模擬按鍵按下"""
x = INPUT(type=self.INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=key_code))
self.user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def release_key(self, key_code):
"""模擬按鍵釋放"""
x = INPUT(type=self.INPUT_KEYBOARD,
ki=KEYBDINPUT(wVk=key_code,
dwFlags=self.KEYEVENTF_KEYUP))
self.user32.SendInput(1, ctypes.byref(x), ctypes.sizeof(x))
def key_press(self, key_code, duration=0.1):
"""模擬完整的按鍵過(guò)程"""
self.press_key(key_code)
time.sleep(duration)
self.release_key(key_code)
def click_mouse(self, x=None, y=None):
"""模擬鼠標(biāo)點(diǎn)擊
參數(shù):
x: 鼠標(biāo)x坐標(biāo)(可選)
y: 鼠標(biāo)y坐標(biāo)(可選)
"""
if x is not None and y is not None:
screen_width = self.user32.GetSystemMetrics(0)
screen_height = self.user32.GetSystemMetrics(1)
x = int(x * 65535 / screen_width)
y = int(y * 65535 / screen_height)
move = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dx=x, dy=y,
dwFlags=self.MOUSEEVENTF_MOVE | self.MOUSEEVENTF_ABSOLUTE))
self.user32.SendInput(1, ctypes.byref(move), ctypes.sizeof(move))
time.sleep(0.1)
down = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_LEFTDOWN))
self.user32.SendInput(1, ctypes.byref(down), ctypes.sizeof(down))
time.sleep(0.1)
up = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_LEFTUP))
self.user32.SendInput(1, ctypes.byref(up), ctypes.sizeof(up))
def right_click_mouse(self, x=None, y=None):
"""模擬鼠標(biāo)右鍵點(diǎn)擊"""
if x is not None and y is not None:
screen_width = self.user32.GetSystemMetrics(0)
screen_height = self.user32.GetSystemMetrics(1)
x = int(x * 65535 / screen_width)
y = int(y * 65535 / screen_height)
move = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dx=x, dy=y,
dwFlags=self.MOUSEEVENTF_MOVE | self.MOUSEEVENTF_ABSOLUTE))
self.user32.SendInput(1, ctypes.byref(move), ctypes.sizeof(move))
time.sleep(0.1)
down = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_RIGHTDOWN))
self.user32.SendInput(1, ctypes.byref(down), ctypes.sizeof(down))
time.sleep(0.1)
up = INPUT(type=self.INPUT_MOUSE,
mi=MOUSEINPUT(dwFlags=self.MOUSEEVENTF_RIGHTUP))
self.user32.SendInput(1, ctypes.byref(up), ctypes.sizeof(up))
# 保持原有的結(jié)構(gòu)體定義
class MOUSEINPUT(ctypes.Structure):
_fields_ = (
("dx", wintypes.LONG),
("dy", wintypes.LONG),
("mouseData", wintypes.DWORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", ctypes.POINTER(wintypes.ULONG))
)
class KEYBDINPUT(ctypes.Structure):
_fields_ = (
("wVk", wintypes.WORD),
("wScan", wintypes.WORD),
("dwFlags", wintypes.DWORD),
("time", wintypes.DWORD),
("dwExtraInfo", ctypes.POINTER(wintypes.ULONG))
)
class INPUT(ctypes.Structure):
class _INPUT(ctypes.Union):
_fields_ = (
("mi", MOUSEINPUT),
("ki", KEYBDINPUT)
)
_anonymous_ = ("_input",)
_fields_ = (
("type", wintypes.DWORD),
("_input", _INPUT)
)
# 使用示例
if __name__ == "__main__":
"""
# 創(chuàng)建模擬器實(shí)例
simulator = InputSimulator()
# 示例:模擬按下A鍵
simulator.key_press(0x41)
# 示例:模擬鼠標(biāo)點(diǎn)擊
simulator.click_mouse()
# 示例:在指定位置右鍵點(diǎn)擊
simulator.right_click_mouse(100, 100)
"""
import keyboard
import random
simulator = InputSimulator()
print("程序已啟動(dòng),按Q鍵退出...")
while True:
if keyboard.is_pressed('q'):
print("檢測(cè)到Q鍵,程序退出")
break
# 隨機(jī)坐標(biāo)(在1000-1100和700-800范圍內(nèi))
x = random.randint(1000, 1100)
y = random.randint(700, 800)
# # 模擬鼠標(biāo)右鍵點(diǎn)擊
# simulator.right_click_mouse(x, y)
# time.sleep(random.uniform(0.05, 0.1))
# 模擬鼠標(biāo)左鍵點(diǎn)擊
simulator.click_mouse(x, y)
time.sleep(random.uniform(0.05, 0.1))
到此這篇關(guān)于Python實(shí)現(xiàn)Windows鍵盤(pán)鼠標(biāo)自動(dòng)化模擬器的文章就介紹到這了,更多相關(guān)Python模擬鍵盤(pán)鼠標(biāo)操作內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 給屏幕打印信息加上顏色的實(shí)現(xiàn)方法
這篇文章主要介紹了Python 給屏幕打印信息加上顏色的實(shí)現(xiàn)方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-04-04
python通過(guò)exifread模塊獲得圖片exif信息的方法
這篇文章主要介紹了python通過(guò)exifread模塊獲得圖片exif信息的方法,實(shí)例分析了Python操作exifread模塊的技巧,需要的朋友可以參考下2015-03-03
Python爬蟲(chóng)獲取全網(wǎng)招聘數(shù)據(jù)實(shí)現(xiàn)可視化分析示例詳解
這篇文章主要介紹了Python爬蟲(chóng)獲取全網(wǎng)招聘數(shù)據(jù)實(shí)現(xiàn)可視化分析示例詳解,實(shí)現(xiàn)采集一下最新的qcwu招聘數(shù)據(jù),本文列舉了部分代碼以及實(shí)現(xiàn)思路,需要的朋友可以參考下2023-07-07
Scrapy基于Python構(gòu)建強(qiáng)大網(wǎng)絡(luò)爬蟲(chóng)框架實(shí)例探究
這篇文章主要為大家介紹了Scrapy基于Python構(gòu)建強(qiáng)大網(wǎng)絡(luò)爬蟲(chóng)框架實(shí)例探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
pyinstaller打包程序后閃退問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于pyinstaller打包程序后閃退問(wèn)題的解決方法,閃退原因可能有很多這里記錄下我遇到的問(wèn)題,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11
Python實(shí)現(xiàn)柵欄密碼的加密解密方法詳解
這篇文章主要介紹了Python實(shí)現(xiàn)柵欄密碼的加密解密方法,所謂柵欄密碼,就是把要加密的明文分成N個(gè)一組,然后把每組的第1個(gè)字連起來(lái),形成一段無(wú)規(guī)律的話。不過(guò)柵欄密碼本身有一個(gè)潛規(guī)則,就是組成柵欄的字母一般不會(huì)太多2023-01-01
Python實(shí)戰(zhàn)之大魚(yú)吃小魚(yú)游戲的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Python制作一個(gè)經(jīng)典游戲之大魚(yú)吃小魚(yú),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python有一定幫助,需要的可以參考一下2022-04-04

