1、需求说明
希望能实现自动化加V,但又不能让使用者知道具体的手机号,确保隐私;另外,这里未进行封装和对接,仅一个DEMO。
效果示例【窗口有一个遮羞/遮挡功能】:
2、相关依赖
import wxauto
import sys, os, win32gui, win32con, win32api, subprocess, time
import pyautogui
import uiautomation as uia
from pynput import mouse, keyboard
import wx
这些库提供了对微信窗口的控制、自动化操作以及系统级别的事件监听(如鼠标和键盘)等功能。
3、相关功能
(1)事件监听模块 (EventListener
)
代码中定义了 EventListener
类,用于检测用户的干预行为(鼠标或键盘操作),从而在脚本运行中可以及时停止。这个类实现了一个事件监听器,主要用于捕捉用户是否有鼠标或键盘操作:
# 监听鼠标和键盘事件,用于检测用户的干预行为
class EventListener:
def __init__(self):
self.mouse_listener = mouse.Listener(on_move=self.on_move, on_click=self.on_click, on_scroll=self.on_scroll)
self.keyboard_listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
self.interrupted = False
# 启动监听器
def start(self):
self.mouse_listener.start()
self.keyboard_listener.start()
# 停止监听器
def stop(self):
self.mouse_listener.stop()
self.keyboard_listener.stop()
# 当鼠标移动时,触发中断
def on_move(self, x, y):
self.interrupt()
# 当鼠标点击时,触发中断
def on_click(self, x, y, button, pressed):
self.interrupt()
# 当鼠标滚轮滚动时,触发中断
def on_scroll(self, x, y, dx, dy):
self.interrupt()
# 当键盘按下时,触发中断
def on_press(self, key):
self.interrupt()
# 当键盘释放时,触发中断
def on_release(self, key):
self.interrupt()
# 中断处理函数
def interrupt(self):
if not self.interrupted:
self.interrupted = True
print("检测到用户干预,停止脚本运行。")
sys.exit(0)
(2)微信遮罩窗口模块 (MaskWindow
)
在微信窗口上创建一个透明的具备鼠标穿透功能的遮罩窗口,以避免用户不小心干扰到窗口内部操作:
- 初始化遮罩窗口:获取微信窗口的坐标和大小,然后创建一个透明的遮罩窗口并设置其位置与微信窗口一致。
- SetMouseThrough:设置鼠标穿透功能,确保遮罩窗口不会阻挡用户鼠标对微信窗口的操作。
- close:用于关闭遮罩窗口。
# 创建微信窗口大小的遮罩窗口
class MaskWindow(wx.Frame):
def __init__(self, hwnd):
# 获取微信窗口的坐标和大小
rect = win32gui.GetWindowRect(hwnd)
x, y, width, height = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
# 创建透明的遮罩窗口
wx.Frame.__init__(self, None, style=wx.NO_BORDER | wx.STAY_ON_TOP)
self.SetPosition((x, y))
self.SetSize((width, height))
self.SetTransparent(200) # 设置透明度,值范围0-255
self.Show()
self.SetMouseThrough(True)
# 设置鼠标穿透功能
def SetMouseThrough(self, through=True):
hwnd = self.GetHandle()
ex_style = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
if through:
ex_style |= win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
else:
ex_style &= ~(win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT)
win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style)
def GetHandle(self):
return self.Handle # 直接使用self.Handle以获取窗口句柄
def close(self):
self.Close()
(3)微信启动及窗口检测模块 (StartWeChat
)
(4)添加好友功能模块 (AddNewFriend
)
4、完整代码
import wxauto
import sys, os, win32gui, win32con, win32api, subprocess, time
import pyautogui
import uiautomation as uia
from pynput import mouse, keyboard
import wx
# 监听鼠标和键盘事件,用于检测用户的干预行为
class EventListener:
def __init__(self):
self.mouse_listener = mouse.Listener(on_move=self.on_move, on_click=self.on_click, on_scroll=self.on_scroll)
self.keyboard_listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
self.interrupted = False
# 启动监听器
def start(self):
self.mouse_listener.start()
self.keyboard_listener.start()
# 停止监听器
def stop(self):
self.mouse_listener.stop()
self.keyboard_listener.stop()
# 当鼠标移动时,触发中断
def on_move(self, x, y):
self.interrupt()
# 当鼠标点击时,触发中断
def on_click(self, x, y, button, pressed):
self.interrupt()
# 当鼠标滚轮滚动时,触发中断
def on_scroll(self, x, y, dx, dy):
self.interrupt()
# 当键盘按下时,触发中断
def on_press(self, key):
self.interrupt()
# 当键盘释放时,触发中断
def on_release(self, key):
self.interrupt()
# 中断处理函数
def interrupt(self):
if not self.interrupted:
self.interrupted = True
print("检测到用户干预,停止脚本运行。")
sys.exit(0)
# 创建微信窗口大小的遮罩窗口
class MaskWindow(wx.Frame):
def __init__(self, hwnd):
# 获取微信窗口的坐标和大小
rect = win32gui.GetWindowRect(hwnd)
x, y, width, height = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
# 创建透明的遮罩窗口
wx.Frame.__init__(self, None, style=wx.NO_BORDER | wx.STAY_ON_TOP)
self.SetPosition((x, y))
self.SetSize((width, height))
self.SetTransparent(200) # 设置透明度,值范围0-255
self.Show()
self.SetMouseThrough(True)
# 设置鼠标穿透功能
def SetMouseThrough(self, through=True):
hwnd = self.GetHandle()
ex_style = win32api.GetWindowLong(hwnd, win32con.GWL_EXSTYLE)
if through:
ex_style |= win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT
else:
ex_style &= ~(win32con.WS_EX_LAYERED | win32con.WS_EX_TRANSPARENT)
win32api.SetWindowLong(hwnd, win32con.GWL_EXSTYLE, ex_style)
def GetHandle(self):
return self.Handle # 直接使用self.Handle以获取窗口句柄
def close(self):
self.Close()
# 启动微信,并返回微信对象和窗口句柄
def StartWeChat(chatroom):
try:
Wx = wxauto.WeChat()
win = win32gui.FindWindow('WeChatMainWndForPC', chatroom)
if win != 0:
win32gui.ShowWindow(win, win32con.SW_SHOWNORMAL)
win32gui.SetForegroundWindow(win)
print('微信已启动成功')
return Wx, win
except:
print(f'找不到【{chatroom}】窗口,尝试启动微信...')
wechat_path = r"C:\Program Files\Tencent\WeChat\WeChat.exe"
if os.path.exists(wechat_path):
subprocess.Popen(wechat_path)
time.sleep(5)
win = win32gui.FindWindow('WeChatMainWndForPC', chatroom)
if win != 0:
print("微信已启动并找到窗口")
win32gui.ShowWindow(win, win32con.SW_SHOWNORMAL)
win32gui.SetForegroundWindow(win)
else:
print("仍无法找到微信窗口,请检查路径和微信是否正常启动")
sys.exit(0)
else:
print("微信路径无效,请检查路径是否正确")
sys.exit(0)
return None
# 关闭空白提示窗口
def close_NullWindow():
UiaAPI = uia.WindowControl(ClassName='WeChatMainWndForPC', searchDepth=1)
windows = UiaAPI.GetChildren()
for window in windows:
try:
if window.Name == "":
window.SetActive()
pyautogui.hotkey('alt', 'f4')
if "无法找到该用户,请检查你填写的账号是否正确" in window.Name:
print("找到提示信息: 无法找到该用户,请检查你填写的账号是否正确")
except Exception as e:
print(f"访问窗口失败或关闭失败: {e}")
# 添加微信好友
def AddNewFriend(phone, addmsg, remark, tags):
try:
close_NullWindow()
wechat.SwitchToChat()
time.sleep(1)
print(f"添加好友,手机号: {phone}")
wechat.AddNewFriend(phone, addmsg=addmsg, remark=remark, tags=tags)
except LookupError as e:
if "Find Control Timeout" in str(e):
print(f"{phone} 已是好友,跳过添加")
close_NullWindow()
else:
print(f"发生意外错误: {e}")
close_NullWindow()
except Exception as e:
print(f"添加好友时出错: {e}")
close_NullWindow()
# 主程序入口
if __name__ == "__main__":
listener = EventListener()
listener.start()
app = wx.App(False)
# 启动微信并获取句柄
wechat, hwnd = StartWeChat("微信")
print(wechat, hwnd)
if wechat and hwnd:
# 创建与微信窗口大小相同的遮罩窗口
mask_window = MaskWindow(hwnd)
# 添加好友的手机号列表
phones = ['1111111111111']
addmsg = '申请语' # 添加好友的消息
remark = '备注'
tags = ['*******']
for phone in phones:
if listener.interrupted:
break
AddNewFriend(phone, addmsg, remark, tags)
time.sleep(1)
# 切换至微信主界面
wechat.SwitchToChat()
# 等待用户干预
while not listener.interrupted:
time.sleep(0.1)
# 当检测到中断时,关闭遮罩窗口并退出程序
mask_window.close()
listener.stop()
sys.exit(0)
【免责声明】本文章内容仅供个人学习、研究和欣赏之用,严禁用于任何商业用途。另内容未经授权,禁止转载或用于商业用途。如有侵权行为,请及时联系及处理。