尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python+OCR实现游戏交易行自动化采购:从截图识别到自动点击

Python+OCR实现游戏交易行自动化采购:从截图识别到自动点击 简介屏幕自动化技术正逐步渗透到日常操作中其核心是让程序具备“看屏、识字、动手”的能力。OCR文字识别作为关键环节通过将图像中的字符转化为可处理文本为自动化决策提供依据。结合OpenCV图像预处理与模拟点击技术可实现完整的人机交互闭环。这类技术广泛应用于网页价格监控、桌面软件UI测试、批量数据录入等场景能显著提升重复性工作的效率。本文以游戏交易行低价采购为切入点详细介绍基于Tesseract-OCR与Python的自动化方案涵盖窗口定位、图像增强、价格识别与坐标换算等关键步骤并分享实际调优过程中的踩坑经验帮助读者掌握一套可复用的屏幕识别与自动操作框架。1. 交易行自动化采购从手慢无到让脚本替你盯屏幕1.1 一个普通玩家面对的真实抢购困境玩三角洲行动S6赛季那段时间交易行里的低价子弹一直是个让我头疼的东西。弹药是消耗品打完一局就得补但低价子弹的刷新窗口极其不稳定有时候半个小时刷不出来有时候刷出来两秒就被抢光。手动盯着交易列表刷新的体验就是一直握着鼠标反复点刷新、滑动列表、对比价格、再点购买一套操作下来手累不说还经常因为慢了零点几秒被别的玩家截胡。后来我意识到这种盯屏幕、识别数字、判断价格、点击购买的过程本质上是一个完全可以程序化的流程。既然人类手速拼不过那就让脚本替我盯着。这个项目的思路其实不复杂用Python对交易行界面截图截到列表区域后用Tesseract-OCR把价格数字识别出来判断当前价格是否低于我设置的阈值如果低于就自动点击购买按钮然后循环刷新继续找下一批。整个链路里最核心的难点不是模拟点击而是怎么把游戏画面里的价格文字稳定、准确地识别出来。游戏里的数字大多是像素字体字号又小背景还有动态光效直接用Tesseract裸识别会出很多错。所以实际做的时候真正花时间的反而是截图区域标定和图像预处理那一部分。这个项目适合谁参考如果你是刚接触Python图像识别或者UI自动化的初学者想找一个有点真实感的练手项目这个场景非常合适——它体量不大不需要深度学习基础不依赖任何服务器单机就能跑。它覆盖了OpenCV图像处理、OCR参数调优、Windows窗口操作、GUI模拟点击、循环状态控制这几个常用知识点做完这一套你对程序怎么看屏幕、怎么操作屏幕这件事会有非常直观的理解。当然游戏服务条款对第三方自动化工具可能有限制这一点我放到最后细说先看技术实现。1.2 自动化方案的整体链路与适用范围把整个流程拆开看大概是这样的先通过窗口句柄拿到游戏窗口的位置和大小然后根据固定偏移截取交易列表区域截出来的图像不会直接丢给OCR而是先做灰度化、放大、二值化处理把背景干扰去掉处理完的图像交给pytesseract识别出价格文本解析成数字拿数字和预设阈值比较一旦低于阈值就把列表行的像素坐标换算成屏幕绝对坐标调用鼠标点击API完成购买最后按固定间隔循环继续下一轮的截图和识别。这套链路看起来简单但里面每一个环节都有可优化的空间。窗口位置会因为用户移动窗口而改变所以不能写死坐标交易列表可能有多个条目OCR识别的是整列价格还是逐行识别会影响准确率点击之后怎么确认真的买到了要不要做防重复下单的标记循环间隔设多少既要保证响应够快又不能因为截图太频繁导致界面卡顿。这些问题在实际开发中会一个个冒出来。我在后面的章节里会把每一个环节的代码和踩坑过程都写出来方便你按步骤复现。这个具体任务是交易行低价采购但技术本身是通用的。只要是屏幕上出现文字、根据文字内容做操作的自动化需求比如监控某个网页的价格变化、定时抢课、批量处理表格里的数据并自动填入系统本质上都是同一套框架截图、识别、判断、操作。所以我更愿意把这个项目定义成一个屏幕文字识别与自动操作的样板工程游戏交易行只是它的第一个应用场景。2. 技术选型OCR、模板匹配、读内存为什么最终选Tesseract2.1 三种方案的核心逻辑与风险对比做游戏内自动化业内通常会考虑三条技术路线直接读进程内存、图像模板匹配、OCR文字识别。这三条路我都评估过也各自做过简单的验证差别非常明显。直接读内存是最暴力的方案通过找到游戏进程读取交易行列表在内存中对应的地址直接拿到价格数据结构。它最大的优点是速度快、数据准完全不需要图像识别的误差问题。但代价也极高你得会逆向工程得用CECheat Engine一类工具去分析游戏的内存布局而且每次游戏更新都可能让地址失效。更关键的是这种做法属于典型的游戏作弊行为很容易触发反作弊机制风险最大我一开始就排除了。模板匹配是用OpenCV把价格数字的模板图片在截图中滑动比对找到匹配位置。它适合识别UI里固定不变的图标或按钮比如购买按钮、固定的货币符号。但价格数字的形态太多了0-9每个数字在不同价格下都会有不同组合还要考虑模糊、缩放、遮挡准备模板会是个无底洞。所以模板匹配适合作为辅助手段不适合作为核心识别方案。Tesseract-OCR是三条路里性价比最高的。它把价格当作文本来识别不需要逆向游戏、不需要准备海量模板只要把图像预处理做好了识别结果基本可用。Tesseract本身的英文数字识别能力很强配合字符白名单之后可以做到只输出数字和小数点非常适合价格这种纯数字内容。它当然没有读内存那么快但对于刷新频率不算极端的交易行场景来说几百毫秒的识别延迟完全能接受。最终我选了OCR为主、模板匹配为辅的组合。2.2 Tesseract-OCR的安装、配置与备选方案Tesseract在Windows上的安装有几个坑需要先说。Python侧的依赖包叫pytesseract它本质上只是Tesseract引擎的封装底层还需要一个独立的Tesseract程序。如果你在Windows上只执行pip install pytesseract运行时会直接报错找不到tesseract可执行文件。正确做法是从GitHub上的UB-Mannheim/tesseract项目下载Windows安装包安装后把安装目录加到系统PATH或者在代码里手动指定路径import pytesseract pytesseract.pytesseract.tesseract_cmd rC:\Program Files\Tesseract-OCR\tesseract.exePython侧需要的依赖并不多我实际用到的是这几个pip install opencv-python numpy pillow mss pyautogui pywin32 pytesseractopencv-python图像预处理和截图的后续处理mss高性能屏幕截图比PIL的ImageGrab更快pyautogui模拟鼠标移动和点击pywin32获取窗口句柄和窗口矩形坐标pytesseract调用Tesseract引擎安装完可以先用一张截图测试一下OCR环境是否正常比如import pytesseract from PIL import Image image Image.open(test_price.png) text pytesseract.image_to_string(image, config--psm 7 -c tessedit_char_whitelist0123456789.,) print(repr(text))如果这条路跑通了环境就算就绪了。需要说明的是Tesseract对中文字体支持也不错但价格识别场景只涉及数字使用英文训练数据就够了不需要额外下载中文语言包。如果以后想识别交易行里的物品名称再去下载chi_sim语言包也不迟。3. 完整实现从窗口定位到自动下单的关键代码3.1 窗口定位与截图区域标定所有屏幕自动化项目的第一步都是先确定你要操作的区域在屏幕的哪个位置。很多新手上来就直接截全屏这会导致两个问题一是全屏截图数据量大传输和处理都慢二是OCR识别区域过大容易把无关文字识别进来干扰判断。所以我习惯用窗口句柄把游戏窗口找出来再基于窗口的左上角坐标计算交易列表区域。import win32gui import mss # 1. 根据窗口标题找到游戏窗口句柄 hwnd win32gui.FindWindow(None, Delta Force) if hwnd: # 2. 获取窗口在屏幕上的矩形范围 left, top, right, bottom win32gui.GetWindowRect(hwnd) print(f窗口位置: left{left}, top{top}, right{right}, bottom{bottom})拿到窗口范围之后还需要确定交易列表价格列在窗口内的相对位置。这里有个偷懒但有效的方法手动截一张交易行的图用画图工具打开记录价格数字区域的像素位置。比如价格列表大约位于窗口左上角偏移(120, 300)的位置宽度180像素高度480像素。这样在代码里就可以拼出要截取的区域price_region { left: left 120, top: top 300, width: 180, height: 480, } with mss.mss() as sct: screenshot sct.grab(price_region)这段代码的关键在于不要截全屏只截价格列表那一列。区域越小截图越快OCR要处理的内容越少准确率越高。后面我会提到这个截图区域标定本身就是一个容易出错的环节因为不同分辨率、不同窗口大小下偏移量会变化所以更健壮的做法是先获取窗口的客户区大小按比例计算偏移而不是用死值。3.2 图像预处理放大、灰度化与二值化的作用截图拿到的是一块带背景色的彩色图像这时候直接丢给Tesseract识别率会很低。原因在于游戏里的数字是像素字体通常夹杂阴影、渐变背景和半透明效果而Tesseract的训练数据基本来自清晰的白底黑字文档。所以预处理的核心目标是把游戏截图改造成Tesseract熟悉的样子。我在这个项目里的处理流程是标准的四步灰度化、放大、二值化、去噪。import cv2 import numpy as np # 把mss截图转成OpenCV的BGR格式 img_bgr np.array(screenshot)[:, :, :3] # 1. 灰度化 gray cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) # 2. 放大3倍让小字号的像素字体笔画更连贯 gray cv2.resize(gray, None, fx3, fy3, interpolationcv2.INTER_CUBIC) # 3. 使用OTSU自动阈值做二值化 _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 4. 中值滤波去噪点 binary cv2.medianBlur(binary, 3)每一步都有它的道理。灰度化是把三通道的彩色信息压缩成一维减少计算量同时去掉颜色对OCR的干扰。放大这一步很多人容易忽略但游戏里的数字往往只有12到16像素高这种尺寸的文本对OCR来说太小了Tesseract在识别小字号文本时会把相邻笔画混在一起放大3倍之后笔画间距拉开识别率会提升一大截。二值化是把灰度图变成纯黑白的图相当于把背景和文字彻底分离OTSU方法的优势是自适应选择阈值不用手动调节亮度参数。中值滤波则是把二值化后残留的孤立噪点抹掉这些噪点通常是背景光效的残留不处理的话容易被OCR误认为小数点。做完这四步图像就已经很接近白底黑字的文档截图了。如果你发现某个区域的识别率仍然不高可以针对性地再补充一步腐蚀或膨胀操作这取决于你的数字笔画是偏细还是偏粗。3.3 价格识别与低价判断图像处理完接下来就是让Tesseract把数字读出来。这里有两个关键配置Page Segmentation Mode页面分割模式和字符白名单。交易行价格是典型的一行数字文本所以我用的是--psm 7它告诉Tesseract把整个图像当成一行文本识别这样比默认的自动分页模式更快也更准。字符白名单则是把识别范围限制在纯数字和逗号、句点上防止Tesseract把某些数字误判成英文字母比如把0识别成O、把1识别成I。text pytesseract.image_to_string( binary, config--psm 7 -c tessedit_char_whitelist0123456789., )原始输出可能带有空格、换行、逗号等杂质需要清洗后再转成整数。这里要注意游戏里价格可能用逗号做千分位分隔也可能用小数点表示单价具体清洗逻辑要看你的实际数据格式。我用的清洗方式是def parse_price(raw_text): # 去掉空白字符和逗号 cleaned raw_text.replace( , ).replace(,, ).replace(\n, ).replace(\x0c, ) # 如果存在小数点说明可能是单价这里取整数部分 if . in cleaned: cleaned cleaned.split(.)[0] if not cleaned: return None try: return int(cleaned) except ValueError: return None有了数字之后判断逻辑就很简单了threshold 50 # 我设置的低价阈值 price parse_price(text) if price is not None and price threshold: print(f发现低价子弹: {price})但这里有个实际中的坑交易列表里往往同时显示十几行的价格OCR识别出来的可能是整列文本而不是一个孤立数字。处理方式有两种一是把截图区域进一步裁剪成单行再逐行识别二是先识别整列文本再按行拆分。我后来用的是第一种把价格列按行高切成了多张小图分别识别这样能精确定位到具体哪一行是低价方便后续点击。3.4 模拟点击和主循环控制识别到低价行之后接下来要做的事情是把它对应的购买按钮坐标算出来然后模拟点击。这里最需要注意的是坐标系的换算OCR处理的是截图区域内的像素坐标而模拟点击需要的是屏幕绝对坐标。如果你直接拿截图内的相对坐标去点击点到的位置会偏移窗口左上角那么远。import pyautogui # pyautogui的安全开关鼠标甩到屏幕左上角会强制中断 pyautogui.FAILSAFE True # price_region_left/top 是截图区域在屏幕上的绝对坐标原点 # row_offset_x/row_offset_y 是购买按钮在该行内相对价格文本的偏移 click_x price_region[left] row_offset_x click_y price_region[top] row_offset_y pyautogui.click(click_x, click_y)点击之后不能立刻进入下一轮循环因为界面可能有短暂反应时间比如弹出购买确认框或者数量输入框。如果没有等待就继续刷新截图很可能把弹出菜单当成交易列表识别出乱码或者误触到其他按钮。所以我在每次点击后加了0.3到0.5秒的等待并且用一个状态标记防止同一价格被重复购买last_price None while True: screenshot capture_region() binary preprocess(screenshot) price get_price(binary) if price is not None and price threshold and price ! last_price: click_buy_button(price_row) last_price price # 固定轮询间隔避免截图过于频繁导致界面卡顿 time.sleep(0.6)主循环用while True配合time.sleep控制节奏这个间隔我调过多次后面的实测部分会细说。整体框架到这里已经能跑通了但离稳定好用还有距离接下来的踩坑记录才是这个项目真正有价值的部分。4. 实测中踩过的坑识别率、延迟、误触一个都没少4.1 游戏像素字体导致识别率不稳的根因与解法我最初的版本识别率大概只有70%左右价格数字经常错。最典型的问题是把8识别成3把0识别成8把5识别成6。排查了很久发现根源在游戏字体的渲染方式上游戏里的价格数字不是Windows系统字体那种平滑矢量字体而是像素风点阵字体笔画之间经常粘连在一起再加上数字本身尺寸小二值化之后字符轮廓变得不规整Tesseract就容易判错。解决这个问题我试了三招效果是叠加的。第一招是放大倍数从2倍提到3倍更大的尺寸让字符特征更明显第二招是用形态学操作把粘连的笔画适当断开我用了cv2.erode和cv2.dilate的组合先腐蚀再膨胀相当于把字体笔画瘦身一圈再恢复能有效分离粘连第三招是缩小识别范围直接用白名单字符并把psm设为7。改完之后识别率稳定在95%左右。如果这种情况下还有零星错误建议不要继续硬调Tesseract参数而是增加一个合理性校验游戏里弹药价格通常在一个可预期的范围内比如5到200之间如果OCR识别出来的价格是0、是几千或者落在完全不可能的范围就直接丢弃不参与购买判断。宁可漏掉一次机会也不要因为误识别以高价买进。4.2 抢购延迟怎么压节奏怎么调交易行低价子弹的抢购本质上是个拼延迟的活。这个项目的延迟来源主要有三块截图耗时、OCR识别耗时、点击响应耗时。我实测下来mss截取一个180乘480的小区域大概需要10到20毫秒OpenCV预处理在3毫秒左右Tesseract识别单行数字大约需要100到200毫秒加上Python本身的调度开销单轮循环大概在200到300毫秒。这个速度够不够我的体会是对于交易行这种刷新频率不算极端的场景其实够用。真正影响体验的是轮询间隔。如果间隔设得太短比如0.1秒一轮界面还没来得及完全刷新就又截图了反而会截到半渲染状态如果间隔太长刷新出来的低价商品容易错过。我最后稳定在0.5到0.7秒一轮这是一个兼顾反应速度和界面稳定性的值。如果你追求更极致的延迟可以考虑两个方向。第一个是把Tesseract的进程常驻化不要每轮都重新初始化引擎这能省掉一部分启动开销第二个是缩小OCR截取区域只截价格列表里最可能刷新的前几行而不是整个列表。但这两种优化都增加了代码复杂度没有特殊需要的话不建议一开始就上。4.3 误触与重复下单的防御措施比识别率更低的问题是误触和重复下单。有一段时间我的脚本会把同一个商品买了两次原因是点击后交易列表发生了滚动原本买到的那一行对应的坐标上变成了另一行商品。后来我在点击前先记录当前识别到的价格点击后检查鼠标位置对应的UI状态如果发现同样价格的条目已经被标记为已购买就跳过。防御重复下单最有效的方式是别只用坐标判断要结合内容判断。我的做法是每次识别到低价后先记录价格和所在行的特征比如这一行是否包含库存充足字样然后点击购买点击后再截一次图识别确认弹窗上的价格确认和之前判断的价格一致才继续执行后续操作。这个点击前记录、点击后确认的机制能挡住绝大多数误触和重复购买的情况。另外一点经验是pyautogui的FAIlSAFE开关一定要开启。脚本失控时鼠标乱飞去买东西人工一时半会关不掉程序这时候把鼠标甩到屏幕左上角就能强制中断回滚别问我怎么知道这个功能有多重要的。5. 使用边界与合规红线这类自动化脚本能走到哪一步5.1 游戏协议对自动化工具的态度聊完技术必须认真讲一下这类脚本的使用边界。几乎所有主流射击游戏的用户协议里都明确禁止使用第三方自动化工具、脚本、宏等辅助手段。这个项目针对的是交易行低价采购相当于代替玩家自动完成紧盯列表、判断价格、点击购买的操作从玩家行为规范的角度看确实存在被认定为违规脚本的风险。我在实际使用中也只在小号上做过短时间的验证从未在正式游戏环境里长期挂机。这里需要你根据自己的情况做判断如果游戏服务条款明确禁止那么使用这个脚本一旦被检测到轻则警告、重则封号这个后果需要自己承担。我不是法律专业人士不能替你做合规性结论但我的个人建议是这类项目更适合作为学习计算机视觉和GUI自动化的练手案例而不是长期依赖的游戏外挂。你把技术学会了价值远大于那几发低价子弹。5.2 技术边界与负责任的实践方式从技术层面看这个项目没有做任何绕过反作弊检测的操作它只是普通的窗口截图、图像识别和模拟鼠标点击和你在系统里跑一个自动截图工具没有本质区别。但我坚决反对在此基础上做进一步的对抗性开发比如隐藏进程、伪造输入、绕过行为检测之类的操作——那属于明确越界既不符合技术伦理风险也完全不可控。如果你对这类屏幕自动化技术感兴趣可以把它迁移到更安全的场景里用同样的框架做网页价格监控工具识别电商页面的价格变化并提醒做桌面软件的UI自动化测试模拟用户点击流程做数据录入工具从单据截图里识别数据并自动填入Excel。这些都是正常、正当、甚至能提高工作效率的方向。把识别屏幕、判断内容、自动操作这套能力用在正道上才是技术本身的价值所在。最后说点实在的。这个项目做完之后我最大的收获并不是成功买到几次低价子弹而是把OpenCV图像预处理、Tesseract参数调优、GUI坐标换算、循环状态机这些知识点完整地串了一遍。如果你本来就在学Python又想找一个既有视觉识别又有自动操作的练手项目我强烈建议照着这个思路自己实现一遍。用不用在游戏里你自己掂量但技术本身值得学透。本文还有配套的精品资源点击获取
返回列表