Hui 的个人资料热带鱼-热的带鱼照片日志列表 工具 帮助

日志


2007/3/23

感谢stone

谢谢石头一直以来对鱼我的关心.
在黑暗的7月里给俺开导
在考研的日子里给俺鼓励~
在考研后的日子里给按照顾~~
在准备复试的日子里还把她心爱的mp4 借俺让按准备英语听力~~~
谢谢石头~~~~
俺会好好努力哈~~~
等俺好消息~
俺也有信心~
 

也许该给自己忙碌忙碌了

下周开始
如果顺利
将开始一周7天的忙碌日子
5天去动物园公交枢纽站工作
剩下2天准备复试和毕设
这样的日子一直得持续到这个学期结束
也许还是忙碌点好,这样生活就充实了
fighting......
fighting.......
鱼,加把劲
不要让人失望~~~
2007/3/19

[转载]男人的痛,女人不懂--停不了的爱

※1、女人永远也不知道男人为什么要学会坚强?
因为他们自己知道.他们虽然外表坚强.但内心很脆弱.他们永远想让自己身边的她觉得自己是最棒的.
☆2、女人永远也不知道男人为什么不会轻易掉眼泪?
因为他们自己知道.他们不是不会掉眼泪.只是他明白.一但眼泪掉下来了.这段感情也就结束了.
△3、女人永远也不知道男人为什么每次在心烦的时候那么喜欢抽烟?
因为他们自己知道.只有在烟雾中才能忆起他们过去美好的时光来寻求一点心里的平衡.
◇4、女人永远也不知道男人为什么要在分手以后还会对她嘘寒问暖?
因为他们自己知道.他们并不是想跟你做朋友.只是想挽回这段曾经属于他的感情.
※5、女人永远也不知道男人为什么每次在听到她被欺负了会显得那么发狂?
因为他们自己知道.哪怕这次架打输了.躺下了.他也会觉得高兴.因为他们宁愿自己受到伤害.也不愿意看到你哭泣.
☆6、女人永远也不知道男人为什么在分手以后会夜夜买醉?
因为他们知道.如果今晚不麻醉自己.那么今晚只能在思念中度过.

※7. 女人永远也不知道男人为什么每次出门会出手那么大方?
因为他们知道.他们宁愿自己一个人省吃检用.也不愿意你看到你被别人看不起.
☆8.女人永远也不知道男人为什么会那么爱对她发脾气?
因为他们自己知道.对她发脾气并不是不爱她.只是希望她在以后的路上不被别人所欺骗.
☆9.女人永远也不知道男人为什么会那么在意你以前的男朋友?
因为他们自己知道.并不是他们不自信.只是他们害怕有一天你会离他而去.
※10. 女人永远也不知道男人为什么看到你为别人写的日记之后还会那么镇静的听你解释?
因为他们自己知道.自己并不是不想发火.只是希望能从你的口中得知到底是他重要还是别人重要?
☆11、女人永远也不知道男人为什么不对她说我爱你⒊个字?
因为他们知道.并不是不想说.只是他们自己明白.⒈万句我爱你用在身上也不够  
2007/3/15

[转载]验证码突破学习二

模拟精灵是首个公开最有效的验证码识别技术的软件,
使用模拟精灵制作了大量的免费、商用群发软件,对很多复杂BT的验证码都能成功的识别。
但是验证码仍然需要精湛的技术与足够的耐心。请牢记这一点。
验证码识别不适合浮躁的人去做。

验证码识别是一项特殊的技术,任何一个公开的验证码识别代码都会很快的失效。
因为代码的公开后相关网站都会很快的更改验证码。
所以下面我只会介绍其原理。

在这里讨论验证码识别技术纯粹基于技术研究目的。
公开此技术也是为了让更多的网站采取更有效的防范措施。
禁止任何人利用这里介绍的验证码识别技术滥发垃圾信息。

本文介绍的验证码识别适用于比较复杂的图片验证码,也是大多数网站采用的方法。
有一些网站的验证码极简单,例如在网页中直接显示验证码字符而不是图片,或者图片的文件名直接就是验证码上的字符。
或者有其他规律可循,或者有其他明显的漏洞可以利用(例如通过改写访问验证码页面的源代码使验证码不刷新)。

这一类的验证码识别极其简单,只要熟练掌握web库element库的函数即可,不需要使用下面介绍的方法。

一、下载验证码样本

打开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格式。
简单的,在验证码上右键点选“图片另存为”,就可以看到格式(不一定准确)。

另外,你可以用UltraEdit等以二进制方式打开看文件头部

首先下载:
str = web.getURL("http://www.***.com/test.asp")
string.save( str,"c:\\test.bin")

然后用UE打开test.bin看文件头部(第一行)

jpg文件头部有 JFIF 字眼
png文件头部 有 PNG 字眼
gif文件头部有 GIF字眼

如果你搞不清楚,这时候就不要指定后缀名
img:getURL("http://vwww.***.com/test.asp","")
这样就可以下载了

二、生成验证码样本数据库

复制下面的代码并粘贴到fap程序的「脚本区块」内,然后点击"回放运行",最后再点击"读取源代码"。

你就可以在ApeML源代码最后面的「数据区块」中看到生成的验证码样本了。
将「数据区块」的内容复制需要使用验证码识别的fap模拟程序中覆盖「数据区块」即可。

local tkey ={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};
 
--在字典中添加所有数字键
for i =0,9,1 do
    tkey[ tostring(i) ] = 0;
end;

--如果一个字符有多个样本,例如 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脚本区块中即可

--从数据区块读取base64编码的图片数据
codekey = ape:loadTable("验证码样本");
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;
 
--载入验证码样本
tkey = ape:loadTable("验证码样本");
for k,v in pairs(tkey) do  --验证样本
    toImage(k,v); --转换为图像
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]);
            if(n<limit)then --比较最小相似度
                  limit = 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, 4 ,3 , 56 ,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;

需要识别验证码的地方添加类似下面的代码:

img = image.new()
img:getURL("http://www.***.com/test.asp","*.jpg")

--因为刷新了验证码与页面不一致,把验证码画到屏幕上
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);

上面我们用了模拟按键的方法输入验证码。
实际上大多时候可以用更简单的方法,如下:

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个点中,再找黑色的点,找到就添加到「连通线」,这样一直递归下去
直到遍历图像所有点,可能有几块。
 
清除杂点使用方法
image.scan(img);
 
清除杂点并切去掉周围的空白
image.scan(img,true);
--]]
f
unction image.scan(img,crop)
   
    --用一个table数组记录所有的「连通线」
     assert(img:ok(),"image.scan 的参数必须是一个有效的图片");
   
     local tlines ={};
    
     --首先计算出图片的高度宽度,避免重复的调用
     local w = img:width();
     local h = img:height();
         
 
    --[[以table形式定义一个数组,对应图象中的每个点。
    作用相当一个开关,首先值为false,但黑点首次被遍历到时。把这个值变为true。
    下次,再找到这个点时忽略。避免重复加入连通线。 
    --]]
    local tchked ={};
    for i=0,w,do
        tchked[i]={};
        for j=0,h,1  do
            tchked[i][j]=false;
        end;
    end;
    
    -----去噪
    img:bpp(1);
    img:bpp(24);
    
    --首先计算出各点的颜色值,避免在循环递归中重复的取
    local tcl={};
    for i=0,w,1  do
        tcl[i]={};
        for j=0,h,1   do
            tcl[i][j]=img:getPos(i,j);
        end;
    end;
 
   
    --[[
    算点数函数
    参数x,y 坐标
    参数tab 所属连通线;
    --]]
    local   function  seed(x,y,tab)
   
        ---出界了则返回
        if(x<0 or y<0 or x>w or y>h) then
            return;
        end;
             
        ---点的颜色为白色时,返回,不处理。
        if(tcl[x][y]==16777215)  then
            return;
        end;
       
        ---值为1,则计数加1,返回
        if ( tchked[x][y]) then
            return ;
        else
            table.insert(tab,{x=x,y=y} );--添加到连通线里
            tchked[x][y]=true;---当值为0时,把值置为1。
            seed(x+1,y-1,tab);
            seed(x,y-1,tab);
            seed(x-1,y-1,tab);
            seed(x-1,y,tab);
            seed(x+1,y,tab);
            seed(x-1,y+1,tab);
            seed(x,y+1,tab);
            return seed(x+1,y+1,tab); --这里可以用一个尾调用(参考教程中的函数部份),加快递归的速度。
        end;
    end;
 
   
    ---------------------------
      
    ----遍历图像中的所有点
    for i=0,w,1   do
        for j=0,h,1  do
            ---如果是黑色的点,而且没有被计过数,则调用seed函数。
            if(tcl[i][j]==0 and (not tchked[i][j])) then       
                local tab = {}
                seed(i,j,tab);
                table.insert(tlines,tab); --添加一条连通线
   
            end;
        end;
    end;
         
    --现在tlines 里记录了的有的连通线,我们现在需要根据连通线的长度排序 
    sproc =  function(l,l2)  
        return table.maxn(l) > table.maxn(l2);--长的连通线排到前面
    end;
    table.sort(tlines,sproc)
              
    --把图像全部画成白色的点     
    for i=0,w,1  do
        for j=0,h,1  do
            img:setPos( i , j, 16777215);
        end;
    end;
         
    --然后把最长的一条连通线画上去
    for i,point in  ipairs(tlines[1])  do
        img:setPos( point.x, point.y , 0);  
    end;
   
 
    --如果需要去掉周围的空白
    if(crop)then
        local n = table.maxn(tlines[1])
           
        --排序最长连通线中的所有坐标点
        sproc =  function(pt,pt2)  
            return  (pt.x <pt2.x );--*左的排前面
        end;
        table.sort(tlines[1],sproc);
        local x,x2 = tlines[1][1].x, tlines[1][n].x;
   
        --排序最长连通线中的所有坐标点
        sproc =  function(pt,pt2)  
            return (pt.y <pt2.y );--*上的排前面
        end;
        table.sort(tlines[1],sproc);
        local y,y2 = tlines[1][1].y, tlines[1][n].y;
       
        img:Crop( x,y,x2+1,y2)
    end;
   
end;

[转载]关于突破验证码的学习一

验证码识别技术

模拟精灵是首个公开最有效的验证码识别技术的软件,
使用模拟精灵制作了大量的免费、商用群发软件,对很多复杂BT的验证码都能成功的识别。
但是验证码仍然需要精湛的技术与足够的耐心。请牢记这一点。
验证码识别不适合浮躁的人去做。

验证码识别是一项特殊的技术,任何一个公开的验证码识别代码都会很快的失效。
因为代码的公开后相关网站都会很快的更改验证码。
所以下面我只会介绍其原理。

在这里讨论验证码识别技术纯粹基于技术研究目的。
公开此技术也是为了让更多的网站采取更有效的防范措施。
禁止任何人利用这里介绍的验证码识别技术滥发垃圾信息。

本文介绍的验证码识别适用于比较复杂的图片验证码,也是大多数网站采用的方法。
有一些网站的验证码极简单,例如在网页中直接显示验证码字符而不是图片,或者图片的文件名直接就是验证码上的字符。
或者有其他规律可循,或者有其他明显的漏洞可以利用(例如通过改写访问验证码页面的源代码使验证码不刷新)。

这一类的验证码识别极其简单,只要熟练掌握web库element库的函数即可,不需要使用下面介绍的方法。

一、下载验证码样本

打开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格式。
简单的,在验证码上右键点选“图片另存为”,就可以看到格式(不一定准确)。

另外,你可以用UltraEdit等以二进制方式打开看文件头部

首先下载:
str = web.getURL("http://www.***.com/test.asp")
string.save( str,"c:\\test.bin")

然后用UE打开test.bin看文件头部(第一行)

jpg文件头部有 JFIF 字眼
png文件头部 有 PNG 字眼
gif文件头部有 GIF字眼

如果你搞不清楚,这时候就不要指定后缀名
img:getURL("http://vwww.***.com/test.asp","")
这样就可以下载了

二、生成验证码样本数据库

复制下面的代码并粘贴到fap程序的「脚本区块」内,然后点击"回放运行",最后再点击"读取源代码"。

你就可以在ApeML源代码最后面的「数据区块」中看到生成的验证码样本了。
将「数据区块」的内容复制需要使用验证码识别的fap模拟程序中覆盖「数据区块」即可。

local tkey ={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};
 
--在字典中添加所有数字键
for i =0,9,1 do
    tkey[ tostring(i) ] = 0;
end;

--如果一个字符有多个样本,例如 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脚本区块中即可

--从数据区块读取base64编码的图片数据
codekey = ape:loadTable("验证码样本");
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;
 
--载入验证码样本
tkey = ape:loadTable("验证码样本");
for k,v in pairs(tkey) do  --验证样本
    toImage(k,v); --转换为图像
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]);
            if(n<limit)then --比较最小相似度
                  limit = 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, 4 ,3 , 56 ,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;

需要识别验证码的地方添加类似下面的代码:

img = image.new()
img:getURL("http://www.***.com/test.asp","*.jpg")

--因为刷新了验证码与页面不一致,把验证码画到屏幕上
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);

上面我们用了模拟按键的方法输入验证码。
实际上大多时候可以用更简单的方法,如下:

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个点中,再找黑色的点,找到就添加到「连通线」,这样一直递归下去
直到遍历图像所有点,可能有几块。
 
清除杂点使用方法
image.scan(img);
 
清除杂点并切去掉周围的空白
image.scan(img,true);
--]]
f
unction image.scan(img,crop)
   
    --用一个table数组记录所有的「连通线」
     assert(img:ok(),"image.scan 的参数必须是一个有效的图片");
   
     local tlines ={};
    
     --首先计算出图片的高度宽度,避免重复的调用
     local w = img:width();
     local h = img:height();
         
 
    --[[以table形式定义一个数组,对应图象中的每个点。
    作用相当一个开关,首先值为false,但黑点首次被遍历到时。把这个值变为true。
    下次,再找到这个点时忽略。避免重复加入连通线。 
    --]]
    local tchked ={};
    for i=0,w,do
        tchked[i]={};
        for j=0,h,1  do
            tchked[i][j]=false;
        end;
    end;
    
    -----去噪
    img:bpp(1);
    img:bpp(24);
    
    --首先计算出各点的颜色值,避免在循环递归中重复的取
    local tcl={};
    for i=0,w,1  do
        tcl[i]={};
        for j=0,h,1   do
            tcl[i][j]=img:getPos(i,j);
        end;
    end;
 
   
    --[[
    算点数函数
    参数x,y 坐标
    参数tab 所属连通线;
    --]]
    local   function  seed(x,y,tab)
   
        ---出界了则返回
        if(x<0 or y<0 or x>w or y>h) then
            return;
        end;
             
        ---点的颜色为白色时,返回,不处理。
        if(tcl[x][y]==16777215)  then
            return;
        end;
       
        ---值为1,则计数加1,返回
        if ( tchked[x][y]) then
            return ;
        else
            table.insert(tab,{x=x,y=y} );--添加到连通线里
            tchked[x][y]=true;---当值为0时,把值置为1。
            seed(x+1,y-1,tab);
            seed(x,y-1,tab);
            seed(x-1,y-1,tab);
            seed(x-1,y,tab);
            seed(x+1,y,tab);
            seed(x-1,y+1,tab);
            seed(x,y+1,tab);
            return seed(x+1,y+1,tab); --这里可以用一个尾调用(参考教程中的函数部份),加快递归的速度。
        end;
    end;
 
   
    ---------------------------
      
    ----遍历图像中的所有点
    for i=0,w,1   do
        for j=0,h,1  do
            ---如果是黑色的点,而且没有被计过数,则调用seed函数。
            if(tcl[i][j]==0 and (not tchked[i][j])) then       
                local tab = {}
                seed(i,j,tab);
                table.insert(tlines,tab); --添加一条连通线
   
            end;
        end;
    end;
         
    --现在tlines 里记录了的有的连通线,我们现在需要根据连通线的长度排序 
    sproc =  function(l,l2)  
        return table.maxn(l) > table.maxn(l2);--长的连通线排到前面
    end;
    table.sort(tlines,sproc)
              
    --把图像全部画成白色的点     
    for i=0,w,1  do
        for j=0,h,1  do
            img:setPos( i , j, 16777215);
        end;
    end;
         
    --然后把最长的一条连通线画上去
    for i,point in  ipairs(tlines[1])  do
        img:setPos( point.x, point.y , 0);  
    end;
   
 
    --如果需要去掉周围的空白
    if(crop)then
        local n = table.maxn(tlines[1])
           
        --排序最长连通线中的所有坐标点
        sproc =  function(pt,pt2)  
            return  (pt.x <pt2.x );--*左的排前面
        end;
        table.sort(tlines[1],sproc);
        local x,x2 = tlines[1][1].x, tlines[1][n].x;
   
        --排序最长连通线中的所有坐标点
        sproc =  function(pt,pt2)  
            return (pt.y <pt2.y );--*上的排前面
        end;
        table.sort(tlines[1],sproc);
        local y,y2 = tlines[1][1].y, tlines[1][n].y;
       
        img:Crop( x,y,x2+1,y2)
    end;
   
end;
    

 

 

2007/3/12

心烦

不知道为什么
想到即将要逝去的.........
心里就是很难过.
我无能为力~~~
也许,
本身就是这样的.
不必为这个而去想太多.
我想去改变,可我凭什么去改变~~~
 
2007/3/8

[转载]服务器安全配置

呵呵看了这篇文章,发觉自己在配置服务器的时候有些细节还是有遗漏,多学多实践才是硬道理
 
我们从裸机说起——
    首先,拔掉网线,按需求分区之后将所有盘格式化为NTFS,在D盘安装系统。系统装完之后立刻做一个裸系统的ghost备份,以防后面配置的过程中出意外。
    先把驱动都装上是必要的。之后先装防火墙,选择一款好的防火墙是很重要的。能买硬件防火墙最好,推荐的选择:cisco pix系列、天融信 NGFW系列、冰之眼(入侵检测系统)。没有硬件防火墙的情况下,使用软件防火墙,推荐:Blackice(我个人的最爱)、Checkpoint(以色列国家级防火墙)、ZoneAlarm(不太熟悉,但口碑不错),虽然比较喜欢天网防火墙,但是不推荐服务器用天网。
装完防火墙装杀毒软件,推荐:KV江民杀毒软件(好东西)、诺顿(虽然好,但比较霸道)、卡巴斯基(听说比较耗内存,但对病毒疗效狂好)。
开始安装各种需要的软件,如果是2003系统,别忘了装IIS。以上所有软件都装在一个非系统盘的指定盘里。
下面开始给系统打补丁,首先用手头有的光盘给2k打上SP4或给2003打上SP1。在本地操作的情况下将能打系统和软件的补丁都打上。之后,在确认防火墙和杀毒软件都设置好的情况下插上网线,开始window update,并升级杀毒软件至最新病毒库。打完所有的系统和软件的补丁之后,将网线拔掉,把所有临时文件和系统补丁留下的卸载文件全部删除,如果觉得占用空间太多还可以把%systemroot%\System32\dllcache\下的所有文件删除(系统备份文件),这将使最后的ghost备份文件体积比较小。然后再次用ghost备份系统。
之后删除不安全的组件,需要将WScript.Shell, WScript.Network, Shell.application删除掉。在cmd下分别输入(以2k为例,2003路经为D:\windows):
regsvr32/u D:\WINNT\System32\wshom.ocx
del D:\WINNT\System32\wshom.ocx
重新启动,就OK了。另外入侵者可以利用getobject("WINNT")获得用户和进程的列表,可以将Workstation服务禁用作为防范措施。
设置权限是必要的。首先,确定IIS里要建立几个站点,之后为每个站点建立一个用户。在IIS站点的目录安全性里选择让这个用户作为匿名访问的帐户。再设置所有分区都禁止这个用户访问,而在站点对应的文件夹设置允许此用户访问。这样即使站点被入侵,入侵者也拿不到服务器的shell。
一切做好之后用ghost再次备份,并将做好的备份文件放在与服务器不在同一局域网的机器上或相对安全的地方。插上网线,服务器就可以安全的正常工作了。之后可以在每次服务器重起时还原一次系统,这都是后话了。
2007/3/7

宝贝,都是我的错

睡不醒 听见雨的声音 
看不清 你离开的背景 
睁开眼 看自己伤心的表情 
转过身 是别人的风景 
天不睛 大雨下个不停 
碎了心 让我怎么安静 
没有你 梦被孤独寂寞惊醒 
还有谁 在雨中聆听 
宝贝 不要再哭 
都是我的错 
不要再难过 
只要你能幸福快乐 
我做什么都值得 
回回头 再看看我 
宝贝 不要再哭 
都是我的错 
请你原谅我 
我的世界失去颜色 
我的心被风吹着 
那份爱 在等待
 

天不睛 大雨下个不停 
碎了心 让我怎么安静 
没有你 梦被孤独寂寞惊醒 
还有谁 在雨中聆听 
宝贝 不要再哭 
都是我的错 
不要再难过 
只要你能幸福快乐 
我做什么都值得 
回回头 再看看我 
宝贝 不要再哭 
都是我的错 
请你原谅我 
我的世界失去颜色 
我的心被风吹着 
那份爱 在等待 
宝贝 不要再哭 
都是我的错 
请你原谅我 
我的世界失去颜色 
我的心被风吹着 
那份爱 在等待 

过元宵

元宵过得开心又痛苦~
和大家一起玩挺开心,但天公不作美,把我们都冻得不成样了,俺还看到石头的嘴唇互相打架了~~~
冷得连拍照的兴趣都没了.
北京这天气,真的是雪打灯了~~
去雍和宫有点失望,我们被骗了10块钱,那香哪是香啊,一烧就弯曲了,然后整个着了,灭不了.无奈扔了.记得我们那的香都是烧起来味很香的
而且香中间是有一根竹条的.点了根本不会弯曲.呵呵各地的佛,菩萨都不一样,很明显~
难道真有佛吗?呵呵刚许完愿就收到了某人的短信.虽然问候的是学习上的事,可我许的不是这样哈~~
回来后又出去吃汤圆,放烟花了.真冷~大街上就我和我师妹俩,天气冷,人气也冷.吃完放完就匆匆回去睡觉,累死,冻死我了~~
好久没这么累了..
 
2007/3/2

郁闷

今天一个研究生加我QQ,说了那个QMD的事,还说要是不看我的spaces,真会闹误会,我就纳闷了
他怎么会知道我的spaces地址呢?百思不得其解.
查了我在论坛,QQ马甲上的所有信息,都没有我的spaces地址
突然,想起来了可以百度啊
用shuguohui一百度,
果然,有spaces的地址,还是检索信息的第一条
hoho,以后不用shuguohui去注册了,用huihui好了~~