基本上的功能都有了,可惜还是差了一点点,一直都没有拿出来。
QQ验证码的样本实在太多,该死的图片比较又不是很聪明,4个图片往往只能辨别出2,3个,甚至一个都认不出来。有空的时候自己去写个图片识别的来
不管怎样,还是先把这些脚本给整理出来了,期待有朝一日出来新的图片比较API,让该死的QQ验证码见鬼去吧
----------------------------------------------------获取图片-----------------------------------------------------------------------
getImg= function()
local ele=wb:getEle("temp");--这是模拟程序web界面上的一个节点,用来显示程序运行过程的相关信息
tab={wb:eleImages()}; --枚举web页所有图片
img=image.new();
for i,tele in ipairs(tab) do
if tele:id()=='idtimage' then --获取指定id的图片
tele:exec("Copy"); --拷贝
img:getClipBD() ;--从粘贴板获取
end
end;
img:Crop(1,2,37,18);--修剪图片。查看下载下来的图片,不断微调。 每个验证码图片这个参数可能不同。
img2,img3,img4,img5=img:split(1,4); --分割图片
img:paint(100,100,40,20); --屏幕显示图片
img2:paint(100,120,10,20);
img3:paint(120,120,10,20);
img4:paint(140,120,10,20);
img5:paint(160,120,10,20);
img:save("c:\\temp\\temp.png");--把图片保存到本地
ele:setAttribute("value","已从指定网址得到图像");--在web界面上显示提示信息。
ele:setAttribute("value","拆分并保存图像已经完成");--在web界面上显示提示信息
return img;
end;
------------------------------得到样本图片并保存在数据岛的函数------------------------------------------------------------------
sampleImg=function()
--遍历图片目录,读取样本图片
local tkey={};
win.enumProc = function(dir,filename)
if(not dir)then
tkey[string.sub(filename,9,10)]=string.sub(filename,9,14); --文件名形如c:\test\1a.jpg
end;
return nStop();
end;
win.enumDir("c:\\test\\","*.jpg") --显示该目录*.jpg文件
--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( 0 , 0 , 9 , 16);--修剪单个字符
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,"验证码样本")
end;
----------------------------------------------把界面写入web窗体的函数-------------------------------------------------------
write= function()
html = [[
]]
wb:go("about:blank");
delay(100)
wb:wait("about")
wb:write(html);
wb:setTitle(true);
wb:setScroll(true);
delay(1000)
wb:wait("")
wb:show(true);
end;
--------------------------------------------------------------------------------------------------------------------
local timg = {}; --这是一个图像数组,用来储存还原后的验证码样本的图片数据
--必须进行一个转换,因为codekey里面只是base64编码的普通字符串,而timg 将是真正的图片对象(二进制数据)
---------------------------------还原到图片对象--------------------------------------------------------------
toImage = function(k,v)
local img = image.new();
local str = string.decode( v ,"");--首先进行base64解码,将纯文本转换为二进制数据
img:setBytes( str ,"*.jpg");--将二进制数据还原为图像
timg[k] = img;
end;
---------------------------------转换图片验证码到字符串的函数-----------------------------------------
function ImgToString(img)
function test(imgX) --test是一个被包含在函数中的内部函数
sleep(0);
local limit = (60 * 20) + (60 * 20); --最小相似度 local关键字声明为局部变量
local chr = "A"; --读取的字符
--testimg是一个被包含在函数中的内部函数,作为table.foreach的回调函数,k参数表示键,v参数表示值
testimg = function(k,v)
--调用image.testXX()函数得出相似度,类似的函数还有image.testX() image.test()
local n = imgX:testXX(timg[k]); --就是这个“图片比较”太垃圾,不然就没有问题了,55555
if(n
chr = k.."";
end;
end;
--遍历timg表,并调用testimg函数
for k,v in pairs(timg) do
testimg(k,v);
end;
return string.left(chr,1); --返回读取到的字符串首字符(如果每个字符有多个样本)
end;
--修剪图片
--image.Crop(img, 1 ,2 , 37 ,18 )
img:bpp(1);
img:bpp(24);
--上面的过程必须与下载样本时的代码完全一致。
--使用split函数分割图片
local img2,img3,img4,img5 = img:split(1,4);
win.messagePrint("正在检测图片,请稍候....");
return test(img2)..test(img3)..test(img4)..test(img5);
end;
-----------------------------------输出辨认结果-------------------------------------------
function showresult(str)
--下面我们把验证码的每个字符都转换为大写,并控制键盘顺序按键
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) );
win.consoleOpen()
print(code1);
print(code2);
print(code3);
print(code4);
end
-----------------------------------主调用-----------------------------------------------
wb=web.new();
write();--构建页面
sampleImg();--读取图片样本
tkey = ape:loadTable("验证码样本");
for k,v in pairs(tkey) do --验证样本
toImage(k,v); --转换为图像
end;
img = getImg();--读取图片
showresult(ImgToString(img));