之前,我用php配合java寫了一個qq群簽到的腳本。需要手動更新cookie,很煩。
最近學習刷題過程中,碰到了很多事情,很煩。就准備寫幾天代碼,把之前的腳本,完整的只用java來實現,順便平復一下最近煩躁的情緒。
登錄QQ之后,能干的事情很多。這里只講述如何自動登錄,至於自動登錄之后干啥,根據自己需求自由發揮。
授人以魚不如授人以漁,我把思路分享出來。
一、登錄
下載selenium相應的jar包。加載ChromeDriver驅動,下載地址
加載驅動之后,就可以考慮開始登錄了。
- 切換賬號密碼登錄
- 輸入賬號
- 輸入密碼
- 登錄
注意,這期間是需要有時間間隔的,因為可能會有網速的影響,所以我在切換賬號密碼登錄和登錄這兩步中,分別設定了間隔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;
}
}