明日方舟奇像巡展模式的画面监听 + 自动抓捕工具的基础框架:
- 后台循环执行“向左移动 4 秒 → 向右移动 5 秒”(可配置),期间每帧截屏 OCR,检测到抓捕页标题“奇象收录时间”立即中断移动;
- 进入抓捕页面后,OCR 识别文字:检测“暂未收录”标签(功能2)与选中的目标奇像名称(功能1,名称映射见
qixiang/ocr.py); - 按用户设定的两个功能(功能1 选择目标奇像 / 功能2 自动抓捕尚未收录,or 关系、可同时勾选)判定:
- 不满足 → 按 ESC 退出抓捕页,继续循环;
- 满足 → 保持监控(不按 ESC、不停止),识别到“快捷编队”(C 标记)或用户手动停止才退出工具;
- 前端:用户设置窗口为主窗口(两种功能、目标多选并显示名称与图鉴图片、置顶悬浮窗开关、移动/行为参数),关闭设置窗口即退出程序;置顶悬浮窗仅含开始/停止按钮,可在设置中勾选开关。
┌──────────────────────────────────────────┐
│ │
┌─────────┐ │ ┌───────────────┐ OCR命中“收录时间” │
│ 移动循环 ├───────┼──►│ 每帧截屏 OCR ├────────────────────►│
│ 左4s 右5s│ │ └───────────────┘ │
└─────────┘ │ ▲ │
▲ │ │ 未命中(继续移动) │
│ │ └───────────────────────────────┘
│ │ │
│ │ ┌──────────────────────────────────────┴──────┐
│ │ │ 抓捕页面处理 │
│ │ │ 1. OCR 检测“暂未收录”标签(B) │
│ │ │ 2. OCR 匹配目标奇像名称(功能1) │
│ │ │ 3. 依据功能条件判定(or 关系) │
│ │ └──────────────────────┬──────────────────────┘
│ │ │
│ 按 ESC 退出│ ┌──────────┴──────────┐
│ 继续循环 │ ▼ ▼
│ │ 不满足条件 满足条件
│ │ ┌──────────┐ ┌────────────────┐
└────────────┼──────┤ 按 ESC │ │ 保持监控等待 C │
│ └──────────┘ │ 直到C或手动停止 │
└───────────────────────────┴────────────────┘
主循环实现于 qixiang/automator.py;移动过程中同样持续截屏 OCR,一旦发现抓捕页立即松开按键并进入抓捕处理,保证“无论什么时候都检测”。
判定逻辑为纯函数 should_capture()(qixiang/detector.py),真值表如下:
| 功能1 命中目标名称 | 功能2 OCR识别“暂未收录” | 结果 |
|---|---|---|
| ✓ | - | 抓 |
| - | ✓ | 抓(无需编号) |
| ✓ | ✓ | 抓 |
| ✗ | ✗ | 不抓(ESC) |
说明:
- 抓捕条件 = 两条独立路径的“或”(无兜底关系):
① 功能1:OCR 识别出画面中的奇像名称命中选中的目标(编号 → 名称映射
DEX_NAMES)→ 抓; ② 功能2:OCR 识别到“暂未收录”标签 → 抓(无需编号); 两条都不满足 → 不抓(ESC)。 - 目标识别仅检测选中的目标编号对应的名称(未选中不检测);OCR 个别字误差有容错匹配兜底;
- 两个功能均未勾选时,工具只移动不抓捕(启动时会有警告日志)。
| 组件 | 说明 |
|---|---|
| 用户设置窗口(主窗口) | gui/settings_window.py:双页面切换(窗口大小形状不变、日志位置大小不变、切页清空日志;切换按钮两状态等大、文字居中)——页面一“刷取特定奇像”:功能1(选择目标奇像,全选镜像复选框 + 多选列表带名称与缩略图)、功能2(自动抓捕尚未收录)、置顶悬浮窗开关;页面二“刷取奇象兑换券”:用法(附 assets/help_1.png 位置图示与注意事项)+ 置顶悬浮窗开关(与页面一双向同步);右侧 运行日志 共用;底部 帮助(弹出中等尺寸帮助窗口:简介/识别原理/功能说明/声明,HELP_HTML 可编辑)+ 页面切换按钮 + 开始/停止 + 保存/取消;关闭本窗口即退出程序 |
| 置顶悬浮窗 | gui/float_window.py:无边框、置顶、仅一个“开始/停止”按钮;按住按钮即可拖动窗口(拖动超过阈值不触发点击);WindowDoesNotAcceptFocus 保证点击按钮不抢游戏焦点;显示/隐藏由设置窗口勾选控制 |
线程模型:Qt 主线程跑 GUI;自动化主循环跑在 TaskWorker(QThread) 中(刷取特定奇像 → Automator,刷取奇象兑换券 → TicketGrinder),通过 Qt 信号(log/state/success)回传日志、状态与结果,互不阻塞。
在设置窗口底部点“刷取奇象兑换券”切到刷券页,点“开始”即运行自动循环(无状态步骤表,从任意步骤进入都能接上):
- 检测到“苍苔”+“对话” → 双击“对话”(间隔 0.5 秒)
- 检测到“我想参加娱乐对决” → 双击该选项
- 检测到“快速对决”(需同帧还识别到“不好意思,还是算了吧”,确认处于快速对决页) → 单击
- 检测到“开始对决” → 单击,进入战斗
- 检测到“对决获胜”(橙色)或“再接再厉”(灰色)→ 日志输出一次(下一次“对话”后重置,可再输出)
- 检测到“下一步” → 单击;检测到“返回巡展” → 单击(识别到就点击,无附加条件),回到巡展地图重复
要点:
- 每轮截屏 OCR 一次,只执行一个命中动作后重新识别(画面变化再继续),天然支持中途进入;
- 同一关键字 5 秒冷却(静默跳过),避免画面未变化时对同一按钮连点;
- 防鼠标遮挡:“开始对决/下一步/返回巡展”在屏幕同一位置,点击“开始对决”“下一步”后以及 检测到战斗结束标记(MATCH/ECB)时,自动把鼠标移到屏幕中心,避免光标挡住按钮导致 OCR 识别不到;
- 结果日志在两个“对话”之间只输出一次,带颜色(获胜橙 / 惜败灰);
- 日志实时显示当前点击的按钮与位置(含屏幕尺寸);点击坐标来自 OCR 文字块中心(屏幕坐标,越界自动夹取);
- 两页日志独立:刷取特定奇像与刷取奇象兑换券各有自己的日志区,切换页面互不清空。
- 实现:
qixiang/grinder.py;鼠标点击由qixiang/inputer.py的click_at()(SendInput 鼠标)完成。
| 环节 | 采用方案 | 理由 | 备选路径 |
|---|---|---|---|
| GUI / 悬浮窗 | PySide6 (Qt6) | 原生置顶悬浮窗、无边框、不抢焦点,单进程即可 | Electron/Tauri+Web(置顶悬浮需原生壳,体积大);tkinter(样式弱) |
| 画面捕获 | mss | 快(数百 FPS)、API 简单 | dxcam(DXGI,独占全屏也可捕,更快);pyautogui(慢,不推荐) |
| 画面识别 | Windows 自带 OCR(winocr) | 对窗口尺寸/DPI 缩放鲁棒,无需模板图片与阈值调参;系统 API 零打包体积 | PaddleOCR/RapidOCR(离线模型、体积大);OpenCV 模板匹配(对尺寸变化敏感,已弃用) |
| 按键模拟 | 自实现 SendInput(扫描码,纯 ctypes) | 兼容 VK/扫描码两类读取方式,无第三方依赖;明日方舟 PC 端(Unity)经社区工具验证可注入按键 | 若反外挂过滤注入输入:interception 驱动、硬件级模拟方案 |
| 鼠标模拟 | 自实现 SendInput(绝对坐标,纯 ctypes) | 与键盘同一套注入方式,点击 OCR 文字块中心 | pyautogui(第三方依赖);硬件级方案 |
| 配置持久化 | JSON(data/settings.json) | 透明可手工编辑 | QSettings(注册表);YAML/TOML |
qixiang-auto/
├── main.py # 程序入口(设置主窗口 + 悬浮窗)
├── requirements.txt
├── QixiangAuto.spec # PyInstaller 打包配置(打包时自动生成)
├── dist/QixiangAuto.exe # 打包产物(单文件,可免 Python 运行)
├── qixiang/ # 核心逻辑(不依赖 GUI)
│ ├── config.py # 路径常量、Settings 模型、JSON 读写
│ ├── capture.py # 屏幕捕获(mss → BGR)
│ ├── ocr.py # OCR 识别(winocr)+ 关键文字/名称映射(DEX_NAMES)
│ ├── matcher.py # 模板匹配(已弃用,仅 tools 联调用)
│ ├── inputer.py # 键盘/鼠标输入(SendInput:扫描码按键 + 绝对坐标点击)
│ ├── detector.py # 抓捕判定(纯函数,功能1/功能2 或关系)
│ ├── automator.py # 刷取特定奇像:主循环状态机(移动+OCR监听+抓捕)
│ └── grinder.py # 刷取奇象兑换券:OCR 步骤表循环(识别文字→点击)
├── gui/
│ ├── app.py # 应用控制器 + TaskWorker(QThread,抓捕/刷券通用)
│ ├── float_window.py # 置顶悬浮窗(一个按钮,按住可拖动)
│ ├── settings_window.py # 用户设置窗口(双页面切换)
│ ├── focus.py # 窗口识别与前台恢复(按标题/类名/进程名识别明日方舟)
│ └── tray.py # 程序图标生成(make_app_icon)
├── assets/
│ ├── A.png # 抓捕页截图(仅存档/转写参考,识别已用 OCR 文字)
│ ├── B.png # “暂未收录”标签截图(同上)
│ ├── C.png # “快捷编队”截图(同上)
│ └── dex/001.png ... # 各奇像截图(设置窗口缩略图用;名称映射在 ocr.py)
├── data/
│ ├── settings.json # 用户设置(自动生成)
│ └── settings_history.txt # 设置变更记录(自动生成)
├── logs/run.log # 运行日志
├── tools/
│ ├── test_input.py # 输入自检(记事本/游戏验证 SendInput)
│ └── verify_templates.py # 模板自检(仅联调用,OCR 版不再依赖)
└── tests/smoke_test.py # 离线冒烟测试(判定+OCR 集成+GUI 构建)
:: 1) 创建虚拟环境并安装依赖(Python 3.10+)
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
:: 2) 启动(识别为 Windows 自带 OCR,无需准备模板)
python main.pyOCR 依赖 Windows 自带 OCR 引擎(winocr)与系统中文语言包(Win10/11 中文系统自带)。
识别不再使用模板图片,而是游戏画面文字(映射定义在 qixiang/ocr.py):
| 画面元素 | 关键文字 | 用途 |
|---|---|---|
| A(抓捕页标题) | “收录时间”(奇象收录时间) | 判断进入抓捕页面 |
| B(未收录标签) | “暂未收录” | 功能2 依据 |
| C(取消/返回) | “快捷编队” | 检测到直接停止工具 |
| dex 编号 | 奇像名称(锐爪巨翼兽、高普尼克…共 38 个,DEX_NAMES) |
功能1 目标匹配(OCR 个别字误差有容错) |
若游戏文字有变动(如活动新增奇像),编辑
qixiang/ocr.py的A_TEXT/B_TEXT/C_TEXT/DEX_NAMES即可,无需截图。
刷取特定奇像(默认页面)
- 启动
python main.py(或直接双击打包产物dist/QixiangAuto.exe),**用户设置窗口(主窗口)**自动出现; - 在功能1中勾选目标编号(显示奇像名称,支持“全选”,每项旁有图鉴图片)和/或勾选功能2(自动抓捕尚未收录); 按需勾选“开启置顶悬浮窗”(悬浮窗即时显示);
- 点“保存”(窗口保持打开);工具会自动识别“明日方舟”窗口(标题 + 类名 UnityWndClass + 进程名 Arknights), 无需手动点击游戏窗口;
- 点设置窗口或悬浮窗的“开始”:设置窗口自动最小化、焦点自动切回游戏窗口, 工具开始 左移→右移 循环,每帧截屏 OCR 监听抓捕页;
- 遇到满足条件的奇像 → 保持监控(右侧日志可见判定过程),识别到 C(快捷编队)自动停止并恢复设置窗口; 想再次运行,点“开始”即可;不满足的遭遇会自动按 ESC 跳过;关闭设置窗口即退出程序。
刷取奇象兑换券
- 在底部点“刷取奇象兑换券”切换页面(窗口大小/日志位置不变、日志清空),按钮变为“刷取特定奇像”,点它可切回;
- 点“开始”即启动刷券循环(流程见第 4 节);日志实时显示识别到的步骤与点击坐标;
- 任意时刻点“停止”结束循环;运行中不可切换页面。
| 字段 | 默认 | 说明 |
|---|---|---|
auto_capture_uncaptured |
true | 功能2:自动抓捕尚未收录的奇像(依据 OCR“暂未收录”标签) |
target_ids |
[] | 功能1:目标奇像编号列表(名称映射见 ocr.py DEX_NAMES;空=不启用) |
float_window_enabled |
false | 会话级:不写入/不读取 settings.json,每次启动默认关闭;运行中可勾选开启(仅本次会话) |
move_left_key / move_right_key |
a / d | 移动按键 |
move_left_seconds / move_right_seconds |
4.0 / 5.0 | 左/右移动时长(秒) |
match_threshold |
0.85 | 已废弃(OCR 版无需阈值,保留兼容旧配置) |
multi_scale |
true | 已废弃(OCR 文字识别对尺寸/DPI 缩放鲁棒,无需多尺度,保留兼容旧配置) |
capture_region |
null | 捕获区域 [left, top, width, height],null=全屏 |
esc_cooldown |
1.0 | 按 ESC 后冷却秒数 |
loop_interval |
0.15 | 画面检测间隔(秒;实际受 OCR 耗时约 0.3s 影响) |
- 管理员权限:若游戏以管理员身份运行,工具也需以管理员身份运行,否则按键无效。 打包版 exe 已默认请求管理员权限(启动确认 UAC);源码方式运行需手动“以管理员身份运行”;
- 窗口模式:独占全屏无法被 mss 捕获,请把游戏设为“窗口化/无边框窗口化”;
- OCR 依赖:识别使用 Windows 自带 OCR(winocr),需系统已安装中文语言包(Win10/11 中文系统自带);
- 焦点:工具会自动按窗口特征识别“明日方舟”窗口(标题“明日方舟” + 类名 UnityWndClass +
进程名 Arknights,规则见
gui/focus.py顶部常量),开始时切回焦点并最小化设置窗口; 识别不到会提示“未检测到明日方舟窗口”并取消启动; - 按键无效排查:先运行
python tools/test_input.py(在记事本里自检 SendInput 是否正常); 游戏以管理员身份运行而工具不是时,UIPI 会静默丢弃按键(工具开始运行时会自检并警告); 反外挂过滤注入输入时,SendInput 类方案均无效; - 合规:本框架仅用于个人自动化研究,请遵守游戏服务条款,自担风险。
- 用
dxcam替换 mss(独占全屏 + 更高帧率); - 按窗口标题捕获指定游戏窗口(
win32gui+ 桌面 Duplication); - 全局热键控制开始/停止(
keyboard库); - 若 Windows OCR 识别率不足,可切换 PaddleOCR/RapidOCR(离线模型,打包体积增大);
- 图鉴记录可视化(在设置窗口展示已收录列表)。
已打包产物:dist/QixiangAuto.exe(约 100MB,单文件、无命令行窗口)。
双击即可运行,目标电脑无需安装 Python;exe 已默认请求管理员权限(启动时确认 UAC 弹窗即可,
保证对以管理员身份运行的游戏也能注入按键)。
图标:exe 文件图标与运行时的窗口图标均使用 assets/icon.ico——
exe 图标由打包时 --icon 嵌入;窗口图标由 main.py 运行时从内嵌资源加载(缺失时自动回退到程序绘制的图标)。
打包方式(需先按第 6 节建好虚拟环境):
:: 在项目根目录执行(Windows)
.venv\Scripts\pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple
.venv\Scripts\pyinstaller --noconfirm --clean --onefile --noconsole ^
--name QixiangAuto --icon "assets/icon.ico" --uac-admin ^
--add-data "assets;assets" main.py打包后的路径行为(qixiang/config.py 已适配 PyInstaller 冻结环境):
| 内容 | 位置 |
|---|---|
图片资源 assets/(图标、设置窗口缩略图) |
内嵌在 exe 内(只读) |
设置 data/settings.json、历史、logs/ |
自动生成在 exe 旁边(可写,不丢失) |
OCR 使用 Windows 自带引擎(winocr / winrt),由系统提供,无需随 exe 打包额外模型。
注意事项:
- 管理员权限:exe 带
--uac-admin(manifest 标记 requireAdministrator),每次启动都会弹 UAC 确认框, 确认后以管理员身份运行(保证 SendInput 对管理员游戏有效);源码方式运行python main.py则无此行为, 游戏以管理员运行时需手动“以管理员身份运行”命令行; - 版本约束:依赖中 PySide6 固定为
6.8.x(对应系统 ICU 72)。6.9+ 的 Qt 需要更新版 ICU, 在多数 Win10/11 上启动会报WinError 127 找不到指定的程序,请勿升级; - SmartScreen / 杀软:未签名的单文件 exe 首次运行可能被 Windows SmartScreen 提示“未知发布者”
(点“仍要运行”即可);个别杀软可能误报,用文件夹模式(
--onedir)可降低概率; - 图标更新:
assets/icon.ico改后需重新打包才会生效(资源内嵌在 exe 内)。
tests/smoke_test.py:[core] OK(or 关系判定、B 标记、未知编号安全策略); [gui] 在本仓库的开发沙箱中因 Qt DLL 无法加载而自动跳过(环境缺少特定系统运行库,与代码无关), 请在正常 Windows 10/11 机器上运行python tests/smoke_test.py验证 GUI 构建。- 全部源码通过
python -m compileall编译检查。 - OCR 验证:真实游戏截图冒烟通过——A.png 识别出“收录时间”、B.png 识别出“暂未收录”、 C.png 识别出“快捷编队”;目标名称匹配(含 1 字 OCR 误差容错)命中正常;全屏 1080p 识别约 0.3s/次。
- OCR 集成测试:功能1(目标名称命中)、功能2(暂未收录)、都不满足按 ESC、检测到 C 停止, 四种场景全部通过。
- 刷券集成测试:完整流程两轮(苍苔对话×2 → 娱乐对决×2 → 快速对决 → 开始对决 → 下一步 → 返回巡展 → 循环) 点击序列正确;从“快速对决”等中途步骤进入可接上循环;结果页分屏(再接再厉 → 下一步 → 返回巡展)正常; 无命中不动作、同按钮冷却防连点,全部通过。
- 快速对决确认条件:同帧含“不好意思,还是算了吧”才点击快速对决;无确认或确认分帧均不点击,测试通过。
- 打包产物
dist/QixiangAuto.exe已在本机试运行验证:进程正常启动, 并在 exe 旁自动生成data/、logs/目录(冻结路径行为正确)。
提示:若默认 PyPI 下载慢(尤其国内网络),可加清华镜像安装:
.venv\Scripts\pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple