e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (二) 图片验证码的识别
上一篇文章讲了“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 一 京东 商品搜索”
关于图片验证码的识别, 有多种方法, 之前有在Google, baidu上找了非常多的文章, 有非常多的方法去实现 ,但我学得使用 Google赞助的tesseract 工具,是比较不错的选择。tesseract是一个exe, 其实本文章实际上与Node.js已经没有太大的关系。因为我们要做的是如果调用这个exe.
保存验证码图片
WebdriverIo, 提供了一个接口为 saveScreenshot 就是可以保证当前页面的屏幕截图。 如下:

首先是打开一个新的窗口, captchaUrl,就是图片验证码的url地址, 如JD的是 https://authcode.jd.com/verify/image?a=1&acid=72c69aa3-7ffc-4934-b8cc-199750307af6&uid=72c69aa3-7ffc-4934-b8cc-199750307af6&yys=1413969656908%22, 放在IE中, F5,不停的刷新,你会发现,他在不停的变化。
就是保存屏幕截图。将图片存放在本地, Node.js 支持调用本地的exe, 请参考 http://nodejs.org/api/process.html 实际上就是执行CMD命令。tesseract 执行如 CMD > tesseract z:\snapshot.pgn result 执行后会在当前目录生成一个txt文件,内容就是识别后的文本。
但是在此, 为了提高识别的概率, 我会先将图片灰度化,然后再生成一张黑白图片, 最后给tesseract 支识别, 使用Node.js会比较麻烦, 所以我使用的.net c#实现, 然后做成一个服务 API, 然后,让Node.js去调用。
C#的内容如下:
[RoutePrefix("api/CaptchaDecoder")]
public class CaptchaDecoderController : ApiController
{
ILog log = LogManager.GetLogger("AppLog");
TesseractService _tesseract;
public CaptchaDecoderController()
{
log4net.Config.DOMConfigurator.Configure();
_tesseract = new TesseractService();
}
public CaptchaDecoderController(TesseractService tesseract)
{
_tesseract = tesseract;
}
[HttpPost]
public ServicePostResponse CaptchaDecoder(ServicePostRequest<CaptchaModel> request)
{
var response = new ServicePostResponse();
try
{
if(request == null)
{
throw new Exception("request is null");
}
if (string.IsNullOrEmpty(request.ExtraData.SystemId))
{
throw new Exception("request.ExtraData.SystemId is null or empty");
}
if (string.IsNullOrEmpty(request.ExtraData.FilePath))
{
throw new Exception("request.ExtraData.FilePath is null or empty");
}
var filePath = request.ExtraData.FilePath;
if (!File.Exists(filePath))
{
throw new Exception("File:" + request.ExtraData.FilePath + " doesn't exist");
}
using (Bitmap sourceBmp = new Bitmap(filePath))
{
GetGrayBitmap(sourceBmp);
GetBackWhiteBitmapNew(sourceBmp);
Bitmap bmp = ClearNoise(sourceBmp, 3);
bmp.Save(filePath + "_new.jpg");
fnOCR(@_tesseract.exePath, @filePath + "_new.jpg " + filePath + "_result nobatch digits");
if (File.Exists(filePath + "_result.txt"))
{
using (StreamReader file = File.OpenText(filePath + "_result.txt"))
{
response.ExtraData = file.ReadLine();
file.Close();
}
}
else
{
throw new Exception("generate the result fail");
}
bmp.Dispose();
sourceBmp.Dispose();
}
response.IsSuccess = true;
response.Total = 1;
}
catch (Exception ex)
{
log.Error(ex);
response.Errors = ex.Message;
response.IsSuccess = false;
response.Total = 0;
}
finally
{
}
return response;
}
private string GetCurrentSeqValue()
{
return System.DateTime.Now.Month.ToString("00");
}
private void GetGrayBitmap(Bitmap bmp)
{
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
//获取该点的像素的RGB的颜色
Color color = bmp.GetPixel(i, j);
//利用公式计算灰度值
int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);
Color newColor = Color.FromArgb(gray, gray, gray);
bmp.SetPixel(i, j, newColor);
}
}
}
private void GetBackWhiteBitmap(Bitmap bitmap)
{
int v = ImageHelper.ComputeThresholdValue(bitmap);
ImageHelper.PBinary(bitmap, v);
}
private void GetBackWhiteBitmapNew(Bitmap bmp)
{
int average = 0;
for (int i = 0; i < bmp.Width; i++)
{
for (int j = 0; j < bmp.Height; j++)
{
Color color = bmp.GetPixel(i, j);
average += color.B;
}
}
average = (int)(average * 1.0 / (bmp.Width * bmp.Height));
}
public Bitmap ClearNoise(Bitmap bmpobj, int MaxNearPoints)
{
int dgGrayValue = ImageHelper.ComputeThresholdValue(bmpobj);
Color piexl;
Bitmap bmp = new Bitmap(bmpobj);
int nearDots = 0;
//逐点判断
for (int i = 0; i < bmpobj.Width; i++)
for (int j = 0; j < bmpobj.Height; j++)
{
piexl = bmpobj.GetPixel(i, j);
if (piexl.R <= dgGrayValue)
{
nearDots = 0;
//判断周围8个点是否全为空
if (i == 0 || i == bmpobj.Width - 1 || j == 0 || j == bmpobj.Height - 1) //边框全去掉
{
bmp.SetPixel(i, j, Color.White);
}
else
{
if (bmpobj.GetPixel(i - 1, j - 1).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i, j - 1).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i + 1, j - 1).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i - 1, j).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i + 1, j).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i - 1, j + 1).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i, j + 1).R < dgGrayValue) nearDots++;
if (bmpobj.GetPixel(i + 1, j + 1).R < dgGrayValue) nearDots++;
}
if (nearDots <= MaxNearPoints)
bmp.SetPixel(i, j, Color.White); //去掉单点 && 粗细小3邻边点
}
else //背景
bmp.SetPixel(i, j, Color.White);
}
return bmp;
}
private void fnOCR(string v_strTesseractPath, string v_Arguments)
{
using (Process process = new System.Diagnostics.Process())
{
process.StartInfo.FileName = v_strTesseractPath;
process.StartInfo.Arguments = v_Arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.WaitForExit();
}
}
}
public class TesseractService
{
public virtual string exePath { get {
return @"C:\Program Files (x86)\Tesseract-OCR\tesseract.exe";
} }
}
上面的代码是ASP.NET WEBAPI应用。
最后,通Node.js的Http模块的功能,可以调用这个服务如下:
var http = require('http')
, fs = require('fs')
function decoderCaptchaECommerce(siteName, callback){
var requestData = {
ExtraData: {
SystemId : siteName,
FilePath : 'Z:\\snapshot.png'
}
};
var requestDataString = JSON.stringify(requestData);
var headers = {
'Content-Type': 'application/json',
'Content-Length': requestDataString.length
};
var options = {
host: '127.1.1.1'
, port: 80
, path: '/api/CaptchaDecoder/CaptchaDecoder'
, method : 'POST'
, headers: headers
};
var responseString = '';
var req = http.request(options, function(res){
res.setEncoding('utf-8');
res.on('data', function(data){
responseString += data;
console.log("验证服务结果:"+responseString);
});
res.on('end', function(){
var resultObject = JSON.parse(responseString);
callback(resultObject.ExtraData);
})
});
req.on('error', function(e) {
// TODO: handle error.
});
req.write(requestDataString);
req.end();
return responseString;
};
e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (二) 图片验证码的识别的更多相关文章
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (六) 自动化测试结构小节
上一篇‘e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (五) 如何让窗体记录登录 ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (四) Q 反回调
上一篇文章“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (三) SqlServ ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (三) SqlServer数据库的访问
上一篇文章“e2e 自动化集成测试 架构 京东 商品搜索 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step 二 图片验证码的识别” ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (一) 京东 商品搜索
之前有发布一篇文章“e2e 自动化集成测试 环境搭建 Node.js Selenium WebDriverIO Mocha Node-Inspector”, 主要是讲了,如何搭建环境, 其中开发环境使 ...
- e2e 自动化集成测试 架构 实例 WebStorm Node.js Mocha WebDriverIO Selenium Step by step (五) 如何让窗体记录登录状态Session
在写自动化测试的Node.js脚本时, 时常需要测试所写的case, 可能都需要去重新登录一遍,这将相当的耗时, 好在Selenium都借了Session的机制, 如果在最初的浏览器没有关闭的情况下, ...
- e2e 自动化集成测试 环境搭建 Node.js Selenium WebDriverIO Mocha Node-Inspector
Node.js已经出来了许多年载,至今才开始接触.周未在家闲来无事,一时心血来潮,Google了大量的文章,经过实验,终于可以把整个环境给搭起来, 废话不多话,请看步骤. 特别注意, 本文章是针对Wi ...
- 前端自动化之路之gulp,node.js
随着现在前端技术的不断发展,和各个公司对前端项目开发更新速度的要求,前端自动化越来越受到大家的重视,之前传统的前端开发方式已经越来越不能满足开发的需求了,于是各种自动化工具随之产生了.而gulp就是其 ...
- 【nodejs笔记1】配置webstorm + node.js +express + mongodb开发博客的环境
1. 安装webstorm 并破解 2. 安装node (以及express框架) 至官网下载并安装.(http://nodejs.org)v0.10.32 msi 安装后测试,打开命令行, c ...
- WebStorm+Node.js开发环境的配置
1 下载地址: webstorm:http://www.jetbrains.com/webstorm node.js:https://nodejs.org/download/ 2 安装node.js ...
随机推荐
- sb 讲解 (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
代码:(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]] 输出sb. 分段解析: 首先解析s: (! ...
- 跨过slf4j和logback,直接晋级log4j 2
今年一直关注log4j 2,但至今还没有出正式版.等不及了,今天正式向大家介绍一下log4j的升级框架,log4j 2. log4j,相信大家都熟悉,至今对java影响最大的logging系统,至今仍 ...
- PHPCMS搭建wap手机网站
PHPCMS搭建PC端网站比较方便,但是在wap手机端方面却不怎么实用,而且自带的手机建站感觉不是很好,而且模版不好控制,现在对其进行修改,手机建站个人感觉比较方便 首先在phpcms/libs/fu ...
- JAVA CAS单点登录(SSO) 教程
一.教程前言 教程目的:从头到尾细细道来单点登录服务器及客户端应用的每个步骤 单点登录(SSO):请看百科解释猛击这里打开 本教程使用的SSO服务器是Yelu大学研发的CAS(Central Auth ...
- ADO.net--杂七杂八(一)
private void BtnConnectDataBase_Click(object sender, RoutedEventArgs e) { string connectionString = ...
- Unity寻路的功能总结
源地址:http://blog.csdn.net/sgnyyy/article/details/21878163 1. 利用Unity本身自带的NavMesh 这篇文章已经比较详细,可能对于很多需要a ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- winform学习日志(十九)----------真正三层架构之登录
摘要:一:三层构架的基础知识在项目开发的过程中,有时把整个项目分为三层架构,其中包括:表示层(UI).业务逻辑层(BLL)和数据访问层(DAL).三层的作用分别如下: 表示层:为用户提供交互操作界面, ...
- nginux做反向代理配置文件
做反向代理的配置文件最好单独创建一个文件,然后在主配置文件中使用 include nginx-test.config; 这样的方式来导入. 配置代码如下: ## Basic reverse prox ...
- 数据段、代码段、堆栈段、BSS段
在linux中,进程在内存中一般会分为5个段,用来存放从磁盘载入的程序代码,等. 这五个段分别是: BSS段: 通常用来存放程序中未初始化的全局变量的一块内存区域.属于静态内存分配. 问题:全局变量不 ...