java爬蟲模擬預約座位

java爬蟲模擬預約座位

因爲近來準備考研,每天需要預約圖書館的座位好不麻煩,於是想着怎麼整一個代碼,自動幫我預約座位。主要需求就是每天凌晨預約 (搶)明天的座位。

一.模擬登陸

因爲圖書館的預約系統比較簡單,登陸都是不需要驗證碼的,這裏給出一個登陸界面圖形,如下所示:
在這裏插入圖片描述
這樣模擬登錄就很好實現了,詳見我的博客 Java 爬蟲實戰之模擬登陸

二.預約座位

在登陸成功之後,就可以開始預約座位了。這裏有如下幾個難點:

  • 因爲在點擊“預約座位”之後,會有一個按鈕進行確認,這個確認怎麼在代碼中實現?
  • 預約座位post請求頭的處理
    其實第二個問題就是第一個問題的引申。我們知道現在大多數的網頁使用的都是ajax進行動態刷新網頁,這樣不用像服務器重新請求就可以刷新網頁了。在點擊“預約座位”之後肯定是進行了網頁的刷新(要麼是修改了表單,要麼是做了其他什麼操作),然後進行請求。
    我之前的思路是:該怎麼在代碼中模擬這個點擊確認的功能,但是沒有抽象到想到:其實這個按鈕的功能實際上可能就是修改了請求中某個表單,或者是在請求頭中添加了某個字段而已!
    有了這個思路的轉換,我就知道之前爲什麼預約座位不成功了。原因就是沒有找出動態刷新之後真正提交的請求 。
    於是研究網頁刷新之後進行的操作,仔細對比無法實現功能的代碼已經瀏覽器的調試結果,發現一個重要的差異在於:代碼中的請求頭丟失瞭如下這個玩意兒:
    在這裏插入圖片描述
    這就是Ajax的確認按鈕之後修改的請求頭,而其他沒有任何變化。

根據網頁的顯示:其請求參數如下:
在這裏插入圖片描述
請求的報頭如下:
在這裏插入圖片描述
根據上面寫出下面預約座位的代碼:

/**
         * 3.開始預約座位
         */

        //設置請求數據
        Map<String,String> info = new LinkedHashMap<String, String>();
        String atDate ;//哪一天
        String st ;//
        String et ;//

        //1.獲取日期
        Date date = new Date();
        DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd");
        //2.獲取當前天+1
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE,+1);//明天:正數 ;昨天:負數
        date=calendar.getTime();
        atDate = df1.format(date);

        st = atDate +" "+ start;
        et = atDate +" "+ end ;

        info.put("atDate",atDate);
        info.put("sid",sid);
        info.put("st",st);
        info.put("et",et);

        String param = JSON.toJSONString(info);

        // 獲取連接
        Connection con_reserve = Jsoup
                .connect("http://?????.aspx");
        con_reserve.header("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0");// 配置模擬瀏覽器
        //因爲這個方法是Ajax 的一個動態方法,所以一定要加到請求頭中,否則無法生效
        con_reserve.header("X-AjaxPro-Method","AddOrder");
        con_reserve.cookies(login.cookies());
        con_reserve.requestBody(param);

        Response seatInfo = con_reserve.ignoreContentType(true)
                .method(Method.POST)
                .header("Content-Type", "application/json")
                .execute();

        System.out.println(seatInfo.statusCode());
        System.out.println(seatInfo.body());

對上面的代碼存在的問題有:

  • post請求參數一定要使用json格式嘛?使用maps的數據格式行不行?因爲之前登錄時,使用的數據格式就是map,那麼按理來說,使用maps應該也是可以的。
  • cookie登錄之後,使用的是登錄的cookie,那麼使用之前第一次的cookie行不行?
    對上面代碼還可改進之處有:
  • cookie的本地磁盤化,避免下次再次請求。該怎麼實現?
  • cookiesession之間的區別?
  • ajax技術的使用【如果真想熟練使用爬蟲技術的話】
  • 如果網絡通信存在問題,代碼一次預約位置不成功,該怎麼處理?
  • 是否可以重複利用這個connection實例?還是說每次請求一個新的url,都需要一個新的connection
  • 是否應該將預約位置的代碼抽離到一個單獨的方法中?
  • 是否應該針對“預約成功”或者“預約失敗”進行一個日誌的保留?

但是因爲最近沒有那麼多的時間,這些待完善的功能,我會再慢慢實現,儘量讓這個系統無bug。

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