Bootstrap

【巧用ddddocr破解算术运算验证码的经典示范】

在这里插入图片描述

计算型验证码

算术验证码,也叫计算型验证码, 计算型验证码其实是一种特殊的字符型验证码,只不过在它的基础上增加了数字运算。
  计算型验证码在将人类视觉和计算机视觉的差异作为区分用户和电脑的依据的同时,还加上了逻辑运算,从而来增加机器识别的难度。
    Python 提供了专门的库用于破解计算性验证码——Ddddocr

破解方式

Ddddocr 其实是一种 OCR,可以将图形识别后得到字符串,字符串中带有运算符

第一步:安装​

pip install ddddocr

第二步:​从网站抓取图片,如下图类型

在这里插入图片描述

第三步:切割图片,将数字和运算符的位置分别截取

分割图片并调用 ddddOcr 解析相应的字符串

// 2 获取图形验证码
			Thread.sleep(1 * 1000);
			String imgCode = null, base64Str;
			byte[] imgByte = null;
			BufferedImage fullBI;
			String logic = "";
			WebElement imgElement = driver.findElement(By.className("pic-check"));
			boolean isPlus = false;
			byte[] logicByte = null, n1Byte, n2Byte;
			long t = System.currentTimeMillis();
			for (int i = 0; i < 6; i++) {
				t = System.currentTimeMillis();
				base64Str = imgElement.getAttribute("src");
				imgByte = (base64Str != null) ? GetImage.imgStrToByte(base64Str) : null;
				fullBI = ImageIO.read(new ByteArrayInputStream(imgByte));
				n1Byte = picCut(fullBI, 80, 22);
				n2Byte = picCut(fullBI, 138, 22);
				logicByte = picCut(fullBI, 99, 40);
				String n1 = DigitFormat.getDigit(ddddOcr.getImgCode(n1Byte));
				String n2 = DigitFormat.getDigit(ddddOcr.getImgCode(n2Byte));
				logic = ddddOcr.getImgCode(logicByte);
				isPlus = logic != null && (logic.contains("加") || logic.contains("如") || logicSet.contains(logic));
				if (logic != null && logic.length() > 0) {
					if (isPlus)
						imgCode = logic(n1, "plus", n2);
					else
						imgCode = logic(n1, logic, n2);
				} else {
					imgCode = null;
					ddddOcr.saveFile("Ddky/", "OP_" + t, logicByte);
				}
				System.out.println("n1=" + n1 + ",logic=" + logic + ",n2=" + n2);
				if (imgCode != null && imgCode.length() > 0)
					break;
				imgElement.click();
				Thread.sleep(1 * 1000);
			}

在这里插入图片描述
在这里插入图片描述

由于 ddddOcr 对识别出的加减汉字存在识别为其它字符串的概率,故采用两中方式可以纠正,
1 在初期可以对识别出的字符串进行纠正,优点是无需训练即可达到 95%的识别率,缺点是需要增加纠正字典表
2 在1的基础上, 对汉字运算符号进行训练, 训练可以去掉纠正表

public static final Set<String> logicSet = new HashSet<String>() {
		private static final long serialVersionUID = -4054136023490781886L;
		{
			add("b");
			add("d");
			add("g");
			add("m");
			add("M");
			add("u");
			add("风");
			add("挪");
			add("如");
			add("帆");
			add("挑");
			add("加");
			add("业");
			add("邮");
			add("此");
			add("爪");
			add("却");
			add("加m");
			add("规");
			add("耻");
			add("州");
			add("期");
			add("机");
			add("址");
			add("抓");
			add("抑");
			add("邯");
			add("虾");
			add("川");
			add("划");
			add("娜");
		}
	};

第四步:​编写程序,对识别得到的字符串进行运算

算术运算部分

/**
	 * 算术运算
	 * @param n1
	 * @param logic
	 * @param n2
	 * @return
	 */
	private String logic(String n1, String logic, String n2) {
		if (n1 != null && n1.length() > 0 && n2 != null && n2.length() > 0) {
			Integer r;
			if (logic.equals("plus")) {
				r = Integer.parseInt(n1) + Integer.parseInt(n2);
			} else {
				r = Integer.parseInt(n1) - Integer.parseInt(n2);
			}
			return String.valueOf(r);
		}
		return null;
	}

测试结果,

在没有训练的基础上,对识别出的结果进行纠正,成功率可以达到 97% , 后期我们有空再进行训练后提供测试的情况

;