系列文章目录
py实现win自动化自动登陆qq
前言
之前都是网页自动化感觉太容易了,就来尝尝win自动化,就先写了一个qq登陆的,这个是拿到className 然后进行点击等。
一、上代码?
示例:
import psutil
import time
import os
from pywinauto import Application
from pywinauto.findwindows import find_window
from pywinauto.timings import WaitUntil
from pywinauto import mouse
class QQAutomator:
def __init__(self):
self.app = None
self.main_window = None
self.qq_path = r'D:\itveteranISTool\itveteranExe\qq\QQ.exe'
def kill_qq_process(self):
"""终止QQ相关进程"""
for proc in psutil.process_iter(['pid', 'name']):
if proc.info['name'] and proc.info['name'].lower() in ('qq.exe', 'qqschat.exe'):
try:
proc.kill()
time.sleep(1)
print(f"已终止进程:{proc.info['name']}")
except Exception as e:
print(f"终止失败:{e}")
def find_qq_window(self, timeout=30):
"""定位QQ窗口并打印详细信息"""
start_time = time.time()
while time.time() - start_time < timeout:
try:
window = self.app.window(
class_name="Chrome_WidgetWin_1",
control_type="Pane",
title_re=".*QQ.*"
)
if window.exists():
self._print_window_details(window)
return window
except Exception as e:
print(f"窗口定位尝试失败:{str(e)}")
time.sleep(1)
return None
def _print_window_details(self, window):
"""打印窗口详细信息"""
print("=" * 60)
print(f"窗口句柄: {window.handle}")
print(f"窗口标题: {window.window_text()}")
print(f"类名: {window.class_name()}")
print(f"坐标范围: {window.rectangle()}")
print("控件层次结构:")
self._print_control_tree(window, level=0)
print("=" * 60)
def _print_control_tree(self, control, level=0, max_depth=3):
"""递归打印控件树结构"""
if level > max_depth:
return
prefix = " " * level + "└─ "
try:
info = f"{prefix}[{control.friendly_class_name()}] {control.element_info.name}"
print(info)
for child in control.children():
self._print_control_tree(child, level + 1, max_depth)
except:
pass
def click_button(self, button_title, retry=3):
"""优化后的点击方法"""
for attempt in range(retry):
try:
# 更精准的定位方式
btn = self.main_window.child_window(
title=button_title,
control_type="Button",
found_index=0
).wait('ready', timeout=5)
if btn.is_visible() and btn.is_enabled():
print(f"点击按钮 [{button_title}] (第{attempt+1}次尝试)")
btn.click_input()
return True
# 新增调试信息
print(f"按钮状态:visible={btn.is_visible()}, enabled={btn.is_enabled()}")
except Exception as e:
print(f"按钮定位失败: {str(e)}")
time.sleep(2)
return False
def run(self):
"""修复后的主流程"""
self.kill_qq_process()
if not os.path.exists(self.qq_path):
print("路径无效!")
return
try:
# 增加启动等待
self.app = Application(backend='uia').start(self.qq_path)
time.sleep(1) # 等待主进程初始化
# 增强窗口定位
self.main_window = self.find_qq_window(timeout=40)
if not self.main_window:
print("窗口定位失败,尝试备用方案...")
qq_procs = [p for p in psutil.process_iter() if 'qq' in p.name().lower()]
if qq_procs:
hwnd = find_window(process=qq_procs[0].pid)
self.main_window = self.app.window(handle=hwnd)
if not self.main_window:
print("❌ 无法定位窗口,退出程序")
return
# 打印调试信息
print("="*40)
self.main_window.print_control_identifiers()
print("="*40)
# 保存控件树
self.main_window.print_control_identifiers(filename='control_tree.txt')
# 执行点击操作
# if self.click_button("添加账号"):
# print("已触发添加账号操作")
# time.sleep(3) # 等待弹窗
if self.click_button("登录"):
print("登录请求已发送")
self._verify_login()
except Exception as e:
print(f"主流程异常: {str(e)}")
import traceback
traceback.print_exc()
def _verify_login(self):
"""修复后的登录验证"""
try:
print("正在验证登录状态...")
WaitUntil(30, 2, lambda: any(
p.info['name'] and p.info['name'].lower() in ('qq.exe', 'qqlite.exe')
for p in psutil.process_iter(['name'])
))
print("✅ 检测到QQ主进程,登录成功!")
# 附加验证:检测主窗口变化
main_window = self.app.window(class_name="Chrome_WidgetWin_0")
if main_window.exists():
print("✅ 检测到QQ主界面窗口")
except TimeoutError:
print("❌ 登录验证超时,可能原因:")
print("1. 账号密码错误")
print("2. 需要处理验证码")
print("3. 网络连接异常")
current_procs = [p.name() for p in psutil.process_iter()]
print(f"当前运行进程:{current_procs}")
if __name__ == "__main__":
automator = QQAutomator()
automator.run()
总结
携知云~ 携手创造知识~ 科技是第一生产力,卷起来