Java Selenium模擬某電商登錄獲取豆豆信息+JUnit單元測試

本來想用Python模擬請求,但是!!經過抓包分析,它的請求裏面有兩個參數eid和fp是用javaScript動態生成的。順藤摸瓜,找到javaScript代碼,結果!!我看不懂……不僅看不懂,人家是專門做了混淆的…算了,就醬吧,還是乖乖用Selenium操作。

JDLogin:

  1. 登錄(有人說登錄次數多了會彈驗證碼,不過我從logout頁面登錄進去,多次,也沒有彈驗證碼)
  2. 到達我的豆豆頁面
  3. 抓取豆豆信息(總數+近三個月的明細),抓明細的時候,頁面上有做分頁,老老實實挨個分頁button點過去
  4. 獲取到的明細信息處理:隱去商品號…

時間着實有限,所以只拿了自己的帳號(有多頁豆豆明細數據的)和一個空白帳號(豆豆數量爲0,沒有豆豆交易明細數據)做測試,結果都是通過的。如下所示:
這裏寫圖片描述
這裏寫圖片描述

JDLoginTest:

  1. 登陸之後判斷是否登錄成功(頁面是否包含”我的**”字符串)
  2. 到達豆豆頁面,要判斷是否包含”可用*豆”字符串
  3. 抓完豆豆明細數據,判斷三個list長度是否相等,正常情況下應該相等(每一條豆豆明細數據包含:日期,增加或減少多少豆豆,交易名稱)

JDLogin Code:

package pkg_JDLogin;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import java.util.List;

import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

/**
 * Created by Sophie on 03/20/2016
 */

public class JDLogin {
    private WebDriver dr;
    private String url;
    private String account;
    private String pwd;
    private String myJDXPATH;
    private String myBeanXPATH;
    private String datesXPATH;
    private String transacDetailsXPATH;
    private String transacNameXPATH;
    private String pageNextXPATH;
    private String total;
    private List dateDetail;
    private List transacDetail;
    private List transacName;

    public List retrieveJDBeanDatesDetails(){
        return dateDetail;
    }

    public List retrieveJDBeanTransacDetail(){
        return transacDetail;
    }

    public List retrieveJDBeanTransacName(){
        return transacName;
    }

    public JDLogin(String url, String account, String pwd,String myJDXPATH, String myBeanXPATH,
                   String datesXPATH, String transacDetailsXPATH, String transacNameXPATH, String pageNextXPATH){
        this.url = url;
        this.dr = new FirefoxDriver();
        this.dr.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        this.account = account;
        this.pwd = pwd;
        this.myJDXPATH = myJDXPATH;
        this.myBeanXPATH = myBeanXPATH;
        this.datesXPATH = datesXPATH;
        this.transacDetailsXPATH = transacDetailsXPATH;
        this.transacNameXPATH = transacNameXPATH;
        this.pageNextXPATH = pageNextXPATH;
    }

    public WebDriver login() throws Exception{
        dr.get(url);
        dr.findElement(By.id("loginname")).clear();
        dr.findElement(By.id("loginname")).sendKeys(account);
        dr.findElement(By.id("nloginpwd")).clear();
        dr.findElement(By.id("nloginpwd")).sendKeys(pwd);
        dr.findElement(By.id("loginsubmit")).click();
        //System.out.println(dr.getPageSource());
        Thread.sleep(2000);
        return dr;
    }

    public WebDriver JDBeanPage(){
        WebElement dropDown = dr.findElement(By.xpath(myJDXPATH));
        Actions act = new Actions(dr);
        act.click(dropDown).perform();
        dr.get(dr.findElement(By.xpath(myBeanXPATH)).getAttribute("href"));
        return dr;
    }

    public List getDatesDetail(WebDriver dr){
        List<WebElement> e = dr.findElements(By.xpath(datesXPATH));
        List result = new ArrayList<String>();
        for (int i = 0; i < e.size(); i ++){
            result.add(e.get(i).getText());
        }

        return result;
    }

    public List getTransacDetail(WebDriver dr){
        List<WebElement> e = dr.findElements(By.xpath(transacDetailsXPATH));
        List result = new ArrayList<String>();
        for (int i = 0; i < e.size(); i ++){
            result.add(e.get(i).getText());
        }

        return result;
    }

    public List getTransacName(WebDriver dr){
        List<WebElement> e = dr.findElements(By.xpath(transacNameXPATH));
        List result = new ArrayList<String>();
        for (int i = 0; i < e.size(); i ++){
            result.add(e.get(i).getText());
        }

        return result;
    }

    public void getJDBeanDetails(){

        total = dr.findElement(By.cssSelector("strong.ftx01.num")).getText();

        //dates that have transactions
        dateDetail = getDatesDetail(dr);
        //gain or lost JDBean
        transacDetail = getTransacDetail(dr);
        //name of transac
        transacName = getTransacName(dr);

        Actions act = new Actions(dr);

        //get pages size
        List<WebElement> pageHref = dr.findElements(By.xpath("//div[@class='pagin fr']/a[not(@class) and @href]"));
        if(pageHref.size() != 0) {//該用戶京豆交易明細至多隻有一頁的情況
            act.moveToElement(pageHref.get(0));
            act.click().perform();
        }
        //System.out.print(dr.getPageSource());

        for (int i = 1; i < pageHref.size(); i ++) {
            WebElement pageIcon = dr.findElement(By.xpath(pageNextXPATH));
            act.moveToElement(pageIcon);
            act.click().perform();

            //date
            dateDetail.addAll(getDatesDetail(dr));

            //gain or lost
            transacDetail.addAll(getTransacDetail(dr));

            //name of transac
            transacName.addAll(getTransacName(dr));

        }

        maskItemNumber(transacName);

        System.out.println("共有京豆:" + total + ",明細如下:\n==============================================================================");

        for(int i = 0; i < transacName.size(); i ++){
            System.out.println(dateDetail.get(i)+"\t\t\t\t\t\t"+transacDetail.get(i)+"\t\t\t\t\t\t"+transacName.get(i));
        }
    }

    public void maskItemNumber(List<String> transacName){
        StringBuffer s ;
        for (int i = 0; i < transacName.size(); i ++){
            if(transacName.get(i).toString().contains("商品")){
                s = new StringBuffer(transacName.get(i).toString());
                for(int j = 0; j < s.length(); j ++){
                    if (Character.isDigit(s.charAt(j)))
                        s.setCharAt(j,'*');
                }
                transacName.set(i,s.toString());
            }
        }
    }


    public void tearDown() throws Exception{
        dr.quit();
    }

    public static void main(String[] args) throws Exception {
        String url = "https://passport.jd.com/uc/login?ltype=logout";

        Scanner s = new Scanner(System.in);
        System.out.println("請輸入帳號:");
        String account = s.nextLine();

        System.out.println("請輸入密碼:");
        String pwd = s.nextLine();

        String myJDXPATH = "//li[@id='ttbar-myjd']/div[1]/i[@class='ci-right']/s";
        String myBeanXPATH = "//li[@id='ttbar-myjd']/div[2]/div[@class='otherlist']/div[@class='fore2']/div[2]/a";
        String datesXPATH = "//span[@class='ftx03']";
        String transacDetailsXPATH = "//table[@class='tb-void']/tbody/tr/td[2]/span";
        String transacNameXPATH = "//table[@class='tb-void']/tbody/tr/td[3]";
        String pageNextXPATH = "//div[@class='pagin fr']/a[@class='current']/following-sibling::a[1]";
        JDLogin jd = new JDLogin(url,  account,  pwd, myJDXPATH,  myBeanXPATH, datesXPATH,  transacDetailsXPATH,  transacNameXPATH,  pageNextXPATH);
        jd.login();
        jd.JDBeanPage();
        jd.getJDBeanDetails();
        jd.tearDown();
    }
}

JUnit測試代碼:

package pkg_JDLogin;

import org.junit.*;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import static  org.junit.Assert.*;
import java.util.Scanner;
import static org.hamcrest.Matchers.*;
import java.util.List;
/**
 * Created by Sophie on 16/3/20.
 */
public class JDLoginTest {
    private JDLogin jd;
    private WebDriver dr;

    @Before
    public void setUpBefore(){
        String url = "https://passport.jd.com/uc/login?ltype=logout";

        //Scanner s = new Scanner(System.in);
        //System.out.println("請輸入帳號:");
        String pwd = "***";

        //System.out.println("請輸入密碼:");
        String account = "***";

        String myJDXPATH = "//li[@id='ttbar-myjd']/div[1]/i[@class='ci-right']/s";
        String myBeanXPATH = "//li[@id='ttbar-myjd']/div[2]/div[@class='otherlist']/div[@class='fore2']/div[2]/a";
        String datesXPATH = "//span[@class='ftx03']";
        String transacDetailsXPATH = "//table[@class='tb-void']/tbody/tr/td[2]/span";
        String transacNameXPATH = "//table[@class='tb-void']/tbody/tr/td[3]";
        String pageNextXPATH = "//div[@class='pagin fr']/a[@class='current']/following-sibling::a[1]";
        jd = new JDLogin(url,  account,  pwd, myJDXPATH,  myBeanXPATH, datesXPATH,  transacDetailsXPATH,  transacNameXPATH,  pageNextXPATH);
        }

    @Test
    public void test() throws Exception {

        //login
        dr = jd.login();
        org.junit.Assert.assertThat( dr.getPageSource(),containsString("我的京東"));

        //JD bean page
        dr = jd.JDBeanPage();
        org.junit.Assert.assertThat(dr.getPageSource(), containsString("可用京豆"));

        //JD bean details
        jd.getJDBeanDetails();

        List<String> dates= jd.retrieveJDBeanDatesDetails();
        List<String> transacDetails = jd.retrieveJDBeanTransacDetail();
        List<String> transacName = jd.retrieveJDBeanTransacName();

        //System.out.println("Dates Size: "+dates.size() + "TransacName Size: "+ transacName.size() + "Transac Details Size: "+ transacDetails.size() );

        org.junit.Assert.assertEquals("抓取京豆明細異常:數據條數不匹配", dates.size(),transacDetails.size());
        org.junit.Assert.assertEquals("抓取京豆明細異常:數據條數不匹配", dates.size(),transacName.size());

        for(int i = 0; i < transacName.size(); i ++){
            for (int j = 0; j < transacName.get(i).length(); j ++){
                org.junit.Assert.assertFalse("敏感信息未隱藏: 第 " + i+1 + "條數據", Character.isDigit(transacName.get(i).charAt(j)));
            }
        }

    }

    @After
    public void testTearDown() throws Exception {
        jd.tearDown();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章