VBS也玩验证码识别

标签: , , ,

这几天不是在学Python嘛,怎么还老写VBS的东西。

其实我学Python有两个原因,一是很多开源的BT下载软件是用Python写的,哪天没事可以改改源码做做弊什么的;二是以前无意中看到《python验证码识别之Discuz》的系列文章,顿时感到Python之强大,验证码都能识别,想做什么不行?

几天下来学了点Python的皮毛,于是迫不及待的看了一下《python验证码识别之Discuz(一) 》,发现依然看不懂。并不是看不懂语法,而是看不懂算法。PIL库固然强大,但是光靠库本身还是无法识别验证码,还得加上图形算法。可见语言什么的都是浮云,会算法才是王道。

于是Google了一下验证码识别的原理,自己尝试着用VBS识别晨光BT(该网站需要IPv6网络才能访问)的验证码,发现并没有想象中的困难。之所以选择晨光BT的验证码,是因为它本身比较简单,再加上我还有它的源码,识别起来会相对容易些。

鉴于大部分网络依然是IPv4,我把生成验证码的页面放到了博客的测试目录中,可以点击这里查看。

cgbt

用PS放大以后可以知道,验证码只是简单添加了些杂点。首先把黑色边框去掉,然后把杂点去掉(颜色改成背景色白色)。

'加载图片
Set Image = CreateObject("WIA.ImageFile")
Image.LoadFile "authcode.png"
Width = Image.Width
Height = Image.Height
Set Vector = Image.ARGBData

'去除边框
For i = 1 To Vector.Count
    If  (i - 1) \ Width = 0 Or _
        (i - 1) \ Width = Height - 1 Or _
        i Mod Width = 0 Or _
        (i - 1) Mod Width = 0 Then
        Vector(i) = &HFFFFFFFF
    End If
Next

'去除杂点
For i = 1 To Vector.Count
    If Vector(i) <> &HFF000000 Then
        Vector(i) = &HFFFFFFFF
    End If
Next

接下来要确定单个验证码的范围,即能把单个验证码框起来的最小矩形的对应坐标。

'获取横向范围
Set Range = CreateObject("WIA.Vector")
For i = 1 To Width
    For j = i To Vector.Count Step Width
        If Vector(j) <> &HFFFFFFFF Then
            Range.Add i
            Exit For
        End If
    Next
Next

'写到这里肚子饿了,感谢怒云提供的算法
'先将Vector转换成String
str = Range(1)
For i = 1 To Range.Count - 1
    If Range(i+1) - Range(i) < 3 Then
        str = str & "," & Range(i+1)
    Else
        str = str & ";" & Range(i+1)
    End If
Next

'然后再分组
x = Split(str,";")
For i = 0 To UBound(x)
    authcode = authcode & GetCode(Split(x(i),","))
Next

x数组保存了6个单独验证码的横向坐标,遍历数组,调用GetCode函数识别验证码。下面是函数的关键算法。

'获取横向范围对应的纵向范围
min = 20
max = 1
For i = xn(0) To xn(UBound(xn))
    For j = i To Vector.Count Step Width
        If Vector(j) <> &HFFFFFFFF Then
            y = (j - i) / Width
            If y < min Then min = y
            If y > max Then max = y
        End If
    Next
Next

'获取单个验证码范围内的ARGB
For i = min To max
    For j = xn(0) To xn(UBound(xn))
        code.Add Vector(i * Width + j)
    Next
Next

'与标准的验证码对比
For Each item In Standard
    Dim difference : difference = 0
    For i = 1 To code.Count
        '这里数组可能会越界,所以上面要On Error Resume Next
        If code(i) <> Standard(item)(i-1) Then
            difference = difference + 1
        End If
    Next
    oDic(difference) = item
Next

'筛选出最匹配的
min = 80
For Each item In oDic
    If item < min Then min = item
Next

先求出单个验证码对应的纵向范围(横向范围已经当成参数传递),然后把范围内的点的ARGB值和标准验证码(standard字典变量)对应点的ARGB值做比较,不同的话difference加1,最后选出difference值最小(即最匹配)的返回。

那就有一个问题了,标准验证码的值怎么得到?这就要靠你的PS功底了。

cgbt2

用PS将单个验证码切片并除杂以后获得,最笨的方法是一个个人工写。比如上图中的W标准值依次为&HFF000000,&HFF000000,&HFFFFFFFF……当然傻子才会这么做,写个VBS完成。

Set img = CreateObject("WIA.ImageFile")
img.LoadFile "w.bmp"
Set v = img.ARGBData
For i = 1 To v.Count
    out = out & "&H" & Hex(v(i)) & ","
Next
out = Mid(out,1,Len(out)-1)
WScript.Echo "Standard(""w"") = Array(" & out & ")" 

假设上面的W切片后保存为w.bmp,上面的程序将输出对应的标准值数组(前提是你的PS过关,保证切片是标准)。虽然上面的脚本可以节省标准值数组的时间,但是切片的工作还是得人工完成(虽然PS也支持VBS自动化,不过等我学会了人工已经完成了),要知道一共有25个字符啊!写这个程序的绝大部分时间都耗在这个上面了。。。

第一次写那么长的文章(主要是代码长),我知道不会有几个人能看到这一行,看到这一行也不一定看得懂。因为我知道,看别人的程序常常比自己写程序还要困难。最后不要脸的说一句,我果然是天才。

源码下载:[download id=50]

随机文章:

  1. VBS调用WMI搜索文件
  2. windows live writer代码高亮插件
  3. 未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包
  4. “WindowsLive.Writer.CoreServices.HttpRequestHelper”的类型初始值设定项引发异常
  5. VBS面向对象编程与Me关键字

23 条评论 发表在“VBS也玩验证码识别”上

  1. good说道:

    很有创意啊

  2. micheal说道:

    写得真是不错啊。。。学习了

  3. 郑斯彬说道:

    借鉴了

  4. prophetk说道:

    借鉴你的代码 我还真的把西贴图片里的报价处理出来了 谢啦

  5. MMMM说道:

    确实不要脸。。。

  6. 神梦无痕说道:

    图片不见了!

留下回复