Java爬取12306余票

  一、前言

  

  今年国庆和中秋一起放,虽然很欢快,但是没有票了!!!

  于是自己倒腾了一个查询余票的小程序。

 

  二、准备工作

   

  1、先打开12306的页面

  

  2、然后右键检查,点network

  

  3、再点一下12306页面上的查询,就可以看到发起了ajax请求

  

  4、点第一个,很明显是json串,这样就方便很多

  

  5、复制第二个的链接

 

  

  比如我这里就是:

      https://kyfw.12306.cn/otn/leftTicket/queryX?leftTicketDTO.train_date=2017-10-01&leftTicketDTO.from_station=BJP&leftTicketDTO.to_station=NJH&purpose_codes=ADULT

 

  三、开始工作

 

   这是通过HttpURLConnection来发起一个请求,里面的网址就填准备工作里面复制的那串

  /**
     * 发起一个http请求
     */
    public static void sendHttp(){
        URL url;
        int responsecode;
        HttpURLConnection urlConnection;
        BufferedReader reader;
        String line;
        try{
            //忽略Ssl(针对12306)
            SslUtils.ignoreSsl();
            //生成一个URL对象
            url=new URL("这里填你要访问的网址");
            /**
             * 这是为了防止12306对同一ip多次访问进行限制
             * 这里填的ip是暂时有效的,想要获取更多就得自己去找 搜索代理ip
             */
            System.getProperties().setProperty("proxySet", "true");
            System.setProperty("http.proxyHost", "120.78.15.63");  
            System.setProperty("http.proxyPort", "80"); 
            //打开URL
            urlConnection = (HttpURLConnection)url.openConnection();
            //伪造一个请求头 一般网页不用,有些网站会看你有没有请求头,比如 12306......
            urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0"); 
            urlConnection.setRequestProperty("Host","kyfw.12306.cn");
            urlConnection.setRequestProperty("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
            urlConnection.setRequestProperty("Accept-Language","zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3");
            urlConnection.setRequestProperty("Accept-Encoding","identity");
            urlConnection.setRequestProperty("Connection","keep-alive");
            urlConnection.setRequestProperty("Upgrade-Insecure-Requests","1");
            //获取服务器响应代码
            responsecode=urlConnection.getResponseCode();
            //假如响应代码为200,就是代表成功
            if(responsecode==200){
                reader=new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),"UTF-8"));
                while((line=reader.readLine())!=null){
                    System.out.println(line);//在这里干你想干的事情
                }
            }else{
                System.out.println("获取不到网页的源码,服务器响应代码为:"+responsecode);
            }
        }catch(Exception e){
            System.out.println("获取不到网页的源码,出现异常:"+e);
        }
    }

   

  跑这个方法之前还需要用到一个类,是用来忽略12306的证书问题

package domain;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SslUtils {

    public static void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    static class miTM implements TrustManager,X509TrustManager {
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }


    public static void ignoreSsl() throws Exception{
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                return true;
            }
        };
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }
}

 

  然后跑一下这个方法,看到获取到了json

  

 

 

  就可以对这串字符串为所欲为了,嘿嘿嘿

 

 

  四、最后

   

  一般查到余票都是发邮件,不会JavaMail的可以看我另一篇博客,开箱即用。

 

  转载需标注原文地址!

 

posted @ 2017-09-26 10:23  夏日浅笑、  阅读(3152)  评论(7编辑  收藏  举报