对于类似以下简单的验证码的识别方案:

1、

2

3

4、

1、建库:切割验证码为单个字符,人工标记,比如:A。

2、识别:给一个验证码:切割为单个字符,在库中查询识别。

/***
* author:chzeze
* 识别验证码并返回
* train_path 验证码字母图库位置
* 验证码图片缓存位置:Configuration.getProperties("web_save_path")+"/captcha.jpg"
*/
public class AmGetCaptchaTest {
private static Logger logger = Logger.getLogger(AmGetCaptchaTest.class);
private static String train_path = "/data/sata/share_sata/AmazonCrawl/amazonWeb/captcha";
private static Map<BufferedImage, String> trainMap = null;
private static int index = 0;
private static int imgnum = 0;
private static MultiThreadedHttpConnectionManager httpConnectionManager = new MultiThreadedHttpConnectionManager();
private static HttpClient client = new HttpClient(httpConnectionManager);
/* static {
//每主机最大连接数和总共最大连接数,通过hosfConfiguration设置host来区分每个主机
client.getHttpConnectionManager().getParams().setDefaultMaxConnectionsPerHost(8);
client.getHttpConnectionManager().getParams().setMaxTotalConnections(48);
client.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
client.getHttpConnectionManager().getParams().setSoTimeout(10000);
client.getHttpConnectionManager().getParams().setTcpNoDelay(true);
client.getHttpConnectionManager().getParams().setLinger(1000);
//失败的情况下会进行3次尝试,成功之后不会再尝试
client.getHttpConnectionManager().getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler());
}*/
public static int isBlack(int colorInt) {
Color color = new Color(colorInt);
if (color.getRed() + color.getGreen() + color.getBlue() <= 100) {
return 1;
}
return 0;
} public static int isWhite(int colorInt) {
Color color = new Color(colorInt);
if (color.getRed() + color.getGreen() + color.getBlue() > 600) {
return 1;
}
return 0;
} public static BufferedImage removeBackgroud(String picFile)
throws Exception {
BufferedImage img = ImageIO.read(new File(picFile));
img = img.getSubimage(1, 1, img.getWidth() - 2, img.getHeight() - 2);
int width = img.getWidth();
int height = img.getHeight();
double subWidth = width / 5.0;
for (int i = 0; i < 5; i++) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int x = (int) (1 + i * subWidth); x < (i + 1) * subWidth
&& x < width - 1; ++x) {
for (int y = 0; y < height; ++y) {
if (isWhite(img.getRGB(x, y)) == 1)
continue;
if (map.containsKey(img.getRGB(x, y))) {
map.put(img.getRGB(x, y), map.get(img.getRGB(x, y)) + 1);
} else {
map.put(img.getRGB(x, y), 1);
}
}
}
int max = 0;
int colorMax = 0;
for (Integer color : map.keySet()) {
if (max < map.get(color)) {
max = map.get(color);
colorMax = color;
}
}
for (int x = (int) (1 + i * subWidth); x < (i + 1) * subWidth
&& x < width - 1; ++x) {
for (int y = 0; y < height; ++y) {
if (img.getRGB(x, y) != colorMax) {
img.setRGB(x, y, Color.WHITE.getRGB());
} else {
img.setRGB(x, y, Color.BLACK.getRGB());
}
}
}
}
return img;
} public static BufferedImage removeBlank(BufferedImage img) throws Exception {
int width = img.getWidth();
int height = img.getHeight();
int start = 0;
int end = 0;
Label1: for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
if (isBlack(img.getRGB(x, y)) == 1) {
start = y;
break Label1;
}
}
}
Label2: for (int y = height - 1; y >= 0; --y) {
for (int x = 0; x < width; ++x) {
if (isBlack(img.getRGB(x, y)) == 1) {
end = y;
break Label2;
}
}
}
return img.getSubimage(0, start, width, end - start + 1);
} public static List<BufferedImage> splitImage(BufferedImage img)
throws Exception {
List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
int width = img.getWidth();
int height = img.getHeight();
List<Integer> weightlist = new ArrayList<Integer>();
for (int x = 0; x < width; ++x) {
int count = 0;
for (int y = 0; y < height; ++y) {
if (isBlack(img.getRGB(x, y)) == 1) {
count++;
}
}
weightlist.add(count);
}
for (int i = 0; i < weightlist.size();i++) {
int length = 0;
while (i < weightlist.size() && weightlist.get(i) > 0) {
i++;
length++;
}
if (length > 2) {
subImgs.add(removeBlank(img.getSubimage(i - length, 0,
length, height)));
}
}
return subImgs;
} public static Map<BufferedImage, String> loadTrainData() throws Exception {
if (trainMap == null) {
Map<BufferedImage, String> map = new HashMap<BufferedImage, String>();
File dir = new File(train_path);
File[] files = dir.listFiles();
for (File file : files) {
map.put(ImageIO.read(file), file.getName().charAt(0) + "");
}
trainMap = map;
}
return trainMap;
} public static String getSingleCharOcr(BufferedImage img,
Map<BufferedImage, String> map) {
String result = "#";
int width = img.getWidth();
int height = img.getHeight();
int min = width * height;
for (BufferedImage bi : map.keySet()) {
int count = 0;
if (Math.abs(bi.getWidth()-width) > 2)
continue;
int widthmin = width < bi.getWidth() ? width : bi.getWidth();
int heightmin = height < bi.getHeight() ? height : bi.getHeight();
Label1: for (int x = 0; x < widthmin; ++x) {
for (int y = 0; y < heightmin; ++y) {
if (isBlack(img.getRGB(x, y)) != isBlack(bi.getRGB(x, y))) {
count++;
if (count >= min)
break Label1;
}
}
}
if (count < min) {
min = count;
result = map.get(bi);
}
}
return result;
} public static String getAllOcr(String file) throws Exception {
BufferedImage img = removeBackgroud(file);//去除重影
List<BufferedImage> listImg = splitImage(img);//切割图片
Map<BufferedImage, String> map = loadTrainData();
String result = "";
for (BufferedImage bi : listImg) {
result += getSingleCharOcr(bi, map);
}
//ImageIO.write(img, "JPG", new File("result6\\" + result + ".jpg"));
return result;
}
/***
* 下载验证码图片暂时保存供识别程序使用
* @param imgurl 验证码图片url
*/
public static void downloadimg(String imgurl)
{
//HttpClient httpClient = new HttpClient(); //httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(10000);
//httpClient.getHttpConnectionManager().getParams().setSoTimeout(10000);
GetMethod getMethod = new GetMethod(imgurl);
try {
int statusCode = client.executeMethod(getMethod);
System.out.println(statusCode);
if (statusCode != HttpStatus.SC_OK) {
System.err.println("("+statusCode+")Method failed: "+ getMethod.getStatusLine());
logger.info("("+statusCode+")Method failed: "+ getMethod.getStatusLine());
}
InputStream inputStream = getMethod.getResponseBodyAsStream();
OutputStream outStream = new FileOutputStream("/data/sata/share_sata/AmazonCrawl/amazonWeb/captcha.jpg");
IOUtils.copy(inputStream, outStream);
inputStream.close();
outStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
//logger.info(new Date()+"captcha appear exception:"+e.getMessage());
try {
//若遇到异常则睡眠20秒后继续重试
Thread.sleep(20000);
} catch (InterruptedException e1) {
logger.error(e1);
}
e.printStackTrace();
}finally {
getMethod.releaseConnection();
}
}
/***
* 抽取页面验证码并返回
* @param stringBuffer
* @return 验证码字符串
*/
public static String GetCaptcha(StringBuilder html){
String captcha_str="######";//未识别则为#
Document doc = Jsoup.parse(html.toString());
String imgurl = doc.select("div[class=a-row a-text-center]").get(0).child(0).attr("src");
//System.out.println(imgurl);
downloadimg(imgurl);
try {
captcha_str = getAllOcr("/data/sata/share_sata/AmazonCrawl/amazonWeb/captcha.jpg");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return captcha_str;
}
}

后记:复杂验证码识别

对于复杂的验证码识别:目前的最简单的方案就是交给第三方人工打码平台:可以参考我做的EBay多线程打码兔验证码解决方案:

http://www.cnblogs.com/zeze/p/6402963.html

更专业的可以采用机器学习、模式识别等方法去实现,但是识别成功率,我目前测试的结果不是很理想,复杂的验证码,正确率在百分之二三十上下,但是我的训练样本库不是很大,提高训练的样本可能结果会好一点。

Java验证码识别解决方案的更多相关文章

  1. Java 验证码识别库 Tess4j 学习

    Java 验证码识别库 Tess4j 学习 [在用java的Jsoup做爬虫爬取数据时遇到了验证码识别的问题(基于maven),找了网上挺多的资料,发现Tess4j可以自动识别验证码,在这里简单记录下 ...

  2. python之web自动化验证码识别解决方案

    验证码识别解决方案 对于web应用程序来讲,处于安全性考虑,在登录的时候,都会设置验证码,验证码的类型种类繁多,有图片中辨别数字字母的,有点击图片中指定的文字的,也有算术计算结果的,再复杂一点就是滑动 ...

  3. 【Java】验证码识别解决方案

    对于类似以下简单的验证码的识别方案: 1. 2 3 4. 1.建库:切割验证码为单个字符,人工标记,比如:A. 2.识别:给一个验证码:切割为单个字符,在库中查询识别. /*** * author:c ...

  4. Java 验证码识别之多线程打码兔

    验证码识别,爬虫永远的话题~ 用打码兔总体的体验就是单线程速度太慢~ import java.io.IOException; import java.net.MalformedURLException ...

  5. JAVA验证码识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本

    JAVA验证识别:基于jTessBoxEditorFX和Tesseract-OCR训练样本 工具准备: jTessBoxEditorFX下载:https://github.com/nguyenq/jT ...

  6. java验证码识别

    首先参考了csdn大佬的文章,但是写的不全ImgUtils类没有给出代码,无法进行了 写不完整就是制造垃圾 不过这个大佬又说这个大佬的文章值得参考于是又查看这篇文章 有案例https://blog.c ...

  7. atitit.验证码识别step3----去除边框---- 图像处理类库 attilax总结java版本

    atitit.验证码识别step3----去除边框---- 图像处理类库 attilax总结java版本 1. 去除边框思路原理 1 2. Thumbnailator 是一个用来生成图像缩略图.裁切. ...

  8. Python&selenium&tesseract自动化测试随机码、验证码(Captcha)的OCR识别解决方案参考

    在自动化测试或者安全渗透测试中,Captcha验证码的问题经常困扰我们,还好现在OCR和AI逐渐发展起来,在这块解决上越来越支撑到位. 我推荐的几种方式,一种是对于简单的验证码,用开源的一些OCR图片 ...

  9. atitit  验证码理论与概览与 验证码规范 解决方案.docx

    atitit  验证码理论与概览与 验证码规范 解决方案.docx 1.1. 验证码的前世今生1 1.2. 第三代:无知识型验证码1 1.3. 短信验证码1 1.4. 语言验证码1 1.5. 图片验证 ...

随机推荐

  1. Python基本运算符

    Python基本运算符 什么是操作符? 简单的回答可以使用表达式4 + 5等于9,在这里4和5被称为操作数,+被称为操符. Python语言支持操作者有以下几种类型. 算术运算符 比较(即关系)运算符 ...

  2. Nvidia Nsight + .NET

    https://devtalk.nvidia.com/default/topic/804306/nsight-4-5-can-t-debug-net-applications/ http://comm ...

  3. MacPorts安装32位动态库

    http://superuser.com/questions/63198/install-32-bits-ports-on-snow-leopard

  4. CentOS6.x安装配置nginx

    nginx安装 nginx的官网:http://nginx.org/   相应下载页面:http://nginx.org/en/download.html   我这里使用nginx的yum在线安装 w ...

  5. linux 下 zip unzip压缩与解压

    注:*压缩成限.zip格式文件 常用解压缩: [root@mysql test]# unzip -o test.zip -d tmp/ 将压缩文件test.zip在指定目录tmp下解压缩,如果已有相同 ...

  6. for while (list each)的用法

    each是返回数组 指针当前指向的 元素的 索引和值: 索引有四个值: 0, 1, key, value. 0和key是一样的, 1和value是一样的 但是each只是将数组指针 向前移动 一步, ...

  7. 关于shell脚本时遇value too great for base (error token is "08")

    今天在书写一个定时cp脚本时遇到了一个问题,value too great for base (error token is "08") 在网上查看到原来是以0开头的数字 系统会默 ...

  8. php5调用web service

    工作中需要用php调用web service接口,对php不熟,上网搜搜,发现关于用php调用web service的文章也不多,不少还是php4里用nusoap这个模块调用的方法,其实php5里已经 ...

  9. CSS-animations和transitions性能:浏览器到底做了什么?

    CSS animations 和 transitions 的性能:浏览器到底做了什么?(译) 原文地址:http://blogs.adobe.com/webplatform/2014/03/18/cs ...

  10. 开始使用pycharm了

    我将python的主力开发工具从eclipse+pydev切换到pycharm社区版了. 选择pycharm 的原因:1. pycharm可以实时按照pep8的规范检查code style和namin ...