本帖最后由 zhiwoda 于 2022-3-5 23:17 编辑
原理:先把两张图片下载下来,然后用opencv灰度化,计算滑块位置,然后以非匀速拖过去,录了一个GIF可以看下效果
[Java] 纯文本查看 复制代码 public static boolean handleVerifyCode(WebDriver driver, int nSort) {
boolean bfinal = false;
try {
TXT.System_out_println("Hello,handleVerifyCode...");
if (!DATA_HTML_HASHMAP.containsKey("验证码背景图Tag") || !DATA_HTML_HASHMAP.containsKey("验证码滑块Tag")
|| !DATA_HTML_HASHMAP.containsKey("验证码拖动滑块Tag") || !DATA_HTML_HASHMAP.containsKey("验证码图片资源路径Txt")) {
TXT.System_out_println("获取验证码Tag失败,未设置...throw new Exception()");
throw new Exception();
}
String sBgName = DATA_HTML_HASHMAP.get("验证码背景图Tag");
String sBlockName = DATA_HTML_HASHMAP.get("验证码滑块Tag");
String sDragName = DATA_HTML_HASHMAP.get("验证码拖动滑块Tag");
// 创建文件夹
String sVerifyFile = DATA_HTML_HASHMAP.get("验证码图片资源路径Txt") + nSort;
File fileVerify = new File(sVerifyFile);
if (!fileVerify.exists()) {
fileVerify.mkdirs();
}
// 存储验证码图片的顺序名称
int nCurSort = 0;
if (DATA_VERIFY_HASHMAP.containsKey(nSort)) {
nCurSort = DATA_VERIFY_HASHMAP.get(nSort);
}
// OpenCV对象
Mat matSlideBlock = null; // 滑块对象
Mat matSlideBg = null; // 背景图对象
Mat matResult = null; // 叠加对象
List<Integer> moveTrack = null; // 移动轨迹
Actions actions = null; // 拖拽对象
int x = 0; // 计算后的滑块横坐标
int y = 0; // 计算后的滑块纵坐标
int tma = 0;
int tmb = 0;
if (!DATA_HTML_HASHMAP.containsKey("验证码验证过于频繁Txt") || !DATA_HTML_HASHMAP.containsKey("验证码验证服务异常Txt")
|| !DATA_HTML_HASHMAP.containsKey("验证码验证验证通过Txt")
|| !DATA_HTML_HASHMAP.containsKey("验证码验证验证后继续Txt")) {
TXT.System_out_println("验证码匹配配置不正确...throw new Exception()");
throw new Exception();
}
String strPage = "";
String str1 = DATA_HTML_HASHMAP.get("验证码验证过于频繁Txt");
String str2 = DATA_HTML_HASHMAP.get("验证码验证服务异常Txt");
String str3 = DATA_HTML_HASHMAP.get("验证码验证验证通过Txt");
String str4 = DATA_HTML_HASHMAP.get("验证码验证验证后继续Txt");
tma = 0;
while (true) {
if (tma > WHILE_LOOP_TOP) {
TXT.System_out_println("处理滑块验证码失败nSort = " + nSort + "...throw new Exception()");
throw new Exception();
}
strPage = driver.getPageSource();
// 页面超时,子页面刷新浏览器
if ((strPage.contains(str1) || strPage.contains(str2)) && nSort > 0) {
driver.navigate().refresh(); // 刷新子页面
Thread.sleep(500);
}
// 页面超时,主页面刷新浏览器
if (strPage.contains(str2) && nSort == 0) {
refreshMainPage(driver); // 主页面点击刷新按钮
Thread.sleep(500);
}
// 判断是否绕过验证码
if (strPage.contains(str3) || !strPage.contains(str4)) {
break;
}
// 下载图片
if (!downVerifyImg(driver, sBlockName, sBgName, nSort)) {
TXT.System_out_println("下载验证码图片失败...throw new Exception()");
throw new Exception();
}
// 给图片取名
nCurSort = 0;
if (DATA_VERIFY_HASHMAP.containsKey(nSort)) {
nCurSort = DATA_VERIFY_HASHMAP.get(nSort);
}
TXT.System_out_println("OpenCV read1");
TXT.System_out_println(sVerifyFile + "/Block" + nSort + "_" + nCurSort + ".jpg");
// 对滑块进行处理
matSlideBlock = Imgcodecs.imread(sVerifyFile + "/Block" + nSort + "_" + nCurSort + ".jpg");
// 灰度化图片
TXT.System_out_println("OpenCV read1.1");
Imgproc.cvtColor(matSlideBlock, matSlideBlock, Imgproc.COLOR_BGR2GRAY);
// 去除周围黑边
for (int row = 0; row < matSlideBlock.height(); row++) {
for (int col = 0; col < matSlideBlock.width(); col++) {
if (matSlideBlock.get(row, col)[0] == 0) {
matSlideBlock.put(row, col, 96);
}
}
}
// 二值化转黑白图
TXT.System_out_println("OpenCV read1.2");
Core.inRange(matSlideBlock, Scalar.all(96), Scalar.all(96), matSlideBlock);
TXT.System_out_println("OpenCV read2");
// 对背景图进行处理
matSlideBg = Imgcodecs.imread(sVerifyFile + "/Bg" + nSort + "_" + nCurSort + ".jpg");
// 灰度化图片
Imgproc.cvtColor(matSlideBg, matSlideBg, Imgproc.COLOR_BGR2GRAY);
// 二值化
Imgproc.threshold(matSlideBg, matSlideBg, 127, 255, Imgproc.THRESH_BINARY);
TXT.System_out_println("OpenCV read3");
// 保存处理后的图片
Imgcodecs.imwrite(sVerifyFile + "/Copy_Block" + nSort + "_" + nCurSort + ".jpg", matSlideBlock);
Imgcodecs.imwrite(sVerifyFile + "/Copy_Bg" + nSort + "_" + nCurSort + ".jpg", matSlideBg);
TXT.System_out_println("OpenCV read4");
// 计算位置
matResult = new Mat();
Imgproc.matchTemplate(matSlideBg, matSlideBlock, matResult, Imgproc.TM_CCOEFF_NORMED);
Point matchLocat = Core.minMaxLoc(matResult).maxLoc;
x = new Double(matchLocat.x).intValue();
y = new Double(matchLocat.y).intValue();
if (!DATA_VERIFY_ZOOM_HASHMAP.containsKey(nSort)) {
TXT.System_out_println("没有存储缩放比例...throw new Exception()");
throw new Exception();
}
x *= DATA_VERIFY_ZOOM_HASHMAP.get(nSort);
y *= DATA_VERIFY_ZOOM_HASHMAP.get(nSort);
// 拖动验证码准备验证
List<WebElement> dragElements = driver.findElements(By.className(sDragName));
actions = new Actions(driver);
tmb = 0;
while (dragElements.size() == 0) {
if (tmb > WHILE_LOOP_NORMAL) {
TXT.System_out_println("拖动控件元素未找到...throw new Exception()");
throw new Exception();
}
Thread.sleep(100);
dragElements = driver.findElements(By.className(sDragName));
tmb++;
}
// 开始滑动
moveTrack = getMoveTrack(x);
actions.clickAndHold(dragElements.get(0)).perform();
for (Integer index : moveTrack) {
actions.moveByOffset(index, 0).perform();
}
actions.release().perform();
Thread.sleep(500);
tma++;
}
bfinal = true;
} catch (Exception e) {
bfinal = false;
} finally {
if (!bfinal) {
TXT.System_out_println("handleVerifyCode...finally...bfinal = " + bfinal);
}
return bfinal;
}
}
[Java] 纯文本查看 复制代码 /*
* Function(8) getMoveTrack(int)
*
* 描绘滑动轨迹
*/
public static List<Integer> getMoveTrack(int dist) {
List<Integer> track = new ArrayList();
try {
Random rand = new Random();
int cur = 0; // 已经移动的距离
int r = 0; // 随机数
int move = 0; // 每次移动的距离
String str = "";
while (true) {
r = rand.nextInt(20);
move += r;
if (r > 18) {
move = -move / 2;
}
if ((cur + move) < dist) {
track.add(move);
} else {
track.add(dist - cur);
str += dist - cur;
break;
}
cur += move;
str += move + ",";
}
TXT.System_out_println("计算滑动轨迹完毕,str = " + str + "...throw new Exception()");
} catch (Exception e) {
} finally {
return track;
}
} |