使用Selenium獲取銀行賬戶餘額

銀行卡很多,每次查看餘額多要進入每個銀行網站進行查看,於是就想到如何通過程序自動獲取,網上查了些資料,一般用selenium做自動化測試,然後就學了下selenium,寫了建行、招行、平安、陸金所,不過招行網站已不允許查,只能在手機進行賬單查詢。

環境:Jdk1.8、selenium3.14、Hibernate3、Spring2

邏輯:

使用selenium最重要的一點就是要找到獲取信息元素的路徑,邏輯比較簡單,先使用WebDriver調用firefox(這裏使用ff驅動geckodriver,也可以使用其他瀏覽器的驅動)打開登錄界面,自動輸入用戶名、密碼,獲取登錄,然後跳轉到要獲取的信息界面,按元素路徑獲取數據,再進行處理入庫。

登錄一般會碰到驗證碼的問題,目前也沒找到較好的識別手段,就用等待的方式人工輸入,有些網站是可以通過瀏覽器緩存的方式,在第一次登錄正確後,後續登錄就不需要再輸入驗證碼了,如陸金所,這種方式可以先設置FirefoxProfile,在Mac下可以在終端窗口輸入:/Applications/Firefox.app/Contents/MacOS/firefox-bin -ProfileManager,調出firefox配置界面,這裏新建了一個”banks”配置,然後點“啓動Firefox”,打開界面後,正確登錄陸金所,在程序調用的時候使用該配置,就不用輸驗證碼了。包括第一次登錄時會出現的一些幫助界面,也可以通過這種方式避免。

建行的登錄現在會發驗證碼到手機,這種情況就只能在該界面等待用戶輸入後再進行後續操作了。

接下來就是你找元素路徑然後對數據進行處理了,以下爲建行代碼:

package cn.com.selen.bank;

import java.util.List;

import org.openqa.selenium.Alert;

import org.openqa.selenium.By;

import org.openqa.selenium.JavascriptExecutor;

import org.openqa.selenium.NoAlertPresentException;

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.support.ui.ExpectedCondition;

import org.openqa.selenium.support.ui.WebDriverWait;

import cn.com.selen.domain.Accountinfo;

import cn.com.selen.util.ThreadUtil;

 

public class Ccb extends BankingBase {

public Ccb(){

BANK_NAME = "ccb";

LOGIN_URL = "https://ibsbjstar.ccb.com.cn/CCBIS/V6/common/login.jsp";

ACCOUNT_URL = "https://ibsbjstar.ccb.com.cn/CCBIS/B2CMainPlat_05?SERVLET_NAME=B2CMainPlat_05&CCB_IBSVersion=V6&PT_STYLE=1";

}

 

@Override

protected void login(String userName, String pwd) {

//CCB的cookie好像沒用,每次就直接登錄

try {

WebElement fclogin = driver.findElement(By.id("fQRLGIN"));

fclogin.click();

driver.switchTo().frame(fclogin);

driver.findElement(By.id("USERID")).click();

driver.findElement(By.id("USERID")).sendKeys("");  //用戶名

driver.findElement(By.id("LOGPASS")).click();

driver.findElement(By.id("LOGPASS")).sendKeys(""); //密碼

Thread.sleep(5000);

 

driver.findElement(By.id("loginButton")).click();

(new WebDriverWait(driver, 10)).until(new ExpectedCondition<Boolean>() {

public Boolean apply(WebDriver d){

return !d.getCurrentUrl().equals(LOGIN_URL);

}

});

ThreadUtil.sleep(1000);  //接收短信界面

try {

Alert alert = driver.switchTo().alert(); 

String alertText = alert.getText(); 

System.out.println("彈出數據:"alertText); 

alert.accept();

catch(NoAlertPresentException e1){

e1.printStackTrace(); 

}

catch (InterruptedException e) {

e.printStackTrace();

}

driver.switchTo().defaultContent();

 

}

public void updateCash(int id){

//如果有介紹界面,先關閉

if(cookiesUtil.isElementPresent(driver,By.id("show1"))){

WebElement show1 = driver.findElement(By.id("show1"));

if(show1.isDisplayed() && cookiesUtil.isElementPresent(driver,By.id("Map1"))){//顯示界面,且找到關閉按鈕

JavascriptExecutor jse = (JavascriptExecutor)driver;

//jse.executeScript("closeMengBan()");

WebElement eMap = driver.findElement(By.xpath("//*[@id=\"Map1\"]/area[1]"));

jse.executeScript("arguments[0].click()"eMap); 

}

}

 

ThreadUtil.sleep(1000);

driver.switchTo().defaultContent();

while(!this.cookiesUtil.isElementPresent(driver, By.xpath("//*[@id=\"per1\"]/a"))) {

ThreadUtil.sleep(5000);

}

ThreadUtil.sleep(5000);//5s時間點掉彈出界面

//點查詢,進入查詢界面

WebElement f = driver.findElement(By.xpath("//*[@id=\"per1\"]/a/i"));

f.click(); 

ThreadUtil.sleep(5000);

driver.switchTo().frame("txmainfrm");

driver.switchTo().frame("result");

List<WebElement> cards;

do {

ThreadUtil.sleep(1000);

cards = driver.findElements(By.xpath("//*[@id=\"scrollPic\"]/ul/li"));

}while(cards.size()<1);

for(int i=0;i<cards.size()-1;i++){//最後一個是隱藏的,不需要處理

WebElement card = cards.get(i);

card.click(); 

ThreadUtil.sleep(8000);

String cardInfo = card.getAttribute("values");

String[] cardInfos = cardInfo.split("\\|"); //格式:卡號|330000000|xyk|多幣種|馬**||浙江省|30||身份證號

driver.switchTo().frame("result"); //切換到取數區

WebElement money = null;//找到結果顯示的Table

if(cardInfos[2].equals("xyk")){//信用卡

money = driver.findElement(By.xpath("//*[@class=\"one_lines_table\"]/tbody/tr[1]/td[5]/span"));

}else if(cardInfos[2].equals("dkzh")){//貸款卡

money = driver.findElement(By.xpath("//*[@class=\"one_lines_table\"]/tbody/tr[2]/td[4]/span"));

}else{//儲蓄卡及其他

if(cardInfos[4] == null || cardInfos[4].length()==0){//自己的賬號會顯示多幣種

money = driver.findElement(By.xpath("//*[@class=\"one_lines_table\"]/tbody/tr[3]/td[5]/span"));

}else{

money = driver.findElement(By.xpath("//*[@class=\"one_lines_table\"]/tbody/tr/td[5]/span"));

}

String strMoney = money.getAttribute("innerHTML");

int ind = strMoney.indexOf("</script>");

if(ind>0){

strMoney = strMoney.substring(ind+9);

}

strMoney = strMoney.replace(",""");

double dblMoney = Double.parseDouble(strMoney); 

Accountinfo act = bank.findByCode(cardInfos[0]);//從數據庫裏查找賬號信息

if(act.getType() ==2 || act.getType() == 5)dblMoney=-dblMoney;

System.out.println(cardInfos[0] +":"+dblMoney);

bank.saveCost(act.getId(), dblMoney);

driver.switchTo().parentFrame();

if((i+1)%4 == 0 ){

driver.findElement(By.id("RightArr")).click();

ThreadUtil.sleep(3000);

}

}

sumCost(1);  //這裏1爲父賬號ID,這裏表示建行的,自己設定的

}

}

 

代碼是幾年前寫的,有些結構可能設計不大合理,Seleium總體來說並不複雜,主要還是要看你爬取信息的邏輯,以及路徑,然後處理好容錯,難點在驗證碼及第三方插件的操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章