自动滑块验证登录QQ-java实现

之前,我用php配合java写了一个qq群签到的脚本。需要手动更新cookie,很烦。

最近学习刷题过程中,碰到了很多事情,很烦。就准备写几天代码,把之前的脚本,完整的只用java来实现,顺便平复一下最近烦躁的情绪。

登录QQ之后,能干的事情很多。这里只讲述如何自动登录,至于自动登录之后干啥,根据自己需求自由发挥。

授人以鱼不如授人以渔,我把思路分享出来。

原博客地址

一、登录

下载selenium相应的jar包。加载ChromeDriver驱动,下载地址

加载驱动之后,就可以考虑开始登录了。

  1. 切换账号密码登录
  2. 输入账号
  3. 输入密码
  4. 登录

注意,这期间是需要有时间间隔的,因为可能会有网速的影响,所以我在切换账号密码登录登录这两步中,分别设定了间隔1秒和5秒。

如果页面还没加载完成,就开始执行程序,那会报错。因为没有找到指定的元素。

二、自动解锁滑块验证码

也可以到这里进行滑块测试,代码需要进行修改

本来是想通过识别图像像素或者对比度的方法,来找出滑块缺失的位置。后来发现,腾讯并没有做得那么牛逼。

经过多次测试,发现,QQ的滑块验证,并不是随机产生的,而是固定的。不管怎么弄,都会有三个固定位置。190px,205px,215px.

换句话说,我们顶多进行三次登录,肯定是能登录成功的。

放上完整代码

public class AutoLogin {
	private static ChromeDriver driver;
	private static String oldUrl;
	private static String newUrl;

	/**
	 * 获取驱动
	 */
	public static void getDriver() {
		// 本地测试
//		System.setProperty("webdriver.chrome.driver", "C:\\Users\\kitchen\\Desktop\\chromedriver.exe");
		// 打包
		System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
		// 下面两行代码关闭无用的log
		System.setProperty("webdriver.chrome.silentOutput", "true");
		java.util.logging.Logger.getLogger("org.openqa.selenium").setLevel(Level.OFF);
		ChromeOptions chromeOptions = new ChromeOptions();
		// 这是指不打开GUI模式
		chromeOptions.addArguments("--headless");
		driver = new ChromeDriver(chromeOptions);
	}

	/**
	 * 获取登录的skey
	 * @param u
	 * @param p
	 * @return
	 */
	public static String getSkey(String u, String p) {
		String skey = null;
		if (login(u, p)) {
			skey = driver.manage().getCookieNamed("skey").toString().split(";")[0].substring(5);
		} else {
			System.out.println("本次自动登录失败,邮件通知管理员");
			String[] mail = { "QQ自动登录异常", "本次登录失败,请检测程序" };
			SendMail.send(mail);
			System.exit(0);
		}
		driver.quit();
		return skey;
	}

	/**
	 * 登录
	 * 
	 * @param u
	 * @param p
	 * @return true表示登录成功
	 */
	public static boolean login(String u, String p) {
		System.out.println("时间到,开始登录...");
		getDriver();
		boolean flag = false;
		driver.get(
				"https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone%26specifyurl%3Dhttp%253A%252F%252Fuser.qzone.qq.com%252F5201314&pt_qr_app=%E6%89%8B%E6%9C%BAQQ%E7%A9%BA%E9%97%B4&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=1");
		try {
			Thread.sleep(1000);
			// 切换登录模式
			driver.findElement(By.id("switcher_plogin")).click();
			Thread.sleep(500);
			// 输入账号以及密码进行登录
			driver.findElement(By.id("u")).clear();
			driver.findElement(By.id("u")).sendKeys(u);
			driver.findElement(By.id("p")).clear();
			driver.findElement(By.id("p")).sendKeys(p);
			driver.findElement(By.id("login_button")).click();

			Thread.sleep(5000);
            
            //轨迹
			int[][] arr = { { 10, 20, 30, 40, 50, 18 }, { 10, 20, 30, 40, 50, 18, 30 }, { 10, 20, 30, 40, 50, 18, 15 },

			};
			oldUrl = driver.getCurrentUrl();
			for (int i = 0; i < arr.length; i++) {
				System.out.print("正在尝试第" + (i + 1) + "次登录:");
				if (unlock(arr[i])) {
					System.out.println("登录成功");
					flag = true;
					break;
				} else {
					System.out.println("登录失败");
					flag = false;
				}
				Thread.sleep(2000);
			}
		} catch (InterruptedException e) {
			System.out.println("登录失败");
			driver.quit();
		}
		return flag;

	}

	/**
	 * 自动进行滑块解锁
	 * 
	 * @return true表示解锁成功
	 */
	public static boolean unlock(int[] arr) {
		boolean flag = false;
		Actions actions = new Actions(driver);
		try {
            //qq里面嵌套了iframe,需要将驱动转到iframe内部,才可以选择元素。
            //如果第一次登录错误,需要将驱动再跳回到当前内容
			driver.switchTo().frame("tcaptcha_iframe");
			WebElement slideBtn = driver.findElement(By.id("tcaptcha_drag_button"));
			// 按下滑动按钮
			actions.clickAndHold(slideBtn).perform();
			for (int i : arr) {
				actions.moveByOffset(i, 0).perform();
			}
			// 松开按钮
			actions.release(slideBtn).perform();
			Thread.sleep(3000);
			newUrl = driver.getCurrentUrl();
			if (oldUrl.equals(newUrl)) {
                //如果登录失败,需要让驱动重新跳回到原来的内容
				driver.switchTo().defaultContent();
				flag = false;
			} else {
				flag = true;
			}
			Thread.sleep(500);
		} catch (InterruptedException e) {
			System.out.println("登录失败");
			driver.quit();
		}
		return flag;
	}
}
posted @ 2020-05-29 08:03  言成言成啊  阅读(1578)  评论(4编辑  收藏  举报