Java Selenium简单浏览器模拟



Java Selenium简单浏览器模拟

模拟登陆QQ邮箱为例



Maven中pom.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.wu</groupId>
    <artifactId>Edge</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>
    </dependencies>
</project>

主要代码:

package com.wu;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;

import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;


public class Edge {
    public static void main(String[] args){
        boolean flag = true;

        System.setProperty("webdriver.edge.driver","E:driver\\msedgedriver.exe");
        WebDriver driver = new EdgeDriver();
        driver.get("https://mail.qq.com/");

        try{
            driver.switchTo().frame(driver.findElement(By.id("login_frame"))); // 切换到相应的frame标签下
            driver.findElement(By.id("switcher_plogin")).click();
        }catch(Exception e){
            // e.printStackTrace();
        }


        while(flag){
            try{
                WebElement input = driver.findElement(By.id("u"));
                input.sendKeys("这里是你的账号");
                WebElement password = driver.findElement(By.id("p"));
                password.sendKeys("这里是你的密码");
                driver.findElement(By.id("login_button")).click();

                driver.switchTo().defaultContent(); // 由于前面已经位于子frame中,故当前需要切换到顶级frame中
                Thread.sleep(500);
                driver.switchTo().frame(driver.findElement(By.id("login_frame"))); // 切换到一级frame
                driver.switchTo().frame(driver.findElement(By.id("tcaptcha_iframe"))); // 切换到二级frame
                driver.findElement(By.id("tcaptcha_drag_thumb")).click();
                mouseAction(840,570); // 滑动验证(不保证100%成功)
                driver.findElement(By.id("tcaptcha_drag_thumb")).click();
                flag = false;
            }catch(Exception e){
                e.printStackTrace();
            }
        }

    }

    /**
     * 鼠标移动事件
     * @param x 横坐标
     * @param y 总坐标
     * @throws AWTException,InterruptedException
     */
    private static void mouseAction(int x, int y) throws AWTException,InterruptedException{
        Robot robot = new Robot();
        robot.mouseMove(x,y); // 鼠标移动到当前位置
        /**
         以下仅供扩展学习
        **/
        // 简单模拟单击鼠标左右键
        robot.mouseMove(x+400,y+200);
        {
            robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); // 按住鼠标右键
            robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); // 释放鼠标右键
            robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); // 按住鼠标左键
            robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); // 释放鼠标左键
        }
        // 实现通过Utools打开百度首页
        {
            // 唤醒Utools
            robot.keyPress(KeyEvent.VK_ALT);
            robot.keyPress(KeyEvent.VK_SPACE);
            robot.keyRelease(KeyEvent.VK_SPACE);
            robot.keyRelease(KeyEvent.VK_ALT);
            // 拼音百度
            Thread.sleep(200);
            robot.keyPress(KeyEvent.VK_B);
            robot.keyRelease(KeyEvent.VK_B);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_A);
            robot.keyRelease(KeyEvent.VK_A);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_I);
            robot.keyRelease(KeyEvent.VK_I);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_D);
            robot.keyRelease(KeyEvent.VK_D);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_U);
            robot.keyRelease(KeyEvent.VK_U);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_1);
            robot.keyRelease(KeyEvent.VK_1);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_ENTER);
            robot.keyRelease(KeyEvent.VK_ENTER);
            Thread.sleep(100);
            robot.keyPress(KeyEvent.VK_ENTER);
            robot.keyRelease(KeyEvent.VK_ENTER);
        }
    }
}




改进策略后…


package com.wu;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.edge.EdgeDriver;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;


public class Edge {
    private static WebDriver driver = null;
    public static void main(String[] args){
        System.setProperty("webdriver.edge.driver","E:driver\\msedgedriver.exe");
        driver = new EdgeDriver();
        driver.get("https://mail.qq.com/");

        try{
            driver.switchTo().frame(driver.findElement(By.id("login_frame"))); // 切换到相应的frame标签下
            driver.findElement(By.id("switcher_plogin")).click();
        }catch(Exception e){
            // e.printStackTrace();
        }

        // 登录
        {
            WebElement input = driver.findElement(By.id("u"));
            input.sendKeys("你的账号");
            WebElement password = driver.findElement(By.id("p"));
            password.sendKeys("你的密码");
            driver.findElement(By.id("login_button")).click();
        }


        while(true){
            try{
                Thread.sleep(200);
                driver.switchTo().defaultContent(); // 由于前面已经位于子frame中,故当前需要切换到顶级frame中
                driver.switchTo().frame(driver.findElement(By.id("login_frame"))); // 切换到一级frame
                driver.switchTo().frame(driver.findElement(By.id("tcaptcha_iframe"))); // 切换到二级frame
                driver.findElement(By.id("tcaptcha_drag_thumb")).click();
                Thread.sleep(200);
                mouseAction();
                driver.findElement(By.id("tcaptcha_drag_thumb")).click();
                Thread.sleep(500);
                // 直到成功为止或者失败
                try{
                    WebElement reload = driver.findElement(By.id("e_reload"));
                    reload.click();
                }catch(Exception e){
                    break;
                }
            }catch(Exception e){
                // e.printStackTrace();
            }
        }


    }

    /**
     * 鼠标移动事件
     * @throws Exception
     */
    private static void mouseAction() throws Exception{
        Robot robot = new Robot();
        int x,y = 570;
        x = imgHandle();
        robot.mouseMove(x,y); // 鼠标移动到当前位置
        // System.out.println("横坐标为:"+x+",纵坐标为:"+y);
    }

    /**
     * 网络获取照片
     * @return 移动的横坐标
     * @throws Exception
     */
    private static int imgHandle() throws Exception{
        WebElement img = driver.findElement(By.id("slideBg"));
        URL url = new URL(img.getAttribute("src"));
        int result = 0;
        try{
            DataInputStream dataInputStream = new DataInputStream(url.openStream());

			/**
            DataInputStream tempInputStream = new DataInputStream(url.openStream());
            String image = "D:\\test.jpg";
            FileOutputStream fileOutputStream = new FileOutputStream(new File(image));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            // dataInputStream.read(byte[] a); 该方法返回写入字符数组返回buffer末端位置
            while((length = tempInputStream.read(buffer)) > 0){
                output.write(buffer,0,length);
            }
            byte[] context = output.toByteArray();
            // handleBytes(context);
            fileOutputStream.write(output.toByteArray()); // 将字节流写入.jpg文件中
            fileOutputStream.close();
            tempInputStream.close();
			**/

            result = bytesHandle(dataInputStream);
            dataInputStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 处理边界像素
     * @param inputStream
     * @return 移动的横坐标
     * @throws Exception
     */
    private static int bytesHandle(InputStream inputStream) throws Exception{

        BufferedImage bufferedImage = ImageIO.read(inputStream);
        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();
        int minx = bufferedImage.getMinX();
        int miny = bufferedImage.getMinY();
        int[][][] rgb = new int[width][height][3];
        int[] temp = new int[width+1]; // 用于计数同一横坐标的个数

        for(int i = minx;i < width ; i++){
            for(int j = miny ; j < height ; j++){
                int pixel = bufferedImage.getRGB(i, j); // 下面三行代码将一个数字转换为RGB数字
                rgb[i][j][0] = (pixel & 0xff0000) >> 16;
                rgb[i][j][1] = (pixel & 0xff00) >> 8;
                rgb[i][j][2] = (pixel & 0xff);
                // 查找右边界策略
                if((rgb[i][j][0] >= 250 &&  rgb[i][j][1] >= 250 && rgb[i][j][2] >= 224) ||
                   (rgb[i][j][0] >= 250 &&  rgb[i][j][2] >= 250 && rgb[i][j][1] >= 224) ||
                   (rgb[i][j][1] >= 250 &&  rgb[i][j][2] >= 250 && rgb[i][j][0] >= 224)
                ){
                    temp[i+1]++;
                }

            }
        }
        int rightMargin = temp[1];
        int result = 0;
        for(int i = 1 ; i < width ; i++){
            if(rightMargin < temp[i]){
                rightMargin = temp[i];
                result = i;
            }
        }

        // 最终计算需要移动横坐标所需要的像素
        System.out.println("照片坐标系右边界的横坐标为:"+result);

        return 680+result/(680/283)-75; // 需要找到固定的初始位置,即这里需要自定义微调
    }
}

简单分析一下,这里如果出现类似这种滑动验证码,由于边界大致是基于白色的,所以一般很难寻找到边界,因此程序会执行‘刷新’…

在这里插入图片描述

但是类似一下这种就一般可以直接命中…

在这里插入图片描述

总而言之,是否容易命中取决于概率加上边界寻找策略。读者可以自己尝试以及修改代码,来实现自己理想的效果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值