【畢設梳理】開始嘗試寫代碼——查票篇

提要:html

查詢餘票網址、所需參數可見上篇博客(http://www.cnblogs.com/sei-cxt/p/8429069.html)。java

參考網上發送https請求的案例代碼寫出能實現查詢餘票的簡易程序,具體代碼原理詳情暫且無論。數組


關於對http和https的鏈接和請求,網上有多種版本,用的最多的就是HttpURLConnection、HttpsURLConnection和HttpClient。如下編寫的代碼參考於兩個網址:瀏覽器

http://blog.csdn.net/qh_java/article/details/52311226緩存

http://blog.csdn.net/guozili1/article/details/53995121app

 

1. 工具類(HttpsRequest):暫時只寫了GET方法,其中要注意的是:dom

GET方法的參數是直接追加在地址後面的,所以doOutput默認爲false便可。ide

在此例中,若setRequestMethod爲「POST」,會報411錯誤,是由於沒有提供相應的BODY數據。須要把doOutput設置爲true,而且使用OutputStream輸出數據。(雖然不會報錯了,但返回的數據爲空)函數

同時有的網站不容許使用「POST」方法,當用OutputStream輸出數據後會報405錯誤。工具

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.HttpsURLConnection;

public class HttpsRequest {

    public static String methodGet(String urlStr, Map<String, Object> params) {

        String realUrl = urlStr;
        StringBuffer sb = new StringBuffer();
        
        // GET方法須要將查詢字符串拼接在url後面
        if(params != null && params.size() != 0) {
            realUrl += encodeParam(params);
        }
        
        try {
            // 鏈接url
            URL url = new URL(realUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            
            conn.setRequestMethod("GET");
            // URL鏈接可用於輸入和/或輸出
            // 若是打算使用 URL鏈接進行輸出,則將DoOutput標誌設置爲true,默認值爲false
            // 若是打算使用 URL鏈接進行輸入,則將DoInput標誌設置爲true,默認值爲true
            // conn.setDoOutput(false);
            // conn.setDoInput(true);
            // 容許鏈接使用任何可用的緩存,默認值爲true
            // conn.setUseCaches(true);
            
            conn.setSSLSocketFactory(MyX509TrustManager.getSSLSocketFactory());
            
            // 設置通常請求屬性
            conn.setRequestProperty("accept", "*/*"); // 客戶端能夠處理哪些數據類型
            conn.setRequestProperty("connection", "Keep-Alive"); // 設置長鏈接,無過時時間
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"); // 使用的何種瀏覽器
            
            // 創建通訊連接
            conn.connect();
            
            // 讀取response
            InputStreamReader isr = new InputStreamReader(conn.getInputStream(), "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String res = null;
            while((res = br.readLine()) != null) {
                sb.append(res);
            }
            
            br.close();
            isr.close();
            
        } catch (IOException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        }
        
        return sb.toString();
    }
    
    /**
     * 將查詢的map形式的參數轉碼並拼成查詢字符串
     * @param params
     * @return
     */
    private static String encodeParam(Map<String, Object> params) {
        if(params == null || params.size() == 0) {
            return "";
        }
        
        StringBuffer sb = new StringBuffer("?");
        for(Entry<String, Object> para : params.entrySet()) {
            try {
                sb.append(URLEncoder.encode(para.getKey(), "UTF-8"));
                sb.append("=");
                sb.append(URLEncoder.encode(para.getValue().toString(), "UTF-8"));
                sb.append("&");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
        
        String query = sb.toString();
        // 去掉最後一個&
        return query.substring(0, query.length() - 1);
    }
}

 

2. 證書相關類(MyX509TrustManager):之後再弄明白原理。

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class MyX509TrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public static SSLSocketFactory getSSLSocketFactory() throws NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException{  
        TrustManager[] tm = {new MyX509TrustManager()};  
        SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");  
        sslContext.init(null, tm, new java.security.SecureRandom());  
        SSLSocketFactory ssf = sslContext.getSocketFactory();  
        return  ssf;  
    }  
}

 

3. main函數:

其中參數params我最開始用的HashMap,可是沒法獲得正確的返回數據。斷點後看出拼接後的網址中查詢字符串順序有顛倒,與前篇博客中抓取的網址有細微的不一樣,並驗證得知這就是錯誤緣由。因而換爲LinkedHashMap(能夠按照插入的順序遍歷的Map),成功。

之後考慮換爲JSON或者構造一個信息類,使用類的數組去解決問題。

正確:(使用LinkedHashMap)

錯誤:(使用HashMap)

    public static void main(String[] args) {
        Map<String, Object> params = new LinkedHashMap<String, Object>();
        params.put("leftTicketDTO.train_date", "2018-02-24");
        params.put("leftTicketDTO.from_station", "BJP");
        params.put("leftTicketDTO.to_station", "SHH");
        params.put("purpose_codes", "ADULT");
        
        String url = "https://kyfw.12306.cn/otn/leftTicket/queryZ";
        
        String response = HttpsRequest.methodGet(url, params);
        System.out.println(response);
    }

 

4. 獲得結果:

{"data":{"flag":"1","map":{"AOH":"上海虹橋","BJP":"北京","SHH":"上海","VNP":"北京南"},"result":["|預訂|240000G1512M|G151|VNP|AOH|VNP|AOH|16:35|22:35|06:00|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P2|01|12|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|2400000G2302|G23|VNP|AOH|VNP|AOH|17:00|22:39|05:39|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P3|01|10|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|240000G1530E|G153|VNP|AOH|VNP|AOH|17:15|22:49|05:34|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P3|01|09|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|240000G1551S|G155|VNP|AOH|VNP|AOH|17:20|23:08|05:48|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P4|01|11|1|0|||||||||||無|無|無||O0M090|OM9|1","|預訂|240000G1570K|G157|VNP|AOH|VNP|AOH|17:43|23:30|05:47|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P3|01|09|1|0|||||||||||無|無|無||O0M090|OM9|1","|預訂|240000G1591Z|G159|VNP|AOH|VNP|AOH|17:48|23:44|05:56|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P4|01|09|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|24000000G704|G7|VNP|AOH|VNP|AOH|19:00|23:24|04:24|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P3|01|04|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|24000000G900|G9|VNP|AOH|VNP|AOH|19:05|23:39|04:34|N|usY%2BUl57hWKitIUp1d4m3n3e0ys4iJTdDfedKU6oXk7F3bAb|20180224|3|P4|01|05|1|0|||||||||||無|無|無||O0M090|OM9|0","|預訂|240000T1090Z|T109|BJP|SHH|BJP|SHH|19:31|10:43|15:12|N|SPyTjS4UE%2BFObI0x4k%2BxWLp41d7MjhINm2wQh8uIolnaeFXRL%2FuqgWcGuRcAiAPUTzxg45bjonU%3D|20180224|3|P4|01|09|0|0||無||無|||無||無|無|||||1040601030|14613|0","UKEhCCI8hqymqGKMu%2B8o597E1HEFnc7PrfQE9WX27aIY0MUZDkZLk7N8xX7027vok5DOLqFeijxQ%0ArVQHPRvldY8ullIIyVt2YYVGSU4WB30nfCSyIgti51pNhRkDqgPRdDCYB34cRQ34xpSBesP53hzV%0Ay%2FqGj551m%2FeK%2BAxwtosRSxdmF95FvZwU6y0H4mbfrw5CAcLy4LfQ5lHEwRKlyOD8%2BHyUCCmiqAz8%0ATTniRABrPWmdQgu2a5nZ2yE%3D|預訂|240000D3130T|D313|VNP|SHH|VNP|SHH|19:34|07:41|12:07|Y|%2FeEHM%2BOX%2FhkUjkIf%2Bhc9UBJHyhWbXMzLqkOUJ61gyvzxghhA|20180224|3|P3|01|04|0|0||||有|||無||||無||||O0O040|OO4|0","B2ptaQsZngo3cuVpKR490RKFxw%2FujNVfaO8q%2Fz9nOn%2Bv9%2BlQsoxygraTjYr8hjp4ls6MDs0jnusA%0Alafi6AR3NiTZBBs4vA41Stjj2m%2Fty%2FyLO2TDRnjk5Mzt00a7ADMG6L56oaDDK7NpYbx8pNPr7ZPP%0AMeVYdrHdxA3VSz78Sx7mRlmOfko8C6ep%2FB4PGNKvywXfmmmiWPr7p%2BRm39gQT5ISQ5WBmGDRFvbJ%0Al3CPql7gu563|預訂|240000D3110J|D311|VNP|SHH|VNP|SHH|21:16|09:09|11:53|Y|%2BypbKTC2HZlFzZByUcQ3VvnTcGuNsar%2B|20180224|3|P2|01|04|0|0||||無||||||||||有|F040|F4|0","nr35RXw6%2BkkqgJ0axRZOQs8MeSPKVstyvt6jqk5NNZpZurw8b0HiI8mnxKbMGYPxoDKfGAvI4%2Bdv%0AsQoW9lSHwZK4PaPjoYpWM90B7gL1IjKy5NW6zsf95CtVyWh8Qgd0nIaDU%2F0NGpD%2FyJiX%2BnUa6igm%0AtPNlEGe2pjgpcCLkQeKs9z3dHdQS18rHxPTnChe8HRrsLTGcBzxzMW%2BbjNE%2FWQqQaLeYSwTJImP5%0Az%2F60kEOkSBw29fQO2Cbp%2Bps%3D|預訂|240000D3210D|D321|VNP|SHH|VNP|SHH|21:23|09:15|11:52|Y|Qu9exXtC3AVH27oNnBfVX5zFLnqdhQ1lY5vwmAt4du%2FqF0zQ|20180224|3|P2|01|04|0|0||||有|||無||||無||||O0O040|OO4|0"]},"httpstatus":200,"messages":"","status":true}
相關文章
相關標籤/搜索