您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 质量控制/管理 > 易语言验证码识别技术带源码
模拟精灵是首个公开最有效的验证码识别技术的软件,使用模拟精灵制作了大量的免费、商用群发软件,对很多复杂BT的验证码都能成功的识别。但是验证码仍然需要精湛的技术与足够的耐心。请牢记这一点。验证码识别不适合浮躁的人去做。验证码识别是一项特殊的技术,任何一个公开的验证码识别代码都会很快的失效。因为代码的公开后相关网站都会很快的更改验证码。所以下面我只会介绍其原理。在这里讨论验证码识别技术纯粹基于技术研究目的。公开此技术也是为了让更多的网站采取更有效的防范措施。禁止任何人利用这里介绍的验证码识别技术滥发垃圾信息。本文介绍的验证码识别适用于比较复杂的图片验证码,也是大多数网站采用的方法。有一些网站的验证码极简单,例如在网页中直接显示验证码字符而不是图片,或者图片的文件名直接就是验证码上的字符。或者有其他规律可循,或者有其他明显的漏洞可以利用(例如通过改写访问验证码页面的源代码使验证码不刷新)。这一类的验证码识别极其简单,只要熟练掌握web库、element库的函数即可,不需要使用下面介绍的方法。一、下载验证码样本打开c:\test文件夹,选“查看缩略图”,然后重复运行下面的LAScript脚本,每运行一次,就查看c:\test下自动生成的图片,把图片上的字符改为文件名.例如图片上面显示5,就把文件名改为5.jpg.如果变化比较复杂的验证码,可以对每个字符多用几个样本,第一个字符为验证码字符,第二个字符可以为任意字符。例如:5a.jpg,5b.jpg,5c.jpg...........等等。样本多就会识别能力就越强。img=image.new();--下载图像,没有后缀名要显示指定*.bmp格式img:getURL(***.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格式。简单的,在验证码上右键点选“图片另存为”,就可以看到格式(不一定准确)。另外,你可以用UltraEdit等以二进制方式打开看文件头部首先下载:str=web.getURL(***.com/test.asp)string.save(str,c:\\test.bin)然后用UE打开test.bin看文件头部(第一行)jpg文件头部有JFIF字眼png文件头部有PNG字眼gif文件头部有GIF字眼如果你搞不清楚,这时候就不要指定后缀名img:getURL(***.com/test.asp,)这样就可以下载了二、生成验证码样本数据库复制下面的代码并粘贴到fap程序的「脚本区块」内,然后点击回放运行,最后再点击读取源代码。你就可以在ApeML源代码最后面的「数据区块」中看到生成的验证码样本了。将「数据区块」的内容复制需要使用验证码识别的fap模拟程序中覆盖「数据区块」即可。localtkey={A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=0,O=0,P=0,Q=0,R=0,S=0,T=0,U=0,V=0,W=0,X=0,Y=0,Z=0};--在字典中添加所有数字键fori=0,9,1dotkey[tostring(i)]=0;end;--如果一个字符有多个样本,例如5A.jpg5B.jpg5C.jpgfork,vinpairs(tkey)doif((#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)localimg=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加载图片文件fork,vinpairs(tkey)doloadtkey(k,v);end;--把所有图片保存到数据岛,ape:saveTable(tkey,验证码样本)三、验证码识别将下面的代码添加到fap模拟程序最前面的init脚本区块中即可--从数据区块读取base64编码的图片数据codekey=ape:loadTable(验证码样本);localtimg={};--这是一个图像数组,用来储存还原后的验证码样本的图片数据--必须进行一个转换,因为codekey里面只是base64编码的普通字符串,而timg将是真正的图片对象(二进制数据)--还原到图片对象toImage=function(k,v)localimg=image.new();localstr=string.decode(v,);--首先进行base64解码,将纯文本转换为二进制数据img:setBytes(str,*.jpg);--将二进制数据还原为图像timg[k]=img;end;--载入验证码样本tkey=ape:loadTable(验证码样本);fork,vinpairs(tkey)do--验证样本toImage(k,v);--转换为图像end;--转换图片验证码到字符串的函数functionImgToString(img)functiontest(imgX)--test是一个被包含在函数中的内部函数sleep(0);locallimit=(60*20)+(60*20);--最小相似度local关键字声明为局部变量localchr=A;--读取的字符--testimg是一个被包含在函数中的内部函数,作为table.foreach的回调函数,k参数表示键,v参数表示值testimg=function(k,v)--调用image.testXX()函数得出相似度,类似的函数还有image.testX()image.test()localn=imgX:testXX(timg[k]);if(nlimit)then--比较最小相似度limit=n;chr=k..;end;end;--遍历timg表,并调用testimg函数fork,vinpairs(timg)dotestimg(k,v);end;returnstring.left(chr,1);--返回读取到的字符串首字符(如果每个字符有多个样本)end;--修剪图片image.Crop(img,4,3,56,18)img:bpp(1);img:bpp(24);--上面的过程必须与下载样本时的代码完全一致。--使用split函数分割图片localimg2,img3,img4,img5=img:split(1,4);win.messagePrint(正在检测图片,请稍候....);returntest(img2)..test(img3)..test(img4)..test(img5);end;需要识别验证码的地方添加类似下面的代码:img=image.new()img:getURL(***.com/test.asp,*.jpg)--因为刷新了验证码与页面不一致,把验证码画到屏幕上localx,y=mouse.getPos()img:paint(x,y,60,20)localstr=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);上面我们用了模拟按键的方法输入验证码。实际上大多时候可以用更简单的方法,如下:ele=wb:getEle(验证码控件名字);ele:setAttribute(value,str)为什么我的验证码与页面上不一样因为我们使用img:getURL读取验证码时已经刷新了验证码。所以验证码与页面上显示的并不一样,您只需要识别最新的验证码即可。如何直接获取页面的上图片,而不是重新下载有些验证码是绑定页面的,必须识别页面上的验证码才行。那么可以使用image.capture函数直接抓屏屏幕上的图片即可。请参考:image.capture函数。更好的方法是使用ele:exec(Copy)函数直接拷贝页面上的图片到剪贴板。然后使用img:getClipBD()获取图片。请参考:ele:exec(Copy)函数img:getClipBD()函数四、关于剪切图片看上面的示意图,Crop就是选取绿色方框内的区域去清除绿色方框外面的区域.必须保证里面的面积正好可以平均分成四块(假设这里是四个验证码字符)这样以后调用img:split(1,4)就正好分成四个字符了分成四份的小图片其宽度应当正好是上面的红色小方块的宽度。高度与绿色方框一样,我这里画的参次不齐是为了让大家看清楚。如果你Crop的参数值不对,那么split就出错了.下载验证码图片以后,可以使用图像编辑软件打开高倍放大。五、使用种子填充算法去除验证码上的干扰线模拟精灵识别验证码的能用是强大的,一个函数即可以去除杂色杂点。img:bpp(1)img:bpp(24)经过上面两句代码的处理,速度很快,所有背景、干扰点、杂色荡然无存。但是有时候验证码中有大量的干扰线,并且位置随机变动的太历害,这时候我们在处理验证码以前首先去除这些干扰线并准确的去除背景提取字符.下面是一个模拟精灵初步处理后的验证码图片.已经去除了杂色、杂点.但是上面还是有干扰线.一个可选的办法是用中值滤波再处理一下。img:median(2);一个函数调用就可以,但是这样虽然去掉了干扰线,原来的字符也被少量的破坏了。下面是使用种子填充算法去除干扰线的源代码,不但能去除杂点,而且可以去除周围的空白(提取位置随机变化的验证码),稍加修改还能有更多的用途.下面是自动处理以后的效果下面是全部的源代码:--[[用一个table结构{x=0;y=0}表示图像上的「坐标点」用一组点构成table结构表示图像上的一条「线」。所有相连的黑色的点被认为是一条「连通线」。找出最长的一条「连通线」,被认为是字符,其他的认为是杂点。算法原理与种子填充算法相似。首先让用img:bpp函数处理为黑白图片,并初步去除杂色。先找到一个黑点,创建一个表示「坐标点」对象,并添加到「连通线」中。然后在黑点周围8个点中,再找黑色的点,找到就添加到「连通线」,这样一直递归
本文标题:易语言验证码识别技术带源码
链接地址:https://www.777doc.com/doc-4486300 .html