模拟精灵是首个公开最有效的验证码识别技术的软件,
使用模拟精灵制作了大量的免费、商用群发软件,对很多复杂BT的验证码都能成功的识别。
但是验证码仍然需要精湛的技术与足够的耐心。请牢记这一点。
验证码识别不适合浮躁的人去做。
验证码识别是一项特殊的技术,任何一个公开的验证码识别代码都会很快的失效。
因为代码的公开后相关网站都会很快的更改验证码。
所以下面我只会介绍其原理。
在这里讨论验证码识别技术纯粹基于技术研究目的。
公开此技术也是为了让更多的网站采取更有效的防范措施。
禁止任何人利用这里介绍的验证码识别技术滥发垃圾信息。
一、下载验证码样本
打开c:\test文件夹,选“查看缩略图”,
然后重复运行下面的LAScript脚本,每运行一次,就查看c:\test下自动生成的图片,把图片上的字符改为文件名.
例如图片上面显示5,就把文件名改为5.jpg.
如果变化比较复杂的验证码,可以对每个字符多用几个样本,第一个字符为验证码字符,第二个字符可以为任意字符。
例如:5a.jpg , 5b.jpg , 5c.jpg ...........等等。
样本多就会识别能力就越强。
img = image.new();
--下载图像,没有后缀名要显示指定*.bmp格式
img:getURL("http://www.***.com/test.asp","*.png");
assert(img:ok(),"下载验证码失败");
img:Crop(4 ,3 , 56 ,18 )
img:save("c:\\test\\test.jpg") --保存到硬盘
--折分图片,指定一行四列
img2,img3,img4,img5 = img:split(1,4);
img2:save("c:\\test\\0001.jpg")
img3:save("c:\\test\\0002.jpg")
img4:save("c:\\test\\0003.jpg")
img5:save("c:\\test\\0004.jpg")
image.del(img);
在整个验证码识别过程中,格式与后缀名一定不能搞错,否则就会失败。
通常:asp的验证码是bmp格式,php的验证码是png格式,其他验证码很多是jpg格式。
简单的,在验证码上右键点选“图片另存为”,就可以看到格式(不一定准确)。
如果你搞不清楚,这时候就不要指定后缀名
img:getURL("http://vwww.***.com/test.asp","")
这样就可以下载了
二、生成验证码样本数据库
复制下面的代码并粘贴到fap程序的「脚本区块」内,然后点击"回放运行",最后再点击"读取源代码"。
你就可以在ApeML源代码最后面的「数据区块」中看到生成的验证码样本了。
将「数据区块」的内容复制需要使用验证码识别的fap模拟程序中覆盖「数据区块」即可。
--如果一个字符有多个样本,例如 5A.jpg 5B.jpg 5C.jpg
for k,v in pairs(tkey) do
if((#k)~=2)then --如果元素键名不是两位字符
tkey[k.."A" ]=0;
tkey[k.."B" ]=0;
tkey[k.."C" ]=0;
tkey[k]=nil;--删除单字符的键名
end;
end;
--k参数为键,v参数表示值 一个典型的tkeyle迭代器回调函数
loadtkey = function(k,v)
local img = image.new();
img:load("C:\\test\\"..k..".jpg");
assert(img:ok(),"C:\\test\\"..k..".jpg".."\n不是有效的图片");
img:bpp(1);
img:bpp(24);
--通过上面两句,轻松去掉验证码上的杂色杂点
img:Crop( 1 , 0 , 9 , 10);--修剪单个字符
img:median(2);--中值滤波进一步去杂点
tkey[k]= string.encode( img:getBytes("*.jpg") , ""); --因为转换到字符串还是二进制,所以用base64进行编码
image.del(img);
end;
--遍历表tkey的所有元素,调用loadtkey加载图片文件
for k,v in pairs(tkey) do
loadtkey(k,v);
end;
--把所有图片保存到数据岛,
ape:saveTable(tkey,"验证码样本")
将下面的代码添加到fap模拟程序最前面的init脚本区块中即可
需要识别验证码的地方添加类似下面的代码:
--因为刷新了验证码与页面不一致,把验证码画到屏幕上
local x,y = mouse.getPos()
img:paint(x,y,60 ,20 )
local str = ImgToString(img);
--下面我们把验证码的每个字符都转换为大写,并控制键盘顺序按键
code1 = string.upper( string.sub(str,1,1) );
code2 = string.upper( string.sub(str,2,2) );
code3 = string.upper( string.sub(str,3,3) );
code4 = string.upper( string.sub(str,4,4) );
key.press(100,code1,code2,code3,code4);
上面我们用了模拟按键的方法输入验证码。
实际上大多时候可以用更简单的方法,如下:
为什么我的验证码与页面上不一样
因为我们使用img:getURL读取验证码时已经刷新了验证码。
所以验证码与页面上显示的并不一样,您只需要识别最新的验证码即可。
如何直接获取页面的上图片,而不是重新下载
有些验证码是绑定页面的,必须识别页面上的验证码才行。
那么可以使用image.capture函数直接抓屏屏幕上的图片即可。
请参考:image.capture函数。
更好的方法是使用ele:exec("Copy")函数直接拷贝页面上的图片到剪贴板。
然后使用 img:getClipBD() 获取图片。
请参考:ele:exec("Copy")函数 img:getClipBD()函数

看上面的示意图,Crop就是选取绿色方框内的区域去清除绿色方框外面的区域.
必须保证里面的面积正好可以平均分成四块(假设这里是四个验证码字符)
这样以后调用 img:split(1,4) 就正好分成四个字符了
分成四份的小图片其宽度应当正好是上面的红色小方块的宽度。
高度与绿色方框一样,我这里画的参次不齐是为了让大家看清楚。
如果你Crop的参数值不对,那么split就出错了.
下载验证码图片以后,可以使用图像编辑软件打开高倍放大。
模拟精灵识别验证码的能用是强大的,一个函数即可以去除杂色杂点。
经过上面两句代码的处理,速度很快,所有背景、干扰点、杂色荡然无存。
但是有时候验证码中有大量的干扰线,并且位置随机变动的太历害,
这时候我们在处理验证码以前首先去除这些干扰线并准确的去除背景提取字符.
下面是一个模拟精灵初步处理后的验证码图片.已经去除了杂色、杂点.但是上面还是有干扰线.

一个可选的办法是用中值滤波再处理一下。img:median(2); 一个函数调用就可以,但
是这样虽然去掉了干扰线,原来的字符也被少量的破坏了。
下面是使用种子填充算法去除干扰线的源代码,不但能去除杂点,
而且可以去除周围的空白(提取位置随机变化的验证码),
稍加修改还能有更多的用途.
下面是自动处理以后的效果

下面是全部的源代码: