问题和思路
滑动拼图验证码
如何使用自动化手段模拟人为操作完成该验证码的验证流程?
思路:计算拼图与缺口之间的距离,通过控制拖动的方式,将拼图拖动至缺口位置,确保误差越小越好。
尝试解决
- 首先需要计算距离,可以采用opencv对图像进行处理,其中最主要的是利用
matchTemplate
函数计算出,拼图与缺口之间的位置,从而获得距离。
Mat slideBlockMat = Imgcodecs.imread(touchFile.getAbsolutePath(), 0); Size size = new Size(3, 3); Imgproc.GaussianBlur(slideBlockMat, slideBlockMat, size, 0); Imgproc.Canny(slideBlockMat, slideBlockMat, 50, 150);
Mat bgBlockMat = Imgcodecs.imread(bgFile.getAbsolutePath(), 0); Imgproc.GaussianBlur(bgBlockMat, bgBlockMat, size, 0); Imgproc.Canny(bgBlockMat, bgBlockMat, 50, 150);
Mat resultMat = new Mat(); Imgproc.matchTemplate(slideBlockMat, bgBlockMat, resultMat, Imgproc.TM_CCOEFF_NORMED); org.opencv.core.Point matchLocation = Core.minMaxLoc(resultMat).maxLoc;
double distance = matchLocation.x;
|
- 得到距离之后,需要通过模拟人为拖动的行为方式,将拼图拖动至缺口处。
Dimension touchEleSize = touchEle.getSize();
distance = distance + (int) (touchEleSize.getWidth() / 4.0) - 5;
List<Double> tracks = new ArrayList<>(); List<Double> offsets = new ArrayList<>(); offsets.add(0d);
double second = (int) (distance / 100) + 1.0;
for (double i = 0d; i < second; i += 0.1) { double offset = Math.round((1 - Math.pow(1 - (i / second), 4)) * distance); tracks.add(offset - offsets.get(offsets.size() - 1)); offsets.add(offset); }
fullscreen(); touchEle = webDriver.findElement(touchBy); Rectangle rect = touchEle.getRect();
AutoItX autoItX = new AutoItX(); autoItX.sleep(3000); autoItX.mouseMove(rect.getX() + touchEleSize.getWidth() / 2, rect.getY() + touchEleSize.getHeight() / 2); autoItX.mouseDown("left"); tracks.forEach(move -> { autoItX.mouseMove(autoItX.mouseGetPosX() + move.intValue(), autoItX.mouseGetPosY(), 5); autoItX.sleep(10); }); autoItX.sleep(1500); autoItX.mouseUp("left"); exitFullscreen();
|
实际效果