使用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总体来说并不复杂,主要还是要看你爬取信息的逻辑,以及路径,然后处理好容错,难点在验证码及第三方插件的操作。

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