前言
引入OpenCV库,下载地址:Releases - OpenCV下载4.5.0即可,在下完成安装exe文件后,会出现下列文件,直接将build/java文件下的jar包导入项目的依赖即可。
一、滑块验证解析?
1.获取驱动,加载126网址
2.切换窗口,因为登录功能是在iframe中,需要先切换窗口
3.输入账号和密码,点击登录(才能弹出滑块提示)
4.下载滑块和背景图
5.用OpenCV技术,处理图片,计算出横向距离(需要计算出原图和显示图的缩放比例才能算出需要滑动的正确距离)
6.用actions模拟鼠标进行滑动
二、解决步骤
1.主流程如下
代码如下(示例):
public static void main(String[] args) throws InterruptedException {
//1.获取驱动,加载网址
ChromeDriver driver = new ChromeDriver();
//driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
driver.manage().window().maximize(); //全屏
driver.get("https://www.126.com");
//2.切换窗口,定位元素
WebElement iframeElement = driver.findElement(By.xpath("//div[@id='loginDiv']/iframe"));
WebDriver loginFrame = driver.switchTo().frame(iframeElement);
//3.输入账号密码
clickLogin(loginFrame);
boolean displayed;
boolean error;
do {
//4下载图片
List<String> photos = downloadPhoto(loginFrame);
//5.解析图片,计算距离
double slideDistance = countDistance(loginFrame,photos);
//6.模拟滑块真实滑动到指定位置
slideVerify(driver, slideDistance);
Thread.sleep(1000);
//判断滑动提示是否存在
displayed= driver.findElement(By.className("yidun_bg-img")).isDisplayed();
//判断是否提示滑动次数过多,需要重新点击
error=driver.findElement(By.className("yidun_tips__icon")).isDisplayed();
if(error){
driver.findElement(By.className("yidun_tips")).click();
Thread.sleep(3000);
}
}while(displayed);
//点击登录
driver.findElement(By.id("dologin")).click();
}
2.输入账号密码方法
代码如下(示例):
private static void clickLogin(WebDriver e) {
e.findElement(By.name("email")).clear();
e.findElement(By.name("email")).sendKeys("username");
e.findElement(By.name("password")).clear();
e.findElement(By.name("password")).sendKeys("password");
e.findElement(By.id("un-login")).click();
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
e.findElement(By.id("dologin")).click();
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
3.下载图片方法
代码如下(示例):
private static List<String> downloadPhoto(WebDriver driver){
String chock_src = driver.findElement(By.className("yidun_jigsaw")).getAttribute("src");
String bg_src = driver.findElement(By.className("yidun_bg-img")).getAttribute("src");
String chockPhoto = download(chock_src, "chock");
String bgPhoto = download(bg_src, "bg_src");
ArrayList<String> list = new ArrayList<>();
list.add(chockPhoto);
list.add(bgPhoto);
return list;
}
//下载图片的方法
private static String download(String urlStr, String name) {
InputStream is = null;
FileOutputStream fos = null;
String fileName = "D:\\java\\JavaProject\\Selenium\\src\\main\\java\\qwc\\selenium\\apidemo\\phono\\" + name + ".png";
try {
URL url = new URL(urlStr);
URLConnection con = url.openConnection();
is = con.getInputStream();
byte[] bytes = new byte[1024];
int len;
fos = new FileOutputStream(fileName);
//读取数据
while ((len = is.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return fileName;
}
4.解析图片,计算距离
代码如下(示例):
private static double countDistance(WebDriver driver,List<String> photos) {
//加载本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
//对拼图图形进行处理,将滑块图片存储为Mat类型
Mat slideBlockMat = Imgcodecs.imread(photos.get(0));
//1.灰度化图片
Imgproc.cvtColor(slideBlockMat, slideBlockMat, Imgproc.COLOR_BGR2GRAY);
//2.去除周围黑边
for (int row = 0; row < slideBlockMat.height(); row++) {
for (int col = 0; col < slideBlockMat.width(); col++) {
if (slideBlockMat.get(row, col)[0] == 0) {
slideBlockMat.put(row, col, 96);
}
}
}
//3.转为黑白图
Core.inRange(slideBlockMat, Scalar.all(96), Scalar.all(96), slideBlockMat);
//对滑动背景图进行处理
Mat slideBgMat = Imgcodecs.imread(photos.get(1));
//灰度化图片
Imgproc.cvtColor(slideBgMat, slideBgMat, Imgproc.COLOR_BGR2GRAY);
//二值化(转黑白图)
//Core.inRange(slideBgMat, Scalar.all(96), Scalar.all(96), slideBgMat);
Imgproc.threshold(slideBgMat,slideBgMat,127,255, Imgproc.THRESH_BINARY);
Mat g_result = new Mat();
/*
* 将凹槽背景和拼图进行匹配
*/
Imgproc.matchTemplate(slideBgMat, slideBlockMat, g_result, Imgproc.TM_CCOEFF_NORMED);
Point matchLocation = Core.minMaxLoc(g_result).maxLoc;
//返回匹配点的横向举例
System.out.println(matchLocation.x*34/48);
return matchLocation.x*34/48;
}
5.模拟滑块真实滑动
代码如下(示例):
private static void slideVerify(WebDriver driver, double distance) {
//定位到滑块元素
WebElement chockElement = driver.findElement(By.className("yidun_slider"));
Actions actions = new Actions(driver);
actions.clickAndHold(chockElement); //模拟鼠标动作,悬停在滑块上
try {
Thread.sleep(500);
actions.moveByOffset(((int) distance) / 2+12, 0);
Thread.sleep(900);
actions.moveByOffset(((int) distance) / 2, 0);
Thread.sleep(600);
actions.release();
actions.perform();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
总结
版权归原作者 橙子味的冰淇淋 所有, 如有侵权,请联系我们删除。