本文为稀土技能社区首发签约文章,30天内制止转载,30天后未获授权制止转载,侵权必究!
有朋友在上一篇文章《用YOLOv8一站式处理图画分类、检测、切割》下评论:
他问,能否来一篇处理滑块验证码的文章。我回复说,能够一试。
随后,我便搜索网上有没有相似的文章。假如遍地都是,那我也没有必要再添一份冗余。成果发现有相似的。可是,他们大多选用传统的手段:有经过操作网页html
元素辨认的,有经过OpenCV
二值化轮廓辨认的,甚至还有遍历像素点去对比RGB
点辨认的。
咱们为什么不经过AI视觉处理去辨认呢?传统的辨认方法,会受页面缩放、图画颜色、画质清晰度等诸多因素的影响,具有局限性。
因此,我觉得写这么一篇,仍是十分有必要的。
声明:本文不是破解类文章,不会讲解怎么剖析或篡改网站的代码。它是仿照最终用户在电脑上的手动操作,这种方法叫机器人流程主动化(Robotic Process Automation, RPA)。
RPA
不是”外挂”,而且差别很大。RPA
不去研究程序的成分,没有侵略性,它完全像用户相同去合法操作软件。举个不恰当的比方,就像考试,RPA
是找个人替你去考试,外挂或许破解工具则是直接往成绩单里塞入你的名字。
下面我将给咱们展现,我是怎么利用AI
+RPA
处理验证码辨认这个问题的。学会了它,你能够利用机器人去操作一些固定的流程,然后提高出产效率。
一、完成思路和可行性验证
别看我写到这儿了,其实到目前为止,我也没有掌握是否能成功。可是,潜意识里觉得是能够的。因此,想一步,试一步。下面就把我的实践记载发布给咱们。
我找来一个滑块验证码的网页。这类网页许多平台都供给,我找的这个是腾讯的。
选用RPA
的方法,咱们就不去按F12
剖析元素结构了。咱们要和用户相同,按下鼠标拖动它到正确的方位。
这里边需求处理如下几个问题:
- 1、找到滑块起点与结尾的坐标方位。
- 2、仿照鼠标的按下、拖动、抬起操作。
- 3、当时状况的判别(什么机遇抬鼠标)。
过程1和过程3,我有思路,那便是经过图画的方针检测或许分类去完成。由于方针检测的成果中,会包含什么物体在哪个方位。而图片分类,能够给各种状况分类。这两项,假定现已做到了。
继续往下推演。
第2步仿照鼠标操作,能完成吗?这对我来说,是一个常识空白。经过百度,我了解到python
能够经过pyautogui
库,完成仿照鼠标的操作。
先来做一个可行性实验。
经过谈天软件自带的截图工具,咱们能够获取物体的方位坐标(下图POS: (xx, xx)
所示)。
咱们经过人工测量的手段,预置现已拿到了滑块的起点和结尾,先看看能否经过主动化操作,来经过验证。
我测量的蓝色滑块起点坐标是(260, 940)
。从这个方位开始,水平往右拖动,大约X轴
到363
时,正好补齐。
那全体操作应该便是先将鼠标移动到起点,然后按下鼠标向右拖动363-260=103
像素的间隔,然后抬起鼠标。
# 首要pip install pyautogui装置库
import pyautogui
# 设置开始方位
start_x = 260
start_y = 940
# 设置拖动间隔
drag_distance = 363-260
# 移动到开始方位
pyautogui.moveTo(start_x, start_y, duration=1)
# 按下鼠标左键
pyautogui.mouseDown()
# 拖动鼠标
pyautogui.moveRel(drag_distance, 0, duration=1)
# 松开鼠标左键
pyautogui.mouseUp()
看看作用怎么。
OK!这一步走通了。技能点验证经过,后面咱们去处理人工智能辨认图画。
二、 练习实施与使用
咱们要做哪些方针的检测辨认呢?这仍是要取决于完成思路。
从上图能够看出,起点块、结尾块、操作块,咱们肯定是要做检测的。咱们需求获取它们的坐标信息,然后进一步经过鼠标去操作它们。
除此之外,还有一种状况咱们最好也要检测。那便是重合状况。这类状况决定了咱们拖动过程中,什么机遇松手。或许有人会觉得这一步是多余的。由于经过计算,咱们将起点块移动到结尾块松手就能够了。这……理论上是这样。可是在实践中,即使你算得很对,假如AI辨认的坐标有差错呢?
咱们人类是看到图画重合才松手的,所以仍是仿照得像一些。关于软件的RPA
方案,过度保证才能够更健壮一些。
咱们能够规划多种算法来保证操作的精确率:
- 直接法:当重合特征的数量大于0时(呈现一个重合)。
- 间接法:当图片的结尾块数量为0时(被覆盖才呈现)。
- 计算法:操作块和结尾块水平方向对齐时(拖到结尾方位)。
详细哪种方法最精确,还得结合搅扰项、辨认精确率。那是后话。
下面,咱们就来符号和练习数据。
2.1 符号与练习数据
选用YOLOv8
进行符号、练习以及使用的流程,我在上一篇文章介绍过了。那一篇是专门讲这个的,此处我就只讲流程,不讲细节,简单一笔带过。
首要是准备素材。我先截图保存了许多验证码区域的图片,然后用labelImg
对截图进行符号。
或许咱们看到我把改写按钮又符号上了,这是规划之外的。由于在符号的过程中,我忽然想到,假如某种反常导致辨认不到滑动块,咱们能够点一下改写按钮。
大约制作了100多份样本。
然后对样本进行练习。练习100轮后,可获取一份最优的best.pt
权重文件。
看看验证集的作用,还不错。
这阐明,找到咱们关注区域的方位不成问题。
接下来,咱们就要开始使用它了。
2.2 剖析成果和获取坐标
YOLOv8
调用model.predict(……)
进行猜测后,会回来辨认成果。假定咱们将成果保存在results
中。
经过这个成果results
,咱们能够拿到有什么物体呈现在什么方位。
拿下面这个test.png
图片举比方:
咱们用新练习的模型进行检测,代码如下:
from ultralytics import YOLO
from PIL import Image
model = YOLO('best.pt')
image = Image.open("test.png")
results = model.predict(source=image)
最终成果如下:
咱们来看数据。results
是多张图片的合集。results[0]
是第一张,咱们界说为result
。
在result
中,有一个result.names
,它是一切的分类,打印成果如下:
{0: 'start', 1: 'target', 2: 'fill', 3: 'operate', 4: 'refresh'}
result.boxes.data
是检测到的方针框的信息,打印出来的话,格式是这样的:
[[ 45.1437, 130.0680, 97.8794, 181.8184, 0.9665, 0.0000],
[ 39.4141, 266.4925, 110.9030, 307.4121, 0.9565, 3.0000],
[216.0383, 129.7685, 269.5766, 181.7017, 0.9546, 1.0000],
[ 35.7875, 318.4604, 65.9167, 347.1984, 0.8392, 4.0000]]
这是一个数组。里边有4组数据,每组数里又有6个元素。这4组数据,便是上图中的4个框。
咱们拿第一组数据举例,解释下每个数据的意义:
索引 | 数值 | 意义 |
---|---|---|
0 | 45.1437 | 矩形框左上角x坐标:x1 |
1 | 130.0680 | 矩形框左上角y坐标:y1 |
2 | 97.8794 | 矩形框右下角x坐标:x2 |
3 | 181.8184 | 矩形框右下角y坐标:y2 |
4 | 0.9665 | 辨认概率(1为满分):probs |
5 | 0.0000 | 辨认分类的索引{0: 'start', 1: 'target' ……
|
之所以都是小数(连分类索引也是),这是由于它们是并排联系,里边有一个概率必须为小数。
了解了这些,咱们就能看懂上面的辨认成果了。它说:
物体 | 概率 | 坐标 |
---|---|---|
0-start 起点块 | 96% | (45, 130) (97, 181) |
3-operate 操作块 | 95% | (39, 266) (110, 307) |
1-target 方针块 | 95% | (216, 129) (269, 181) |
4-refresh 改写按钮 | 83% | (35, 318) (65, 347) |
接下来,咱们只需求将鼠标移动到操作块
的区域,然后拖动的方向和间隔是从起点块
到结尾块
。最终,抬起鼠标。操作就完成了。
咱们请注意,尽管上面一向拿着一张图举例。可是,这个人工智能模型对其他巨细、颜色、形状的验证码也是起作用的。
前提是他们得在一个特征系统下。就算方形换成三角形,它也能够正确辨认。可是,假如换成将小动物拖到笼子里,那就得再额定练习了。
到目前为止,咱们现已有了手(仿照鼠标拖动的pyautogui
),也有了大脑(从图片判别方针信息的best.pt
)。还差什么呢?
没错!那便是眼睛。
2.3 截取屏幕并移动滑块
在上一个过程中,测验图片是咱们设置的固定图片。但在实际场景中,咱们更希望程序自己去屏幕上瞅。我要有手动截屏的功夫,还不如我自己去拖动。
我首要想到的是程序截屏,拿着截屏图片让AI
去辨认方针物体。
在pyautogui
中,截屏很简单,调用pyautogui.screenshot()
就能够把当时屏幕拿到。它回来的数据是PIL
的Image
格式,适当所以Image.open('xx.png')
,内容是像素的矩阵数组。
假如我在程序页面运转screenshot
,它不就把我的IDE
截屏了吗?这时截取下来的是代码界面。因此,我把浏览器页面和代码页面左右并排排放在屏幕上。这样就能拿到包含网页的信息了。然后,再去辨认就能够了。
上面的作用完成起来很简单,便是下面这点代码。
import pyautogui
from ultralytics import YOLO
# 截取整个屏幕
screenshot = pyautogui.screenshot()
# 裁剪方针区域
x1,y1,x2,y2 = 140, 110, 570, 510
cropped = screenshot.crop((x1,y1,x2,y2))
# 进行辨认
model = YOLO('best.pt')
results = model.predict(source=cropped, save=True)
需求解释一下,此处我偷了个懒。正常状况下,一切的操作都得是主动的。咱们或许发现,我手动指定了一个(x1, y1)
、(x2, y2)
,这是验证码的区域边框。原因有2点:
- 第一,我不想将整个屏幕截图全交给AI去辨认,这样效率比较低。让程序主动寻找验证码区域,能够做到,其实便是再来一份方针检测。可是,我这个不是商业项目,是技能教程,没必要面面俱到。
- 第二,针对一款软件而言,它的登录界面的方位相对固定,不会常常变换。对个人用户而言,针对某个场景大体指定一个区域,能够满意日常使用。
假如你要做成商业项目去卖钱,现在的方法是软弱的。你得让它能主动找到、翻开指定的浏览器。其实这些都能够做到。
import pyautogui
# 获取一切窗口的信息
windows = pyautogui.getWindowsWithTitle('Google Chrome')
# 筛选出Chrome浏览器窗口
chrome_window = None
for window in windows:
if 'Google Chrome' in window.title:
chrome_window = window
break
# 查看是否找到了Chrome浏览器窗口
if chrome_window is not None:
# 获取Chrome浏览器窗口的方位和巨细
chrome_left = chrome_window.left
chrome_top = chrome_window.top
chrome_width = chrome_window.width
chrome_height = chrome_window.height
可是,假如细讲这些,我认为就跑题了。
下面,咱们开始测验拖动它。有成果了,对成果进行剖析,找到坐标点,然后履行操作就能够了。
# 辨认成果
b_datas = results[0].boxes.data
points = {}
names = {0: 'start', 1: 'target', 2: 'fill', 3: 'operate', 4: 'refresh'}
# 将数据依照{"start":[x1,y1,x2,y2]}的格式重组,便利调用
for box in b_datas:
if box[4] > 0.65: # 概率大于65%才记载
name = names[int(box[5])]
points[name] = np.array(box[:4], np.int32)
# 获取起点块、结尾块的间隔
start_box = points["start"]
target_box = points["target"]
operate_box = points["operate"]
# 找到起点块的中心
centerx_start = (start_box[0] + start_box[2])//2
# 找到结尾块的中心
centerx_target = (target_box[0] + target_box[2])//2
drag_distance = centerx_target - centerx_start
# 找到操作块的中心点
centerx_op = (operate_box[0] + operate_box[2])/2 + x1
centery_op = (operate_box[1] + operate_box[3])/2 + y1
# 移动到操作块中心点
pyautogui.moveTo(centerx_op, centery_op, duration=1)
pyautogui.mouseDown()
# 拖动鼠标
pyautogui.moveRel(drag_distance, 0, duration=1)
pyautogui.mouseUp()
代码很简单,也有注释。
着重说一下,centerx_op
、centery_op
那里需求加上x1
、y1
。由于辨认成果的坐标是相对裁剪图片而言,而pyautogui
移动鼠标,是针对整个屏幕坐标系操作的。
下面是运转的作用。
看,能够搞定!
这么杂乱的操作都能做到,那么检测输入框,输入文本,点击登录按钮啥的,也不在话下。
2.4 更加健壮的战略
多测验几次,我便发现了报错。
这个报错的原因是没有检测到起点块的信息,我还去取它的数据。之前练习时,咱们符号了fill
已填充这个状况,这或许会和起点块start
弄混。
其实,符号的时分我有考虑过“两者这么相似,它能区分吗?”这导致我寝食难安,犹豫不决。后来我觉得不应该这样尴尬自己,该尴尬的应当是算法。别的,这也绝非是强人所难,两者是不相同,start
和周围颜色有横断色差,fill
和周边像素是交融的。
没想到,现在呈现了一个万金油特例,它从空里被挖出来挪到很远的间隔后,居然和周围的环境也不违和。
没联系,咱们能够处理。这类状况,咱们只当没有start
,只要将滑块滑动到target
的下方就能够了。
代码如下:
……
if "operate" not in points or "target" not in points:
raise ValueError("找不到元素")
# 假如没有起点块,操作块充任起点
if "start" not in points:
start_box = operate_box
else: # 有起点块
start_box = points["start"]
……
同时把代码加固了一下,假如找不到必要元素就抛反常,不至于让程序崩溃。
如此一来,它又能正常工作了!
这仅仅举了一个提高健壮性的比方。实际在使用时,还会遇到更多的反常。都需求挨个处理。
三、小结
我还有许多想法,比方滑到了目的地,先不抬起鼠标,再截屏辨认一次,看看是否真的填充上了。假如没有,则左右移动几个像素,再测验。这样能够确保向人工操作去看齐。
尽管咱们用机器竭力仿照人工,可是实际上,机器操作和人工操作是有很大差异的。
机器的操作是规整的,这一点人工基本做不到。
假如你仔细观察的话,咱们上面的程序控制鼠标移动,它的途径是直线,这一点很难骗人。
你说,我绕个圈不就行了。能够!可是,让程序完成绕圈是这样的。
对人类来说,不管是上面的直线、曲线仍是折线,咱们都很难做到机器那么规整。
换一个视点,人工的方法,机器想要仿照,本钱也很高。
下面是我拿着鼠标移动的路线,尽管我竭力坚持直线,但放大了看,在要害点(点击鼠标)上,仍是存在极不规则的途径。
机器想要搞出我这么个途径,它会很累的,由于这就像是笔迹判定相同。
这便是为什么,有的验证码让你点一个小圈,就能判别出你是不是机器人。所以啊,想要防机器主动操作,也不是很难。
我想这便是开源软件和商业软件的差异。开源软件仅仅是走通了,阐明可行、能用。可是假如你想拿去卖钱,就得下功夫去完善,得让它好用、易用。
AI+RPA
我现已在使用了,但仅限于处理自己生活中遇到的问题。我在学习高数时,遇到不会做的题目,有时想搜都不知道该敲些什么字符。那么,经过AI进行辨认,然后对接大言语模型,能够直接给出解题思路。
总归,科技发展地很快。有时分换个思路,会有意想不到的收获。它会将许多你认为的不或许,变为或许。
欢迎咱们在我的完成思路上去验证、改善、完善。很希望能帮到你,或许仅仅是对你有所启示。
最终献上本项目的GitHub地址:github.com/hlwgy/jueji…
我是TF男孩,喜欢和读者唠嗑的程序员。