手游脚本开发实战:图像识别与状态机架构设计
1. 从零到一手游脚本开发的核心逻辑与整体设计1.1 为什么选择脚本而不是直接改内存很多刚接触这个领域的朋友第一反应往往是去逆向游戏客户端、直接修改内存数据。我早期也走过这条路踩过的坑足够写一本小册子。直接改内存确实见效快但问题在于游戏每次热更新内存地址和数据结构就可能全变维护成本极高而且一旦触发服务端的校验逻辑轻则回档重则封号。相比之下脚本走的是“模拟人类操作”的路线——它不碰游戏进程内部只是在系统层面模拟点击、滑动、识图从游戏的角度看和一个真实玩家在操作几乎没有区别。这就是脚本方案的核心优势低侵入性。它不依赖游戏的具体版本号只要UI布局没有大改脚本就能继续跑。对于需要长期稳定运行的场景来说这个特性比什么都重要。当然脚本也不是万能的。它的短板在于响应速度受限于图像识别和模拟操作的耗时通常单次操作在几十到几百毫秒之间对于需要毫秒级反应的竞技类操作脚本天然不占优势。所以脚本更适合那些重复性高、节奏相对固定的任务场景比如日常任务、资源采集、挂机刷本这类。1.2 整体架构感知、决策、执行三层分离一个能长期迭代、不至于写成一坨面条的脚本架构上一定要做分层。我习惯把它拆成三层感知层负责“看”。包括截屏、图像匹配、颜色检测、OCR文字识别。这一层的输出是结构化的游戏状态数据比如“当前在哪个界面”“某个按钮在什么坐标”“血条还剩多少”。决策层负责“想”。根据感知层传来的状态决定下一步做什么。比如检测到体力不足就决定去领体力检测到战斗结束就决定点结算按钮。执行层负责“做”。把决策层的指令翻译成具体的点击、滑动、长按操作并处理操作后的等待和重试。这么分的好处是当游戏UI改版时你只需要改感知层的匹配模板当游戏玩法调整时你只需要改决策层的状态机。各层之间通过明确的数据接口通信互不干扰。我见过太多人把所有逻辑塞在一个大循环里结果改一个按钮坐标要翻遍整个文件迭代效率极低。1.3 技术选型不同平台的工具对比选什么工具取决于你的目标平台和自身技术栈。下面这张表是我实际用过的几套方案对比方案适用平台开发语言上手难度运行稳定性适合场景Airtest安卓/iOS/WindowsPython低中高快速原型、跨平台按键精灵安卓/Windows自有脚本语言极低中简单重复操作Auto.js安卓JavaScript中高安卓原生、免rootAppium安卓/iOS多语言中高高需要精确控件定位自研图像方案全平台Python/C高取决于实现特殊需求、极致性能我个人的主力方案是Python OpenCV ADB这套组合。原因有三Python的生态足够丰富OpenCV做图像处理成熟稳定ADB是安卓调试的通用接口不依赖任何特定框架。这套组合的灵活性最高遇到任何奇怪的需求都能找到办法实现。注意无论选哪套方案都要确保你的操作方式不违反游戏的服务条款。本文讨论的技术方案仅用于学习自动化和图像识别的工程实践请勿用于任何破坏游戏公平性的场景。2. 核心细节解析图像识别与操作模拟的实操要点2.1 截屏方案的选择与性能影响截屏是感知层的第一步也是整个脚本性能的瓶颈所在。常见的截屏方式有三种ADB截屏通过adb shell screencap命令获取屏幕图像。兼容性最好几乎所有安卓设备都支持。缺点是速度较慢单次截屏加上传输耗时通常在200-500毫秒。minicap一个专门为安卓优化的截屏工具速度可以做到每秒30帧以上。缺点是需要推送二进制文件到设备部分设备需要root权限。系统API截屏在Windows上可以用win32 API在安卓上可以用MediaProjection。速度最快但平台绑定强。对于大多数场景ADB截屏已经够用。如果你的脚本对实时性要求高比如需要快速连点那就要考虑minicap或者降低截屏频率、只在关键节点截屏。这里有个实操技巧不要每次操作前都截全屏。全屏图像的分辨率可能是1080x2400处理起来很慢。我的做法是先用ADB截一次全屏确定关键区域的大致坐标然后后续只截取那个小区域。比如只截取按钮所在的200x100像素区域处理速度能提升十几倍。2.2 图像匹配模板匹配与特征点匹配的取舍图像匹配是感知层的核心。最常用的是模板匹配也就是拿一张事先截好的按钮图片在屏幕图像里找它出现的位置。OpenCV的matchTemplate函数就能做这件事原理是滑动窗口逐像素比对。模板匹配的优点是简单直接缺点是对缩放和旋转敏感。如果游戏在不同分辨率的设备上运行按钮大小会变模板就匹配不上了。解决办法有两个一是针对不同分辨率准备多套模板二是用多尺度匹配把模板缩放到多个尺寸分别匹配取最高分。另一种方案是特征点匹配比如SIFT、ORB这类算法。它提取图像中的关键点和描述子然后做匹配。优点是对缩放、旋转、光照变化都有一定鲁棒性。缺点是计算量大而且对于按钮这种纹理简单的图像特征点可能不够多反而容易匹配失败。我的经验是按钮类元素用模板匹配复杂场景用特征点匹配。比如一个纯色背景上的文字按钮模板匹配又快又准而一个游戏场景中的特定建筑特征点匹配更靠谱。import cv2 import numpy as np def match_template(screen, template, threshold0.8): 在screen中查找template返回中心坐标和匹配度 result cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc cv2.minMaxLoc(result) if max_val threshold: h, w template.shape[:2] center_x max_loc[0] w // 2 center_y max_loc[1] h // 2 return (center_x, center_y), max_val return None, max_val这段代码里threshold的设定很关键。设太高容易漏检设太低容易误检。我的做法是先用一批正常截图跑一遍统计匹配度的分布然后取一个能区分“有”和“没有”的阈值。通常0.8是个不错的起点但具体要看图像质量。2.3 操作模拟点击、滑动与随机化处理执行层的操作看起来简单但细节决定成败。最基础的点击就是ADB的input tap x y命令。但如果你每次都点同一个精确坐标时间长了很容易被检测出异常。所以随机化是必须的。我的做法是在目标坐标周围加一个随机偏移比如±5个像素。同时点击的间隔时间也要随机化不要固定每隔1秒点一次而是在0.8到1.5秒之间随机取值。滑动的轨迹也要注意不要走完美的直线可以加一点弧度或者中途的微小抖动。import random import subprocess import time def random_tap(x, y, offset5): 在(x,y)附近随机点击 rx x random.randint(-offset, offset) ry y random.randint(-offset, offset) subprocess.run(fadb shell input tap {rx} {ry}, shellTrue) time.sleep(random.uniform(0.1, 0.3)) def random_swipe(x1, y1, x2, y2, duration300): 带随机化的滑动 # 在起点和终点加随机偏移 x1 random.randint(-10, 10) y1 random.randint(-10, 10) x2 random.randint(-10, 10) y2 random.randint(-10, 10) # 持续时间也随机化 duration random.randint(-50, 50) subprocess.run( fadb shell input swipe {x1} {y1} {x2} {y2} {duration}, shellTrue )实操心得随机化的程度要适度。偏移太大可能导致点不中按钮太小又起不到作用。我一般把偏移控制在按钮尺寸的10%以内时间随机范围控制在基准值的±30%左右。2.4 状态机设计让脚本知道“现在该做什么”脚本最容易出问题的地方不是识别不准而是状态混乱。比如脚本以为自己在主界面实际上弹出了一个公告窗口结果后续所有操作全部错位。解决这个问题的标准方案是有限状态机。状态机的核心思想是脚本在任何时刻都处于一个明确的状态每个状态有对应的识别特征和可执行的动作。比如状态“主界面”特征是屏幕下方有“冒险”“背包”“商店”三个按钮。可执行动作点击“冒险”。状态“战斗中”特征是屏幕上方有血条下方有技能按钮。可执行动作等待或释放技能。状态“结算界面”特征是屏幕中央有“胜利”或“失败”文字。可执行动作点击“确认”。每次循环脚本先识别当前状态然后执行该状态下的动作动作执行后再重新识别状态。这样就形成了一个闭环即使中间出现了意外弹窗只要为弹窗定义一个状态和处理动作脚本就能自动恢复。class GameState: def __init__(self, name, detector, action): self.name name self.detector detector # 返回True/False的函数 self.action action # 执行动作的函数 class StateMachine: def __init__(self): self.states [] self.current_state None def add_state(self, state): self.states.append(state) def run_once(self, screen): for state in self.states: if state.detector(screen): self.current_state state state.action() return state.name return unknown这个框架看起来简单但扩展性极强。你可以为每个状态单独调参、单独加日志排查问题时一目了然。3. 实操过程从环境搭建到完整脚本运行3.1 环境准备Python、ADB与OpenCV的安装配置先把基础环境搭起来。你需要一台电脑Windows/Mac/Linux都行、一部安卓设备或者模拟器、一根数据线。第一步安装Python。建议用3.8以上的版本太老的版本有些库不支持。安装时记得勾选“Add Python to PATH”。第二步安装必要的库pip install opencv-python numpy pillow第三步下载ADB工具。Windows用户可以直接下载platform-tools压缩包解压后把路径加到系统环境变量里。Mac用户可以用brew install android-platform-tools。Linux用户用包管理器安装即可。第四步连接设备。用数据线把手机连到电脑在手机开发者选项里打开“USB调试”。然后在命令行输入adb devices如果看到设备列表里有一串序列号说明连接成功。如果是模拟器通常需要先启动模拟器ADB会自动识别。注意不同品牌的手机开启开发者选项的方式不同通常在“关于手机”里连续点击“版本号”七次就能激活。如果ADB识别不到设备检查数据线是否支持数据传输有些线只能充电以及是否安装了对应的USB驱动。3.2 编写第一个可运行的脚本框架环境好了先写一个最小的可运行框架验证整条链路是否通畅。import cv2 import numpy as np import subprocess import time import os class GameBot: def __init__(self, adb_pathadb): self.adb adb_path self.screen_dir screens os.makedirs(self.screen_dir, exist_okTrue) def screenshot(self, filenamecurrent.png): 截屏并拉取到本地 remote_path /sdcard/screen.png local_path os.path.join(self.screen_dir, filename) subprocess.run(f{self.adb} shell screencap -p {remote_path}, shellTrue) subprocess.run(f{self.adb} pull {remote_path} {local_path}, shellTrue) return cv2.imread(local_path) def find_and_tap(self, template_path, threshold0.8): 找到模板并点击 screen self.screenshot() template cv2.imread(template_path) if screen is None or template is None: return False result cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc cv2.minMaxLoc(result) if max_val threshold: h, w template.shape[:2] cx max_loc[0] w // 2 cy max_loc[1] h // 2 subprocess.run(f{self.adb} shell input tap {cx} {cy}, shellTrue) return True return False if __name__ __main__: bot GameBot() # 先截一张图看看 img bot.screenshot(test.png) print(f截图尺寸: {img.shape if img is not None else 失败})运行这段代码如果能在screens目录下看到截图文件说明截屏链路通了。接下来准备一张按钮的模板图片调用find_and_tap测试点击功能。3.3 模板制作与匹配阈值调优模板制作是个细致活。我的标准流程是在游戏里截一张包含目标按钮的完整截图。用图像编辑工具比如画图、GIMP、Photoshop把按钮区域裁剪出来保存为PNG。裁剪时注意不要包含太多背景只保留按钮本身和一点点边缘。背景越多匹配时受干扰越大。如果按钮有多个状态比如普通态和按下态分别制作模板。阈值调优的方法准备20张正常截图和20张不含目标按钮的截图分别跑匹配记录最高匹配度。正常截图的匹配度应该明显高于异常截图。取两者之间的一个值作为阈值。如果两者有重叠说明模板质量不够好需要重新裁剪或者换用其他识别方法。3.4 完整任务流程的实现与调试假设我们要实现一个“自动刷副本”的流程状态机大概是这样def detect_main_screen(screen): 检测是否在主界面 template cv2.imread(templates/adventure_btn.png) result cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) return cv2.minMaxLoc(result)[1] 0.8 def detect_battle_screen(screen): 检测是否在战斗中 template cv2.imread(templates/skill_btn.png) result cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) return cv2.minMaxLoc(result)[1] 0.8 def detect_result_screen(screen): 检测是否在结算界面 template cv2.imread(templates/confirm_btn.png) result cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) return cv2.minMaxLoc(result)[1] 0.8 # 状态机主循环 bot GameBot() while True: screen bot.screenshot() if detect_result_screen(screen): bot.find_and_tap(templates/confirm_btn.png) time.sleep(2) elif detect_battle_screen(screen): # 战斗中等待或执行战斗逻辑 time.sleep(1) elif detect_main_screen(screen): bot.find_and_tap(templates/adventure_btn.png) time.sleep(1) else: # 未知状态尝试点击屏幕中央关闭可能的弹窗 subprocess.run(f{bot.adb} shell input tap 540 1200, shellTrue) time.sleep(1)调试时建议把每次截屏和识别结果都保存下来方便回溯。我习惯在关键节点加日志记录时间戳、当前状态、匹配度。这样当脚本跑飞了翻日志就能定位到是哪一步出的问题。4. 常见问题与排查技巧实录4.1 识别率突然下降的排查思路脚本昨天跑得好好的今天突然识别不到了。这种情况太常见了排查顺序如下第一步检查游戏是否更新了UI。这是最常见的原因。游戏一次小更新可能就把按钮颜色改了、位置挪了。解决办法是重新截取模板。第二步检查设备分辨率是否变化。如果你换了设备或者模拟器改了分辨率模板尺寸就对不上了。解决办法是重新制作对应分辨率的模板或者实现多尺度匹配。第三步检查截屏是否正常。有时候ADB连接不稳定截出来的图是黑屏或者花屏。可以在脚本里加一个检查如果截图的平均像素值接近0说明截屏失败需要重连ADB。第四步检查匹配阈值是否过于严格。如果游戏画面有动态元素比如飘动的云、闪烁的光效可能会干扰匹配。适当降低阈值或者选择更稳定的区域作为模板。4.2 脚本运行一段时间后卡死的处理脚本跑了几十分钟后不动了通常有几个原因ADB连接断开长时间运行后ADB可能掉线。解决办法是加一个心跳检测每隔几分钟执行一次adb devices如果设备不在列表里就重新连接。游戏弹出了未知窗口比如网络波动提示、活动公告。解决办法是在状态机里加一个“未知状态”处理分支尝试点击常见的关闭按钮位置。内存泄漏如果脚本持续截屏但不释放图像对象内存会越用越多。确保每次处理完图像后及时释放或者用固定大小的缓冲区复用。游戏本身卡住了有时候游戏自己会卡死。可以在脚本里加一个超时机制如果某个状态持续超过预期时间就执行一次重启游戏的操作。4.3 常见问题速查表问题现象可能原因排查方法解决方案匹配度一直很低模板过时/分辨率不匹配对比当前截图和模板重新制作模板点击没反应坐标偏移/按钮被遮挡手动点击验证调整坐标或先关闭弹窗脚本跑飞状态识别错误查看日志中的状态序列增加状态校验和异常处理ADB频繁掉线数据线接触不良/驱动问题换线换口测试使用无线调试或更换设备截屏速度慢ADB截屏本身瓶颈计时测试改用minicap或降低截屏频率被检测到异常操作过于规律观察操作间隔加强随机化模拟人类节奏4.4 迭代维护的经验之谈脚本开发不是一锤子买卖后续的迭代维护才是大头。我总结了几个原则模板集中管理。所有模板图片放在一个目录里用有意义的文件名。不要散落在各处否则改版时找都找不到。配置与代码分离。坐标、阈值、等待时间这些参数全部写到配置文件里JSON或YAML不要硬编码在代码里。这样调整参数不用改代码也方便针对不同设备用不同配置。版本控制。用Git管理脚本代码和模板。每次游戏更新后如果改了模板提交一次记录。这样万一改坏了可以随时回滚。日志要详细。每个关键步骤都打日志包括时间、状态、匹配度、执行的动作。日志文件按天分割避免单个文件过大。出问题时日志是唯一的线索。定期回归测试。游戏每次更新后跑一遍完整的测试流程确认所有状态都能正确识别。不要等到正式跑的时候才发现问题。最后分享一个小技巧如果你的脚本需要长时间运行建议加一个“健康检查”机制。每隔一段时间自动截屏并检查是否在预期状态如果连续多次异常就自动重启游戏和脚本。这个机制能解决90%的偶发性卡死问题。这个领域的技术栈其实不复杂难的是对细节的把控和持续的维护。我见过太多人写了一个能跑的脚本就以为万事大吉结果游戏一更新就全废了。真正有价值的不是脚本本身而是那套能够快速适应变化的开发和迭代流程。把状态机设计好把配置分离好把日志打清楚后面无论游戏怎么改你都能在半小时内完成适配。

相关新闻

基于YOLO的植物气孔开闭检测:显微图像目标检测全流程实战

基于YOLO的植物气孔开闭检测:显微图像目标检测全流程实战

植物气孔开闭检测这个需求,我最初是从一摞叶片显微图里被逼出来的——3600张照片,气孔在视野里密密麻麻,开着的像张开的嘴,闭着的缩成一条细线。人工一个个数,数到第两百张眼睛就开始发花,这就是我转向YOLO…

2026/10/14 14:22:35 阅读更多 →
3600张YOLO寄生虫虫卵检测数据集:从训练到落地的完整指南

3600张YOLO寄生虫虫卵检测数据集:从训练到落地的完整指南

在医学检验这一行,寄生虫虫卵镜检从来都是“看着简单、做好极难”的典型项目。一张粪便涂片放到显微镜下,要找的目标可能只有几十微米,背景里还全是植物纤维、气泡、脂肪滴这些形态相似的干扰物——我自己就经历过一上午连看几十张片子、眼睛…

2026/10/14 14:22:35 阅读更多 →
Word文档体积优化全攻略:从原理到实践

Word文档体积优化全攻略:从原理到实践

1. 为什么Word文件会变得臃肿?这个问题困扰过每个经常处理文档的人。上周我帮同事处理一个仅20页却达到50MB的调研报告时,发现里面竟然嵌入了上百张未经压缩的高清图片。这让我意识到,多数人并不清楚Word文档体积膨胀的真正原因。文档变大的罪…

2026/10/14 14:22:35 阅读更多 →

最新新闻

STM32F103储能逆变器硬件-固件协同设计实战

STM32F103储能逆变器硬件-固件协同设计实战

简介:本资源是一套基于STM32F103微控制器开发的5kW储能逆变器完整工程资料,面向嵌入式电力电子方向的工程师、高校电力系统/自动化专业学生及硬件开发者,解决中小型储能系统中并网充放电控制、离网无缝切换与多重安全保护等核心实现问题。压缩…

2026/10/14 14:59:33 阅读更多 →
EAV模式实战指南:动态属性数据库设计与优化

EAV模式实战指南:动态属性数据库设计与优化

1. 什么是EAV模式:当数据库遇到“千变万化的属性”时的务实解法你有没有遇到过这样的场景:某电商平台突然要上线一批智能硬件,每款设备都有完全不同的技术参数——有的强调电池续航(单位:小时),…

2026/10/14 14:59:33 阅读更多 →
滚刀状态识别:多模态时序建模与边缘部署实战

滚刀状态识别:多模态时序建模与边缘部署实战

简介:本资源是一套面向本科生毕业设计、课程设计与期末大作业的滚刀状态智能识别实战项目,聚焦工业设备健康监测场景,融合深度学习与传统机器学习方法解决刀具磨损、异常振动等状态分类问题。项目完整实现CNN、LSTM、GRU时序建模及SVM、随机森…

2026/10/14 14:59:33 阅读更多 →
语义分割各类别mIoU计算:从混淆矩阵到逐类IoU的工程实践

语义分割各类别mIoU计算:从混淆矩阵到逐类IoU的工程实践

简介:这份资源聚焦语义分割任务中的精度评估环节,面向正在使用 PyTorch 训练分割模型、需要量化各类别表现的学生与算法工程师。它解决的是「模型整体指标尚可、却难以定位具体类别分割效果」的问题,通过脚本演示如何从预测结果出发逐类计算 …

2026/10/14 14:59:33 阅读更多 →
SSL证书安全风险:中间人攻击与证书劫持防护

SSL证书安全风险:中间人攻击与证书劫持防护

一、什么是SSL中间人攻击(MITM)HTTPS依靠TLS加密证书身份校验来保护通信,但攻击者一旦插入客户端与服务端之间,就可以做双向TLS会话:一边和浏览器建立TLS连接、出示伪造证书;另一边和真实服务器建立TLS连接…

2026/10/14 14:59:33 阅读更多 →
血管分析套件2019血流速度计算原理与工程实践

血管分析套件2019血流速度计算原理与工程实践

简介:本资源是面向生物医学图像分析领域科研人员与临床工程师的MATLAB血流动力学计算工具包,聚焦于纸基血管图像中血流速度的定量评估,适用于糖尿病视网膜病变、高血压血管监测等疾病研究场景。压缩包共136个文件,含89个核心MATLA…

2026/10/14 14:58:32 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →