QMT 验证码无法自动登录的问题

1,516 阅读5分钟

背景

为了不用考虑断网、断电的问题,我直接把 QMT 放在了 windows 服务器上运行,并且开启了「自动初始化」功能,每天的 9:20 和 20:50 都会重启应用。

但是!!!偶尔会碰到需要填验证码的情况,我就很纳闷,都点了自动登录了,还加个验证码,这是什么逻辑?!?!?!

image.png

这就导致我需要时不时的就登录服务器去看一下,有的时候赶巧了,好几天策略都没跑,简直!@FRQ#@$!@#!@#……

在技术群里也反馈这个问题了,也毫无结果,得,自己写个脚本搞定吧。

正文

原理

原理其实很简单:如果出现了验证码,那么关掉窗口,重新启动一下就好了。

所以,我们只需要在启动程序 60s 后,判断是否还是停留在登录界面(也就是登录失败),是的话重启应用就可以了。这个用 Python 实现不难。

然后就是每天定时运行这个 Python 脚本就可以了,这个用 windows 自带的「计划任务」功能就可以了。

下面先给出脚本的代码,然后再写一下使用步骤,其实还是有一些小门槛的。

import time
import pywinauto as pw

EXE_NAME = "XtItClient.exe"
EXE_PATH = r'C:\iQuant\bin.x64\XtItClient.exe'
EXE_TITLE_RE = "国信iQuant策略交易平台 *" # Change if needed
LOGIN_TIME = 60 # Time to wait for the login

def login():
    try:
        proc_id = pw.application.process_from_module(EXE_NAME)
        print('proc_id:', proc_id)
        app = pw.application.Application(backend="uia").connect(process=proc_id)
        app.kill()
    except Exception:
        pass
    
    app = pw.Application(backend='uia').start(EXE_PATH, timeout=10)
    time.sleep(5)

    try:
        # Wait for the login window to disappear
        time.sleep(LOGIN_TIME)
        login_window = app.window(title_re=EXE_TITLE_RE, control_type="Pane")
        login_window.wait('visible', timeout=1)
        print('Login failed, retrying...')
        login()
    except (pw.findwindows.ElementNotFoundError, pw.timings.TimeoutError):
        print('Login successful!')

if __name__ == '__main__':
    login()

注意:

  1. LOGIN_TIME 是等待几秒后检查是否登录成功,如果机器比较慢或者网络比较慢,把这个值改大点即可。

  2. 代码中的 EXE_TITLE_RE 是 QMT 程序启动时的 title,是个正则值。只要把鼠标 hover 到任务栏中正在运行的应用上,就能看到了。各位同学使用的券商可能不一样,修改一下就可以了。因为是正则,所以忽略后面的版本号即可。

    image.png

使用步骤

1. 自动登录 QMT

首先我们先人工登录一下 QMT 程序,登录的时候勾选「记住密码」和「自动登录」,如下图:

image.png

登录后把「账号自动登录」和「策略自动运行」配置好,然后关闭「自动重启设置」里面的两个选项,取消勾选,如下图:

image.png

保证我们每次打开程序,不需要输入用户名和密码,能够自动登录程序即可。

2. 测试脚本

  1. 在服务器上安装 Python,把上面的代码复制生成 auto_login.py 文件;
  2. 如需要,修改脚本中的变量;
  3. pip install pywinauto
  4. 运行脚本 py auto_login.py 查看效果。

3. 新建计划任务

笔者之前写过一篇 《如何在 windows 服务器上开机启动程序》大概介绍了一下「计划任务」怎么用,那个时候还没有完全解决这个问题,不过可以当作入门教程来看。如何新建任务这里就不展开了,只说几个要点:

  1. 因为依赖 pywinauto,所以一定要有 GUI 环境才能运行,也就是说要勾选「只在用户登录时运行」才可以; image.png
  2. 触发时间设置为每周一到周五 image.png
  3. 操作这里,「程序」一定要填 python.exe 的地址,不能直接写脚本地址,否则会跳出选项让你选择用什么程序运行。脚本地址写在「添加参数」里面。 image.png
  4. 新建成功后,记得运行测试一下,是否能成功运行脚本。 image.png

4. 用 VNC 保持服务器的 GUI 会话

做完了以上的工作,本以为完成了,结果第二天登录一看,脚本根本没有运行。后来才知道,原来关闭与服务器的连接之后,GUI 会话就关闭了。没有 GUI 环境,pywinauto 是无法正常运行的。问过 ChatGPT 之后,终于找到了解决办法。

我把它整理成了另一篇文章:《解决windows服务器「计划任务」无法运行GUI脚本的问题》,笔者用的是 TightVNC,具体的操作我就不在这里重复了,大家看这篇文章即可。

搞完了才知道,用 Windows 服务器也是分 Level 的:

  • 菜鸟:云服务网页登录;
  • 老手:.rdp windows 远程桌面;
  • 高手:.vnc VNC Server 应用。

总结

按照上面的步骤搞完,QMT 自动登录问题就解决了。写下来才发现,好像也挺复杂的。只是笔者有「计划任务」和「VNC」的知识储备,所以觉得不太难。现在回想起来,当时也是踩了不少坑的。不过很值得,因为笔者还有其它功能也需要依赖这些。

说远了,说回 QMT 自动登录。因为现在我的策略还很简单,所以用的服务器是最低配的「2核4G」,还算便宜,不过随着后面策略的复杂度增加,这个配置估计就不太够用了。于是笔者绞尽脑汁,终于找到了一个终极版省钱办法,我把它整理成了《省钱妙招:windows服务器开机登录GUI》一文,有兴趣的同学可以看看。