Skip to content

Latest commit

 

History

History
250 lines (194 loc) · 9.27 KB

20180606.md

File metadata and controls

250 lines (194 loc) · 9.27 KB

了解验证码

什么是验证码?

所谓验证码,就是将一串随机产生的数字或符号,生成一幅图片,图片里加上一些干扰象素(防止OCR),由用户肉眼识别其中的验证码信息,输入表单提交网站验证,验证成功后才能使用某项功能,通俗说就是一种区分用户是计算机和人的公共全自动程序

验证码的作用

可以防止恶意破解密码、刷票、论坛灌水,有效防止某个黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试,所使用验证码技术是现在很多网站通行的方式(比如招商银行的网上个人银行,百度社区)。 没有验证码登陆,黑客会更加容易破解你的账号,通过组合码刷机等黑客技术来破取你的密码,有了验证码相当于加了一层很厚的屏障,安全系数很高。

常见的验证码

  1. 随机的四位数字的组合,这是最原始的验证码
  2. 随机数字图片验证码,图片上的字符比较中规中矩,验证作用比上一个好
  3. 随机数字+随机大小写英文字母图片验证码,每刷新一次,每个字符还会变位置
  4. 随机数字+随机大小写英文字母+随机干扰像素+随机位置图片验证码,比上一个验证作用更好,不易识别

如何识别验证码的内容?

所需要的工具:

识别工具,目前由Google维护,支持中文,默认的识别率很低,特别是中文,但是可以自己提供样本,训练提高识别率。

安装:

brew install tesseract --all-languages // MAC安装
npm install node-tesseract // // windows安装

在DOS窗口输入:tesseract,显示如图则证明安装成功

ZULBRNUK%7BBU$3%5BY~0JM0%7BGB.png

命令行使用方法:

tesseract imagename outputbase [-l lang] [-psm pagesegmode] [configfile…]

imagename为目标图片文件名,需加格式后缀;outputbase是转换结果文件名;lang是语言名称(在Tesseract-OCR中tessdata文件夹可看到以eng开头的语言文件eng.traineddata),如不标-l eng则默认为eng;pagesegmode则是生成结果显示相关配置。

例如:

tesseract 1.jpg result -psm 7 

tesseract code.jpg result -l chi_sim -psm 7 //  -l chi_sim 表示用简体中文字库, -psm 7 表示告诉tesseract code.jpg图片是一行文本,这个参数可以减少识别错误率,默认为3

node使用方法(官方示例):

var tesseract = require('node-tesseract');

// Recognize text of any language in any format
tesseract.process(__dirname + '/path/to/image.jpg',function(err, text) {
	if(err) {
		console.error(err);
	} else {
		console.log(text);
	}
});

// Recognize German text in a single uniform block of text and set the binary path

var options = {
	l: 'deu',
	psm: 6,
	binary: '/usr/local/bin/tesseract'
};

tesseract.process(__dirname + '/path/to/image.jpg', options, function(err, text) {
	if(err) {
		console.error(err);
	} else {
		console.log(text);
	}
});

运行结果:

图片描述图片描述

图片描述图片描述

尝试调用此方法后会在本地文件生成一个对应的txt文件,内容即为识别内容。可以看出来,对于简单清楚的验证码识别还比较准确,但是对于带有噪点或者其他影响的识别效果的就很坑,完全识别不出来,所以我们需要对图片进行一些处理,比如提高图片的阈值,比如设置为55%,可以用ps等软件实现,但是node中已经有相应的包graphicsmagick,可以对图像进行这种处理,比较方便。


非常实用的图像处理工具,一般后台想要处理图片就需要下载graphicsmagick,可以方便实现比如:制作缩略图、头像剪切等功能。 验证码的识别成功率跟图片质量关系密切,一般拿到后的验证码都得经过灰度化,二值化,去噪,利用graphicsmagick就可以很方便的做到。

安装:

brew install imagemagick
brew install graphicsmagick // Mac安装

npm install gm // windows安装

命令行使用方法:

gm convert 1.jpg -thumbnail "100x100!" output_1.jpg  // 非等比缩图,生成的图片大小是:100x100

gm convert 1.jpg 1.pdf  // 格式转换

node使用方法(官方示例):

var fs = require('fs')
  , gm = require('gm');

// resize and remove EXIF profile data
gm('/path/to/my/img.jpg')
.resize(240, 240)
.noProfile()
.write('/path/to/resize.png', function (err) {
  if (!err) console.log('done');
});

// some files would not be resized appropriately
// http://stackoverflow.com/questions/5870466/imagemagick-incorrect-dimensions
// you have two options:
// use the '!' flag to ignore aspect ratio
gm('/path/to/my/img.jpg')
.resize(240, 240, '!')
.write('/path/to/resize.png', function (err) {
  if (!err) console.log('done');
});

运行结果: 图片描述 图片描述 图片描述

可以看出,gm成功将这个图片进行裁剪或者转换为pdf格式,使用很方便。

使用node识别验证码示例

新建项目目录

在合适的磁盘目录下创建项目目录 node-orc

初始化项目

1.进入node-orc文件夹下 2.执行npm init,初始化package.json文件

安装依赖包

1.npm install gm 2.npm install node-tesseract

新建index.js,写入代码如下:

var fs        = require('fs');
var tesseract = require('node-tesseract');
var gm        = require('gm');

/**
 * 对图片进行阈值处理(默认55)
 */
function disposeImg (imgPath, newPath, thresholdValue) {
  return new Promise((resolve, reject) => {
    gm(imgPath)
      .threshold(thresholdValue || 55)
      .write(newPath, (err)=> {
        if (err) return reject(err);
        resolve(newPath);
      });
  });
}

/**
 * 识别阈值化后图片内容
 */
function recognizeImg (imgPath, options) {
  options = Object.assign({psm: 8}, options);
  // options = Object.assign({l: 'chi_sim'}, options); // 识别中文

  return new Promise((resolve, reject) => {
    tesseract
      .process(imgPath, options, (err, text) => {
        if (err) return reject(err);
        resolve(text.replace(/[\r\n\s]/gm, '')); // 去掉识别结果中的换行回车空格
      });
  });
}

async function recognize(imgPath, newPath, thresholdValue) {
  try {
    const newImgPath = await disposeImg(imgPath, newPath, thresholdValue)
    const result = await recognizeImg(newImgPath)
    console.log(`识别结果:${result}`)
  } catch (err) {
    console.error(`识别失败:${err}`);
  }
}

recognize('1.jpg', 'test_1.jpg')

运行代码

进入当前目录,运行node index即可直接打印出当前识别的结果

识别结果 图片描述图片描述

图片描述图片描述

图片描述图片描述

可以看到比之前的识别率高很多,但是还是细节方便识别不够好,不够完善,感兴趣的可以看看tesseract训练,训练一个自己的识别库,精确度会提高很多

注意: windows直接运行代码会提示Could not execute GraphicsMagick/ImageMagick: gm "convert",这是因为Windows系统找不到gm中的convert命令,所以需要我们安装个客户端工具GraphicsMagick(下载的时候要下载Q8版本的),然后,因为convert这个命令执行需要特定的环境,所以我们需要在电脑的环境变量中加gm.exe的所在目录

关于中文的识别

目前这个库只能识别英文,中文直接是乱码,如何识别中文呢? 我们可以下载一个中文库,下载地址如下:https://pan.baidu.com/s/13DCNSz-91dSgVShyN4eLmg,并下载[Tesseract-OCR][18]安装包,`tesseract`安装目录的`tessdata`文件是存放语言库的,可以将解压后的文件放入这个文件夹下,字库文件扩展名为.`raineddata` 简体中文字库文件名为 chi_sim.traineddata,使用的时候带上语言类型即可,例如:tesseract 7.jpg result -l chi_sim

中文识别效果:

图片描述图片描述

最后总结

  1. 对于简单的验证码直接用Tesseract识别
  2. 对于一些有噪点或者其他影响的验证码可以通过graphicsmagick进行图像处理,再用Tesseract识别
  3. 关于中文或者其他语言的识别需要单独下载相关的语言库并放到tessData文件夹下,并在Tesseract识别代码中配置一下

整个识别效果还是不够完善,想要识别结果的准确度更高,可以对代码进行Tesseract训练,因为这个稍微复杂点,之后会继续了解,希望大家多多交流指正!

相关代码

本文相关代码和图片github地址:https://github.com/fighting123/node-tesseract