【问题标题】:How to parse PNR Captcha to get PNR status.?如何解析 PNR 验证码以获取 PNR 状态。?
【发布时间】:2014-02-17 20:34:08
【问题描述】:

我在 Google Play 上有一个 PNR 查询应用。它工作得很好。但是最近 Indian Railwys 在他们的 PNR 查询部分添加了验证码,因此我无法将正确的数据传递给服务器以获得正确的响应。如何以图像视图的形式在我的应用中添加此验证码,并要求用户输入验证码详细信息,以便我可以发送正确的数据并获得正确的响应。

Indian Railways PNR Inquiry Link

这是我之前使用的 PnrCheck.java。请帮助这里应该进行哪些修改..

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.DefaultHttpClientConnection;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.ExecutionContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.protocol.RequestConnControl;
import org.apache.http.protocol.RequestContent;
import org.apache.http.protocol.RequestExpectContinue;
import org.apache.http.protocol.RequestTargetHost;
import org.apache.http.protocol.RequestUserAgent;
import org.apache.http.util.EntityUtils;

public class PNRStatusCheck {
    public static void main(String args[]) {
        try {
            String pnr1 = "1154177041";
            String reqStr = "lccp_pnrno1=" + pnr1 + "&submitpnr=Get+Status";
            PNRStatusCheck check = new PNRStatusCheck();
            StringBuffer data = check.getPNRResponse(reqStr, "http://www.indianrail.gov.in/cgi_bin/inet_pnrstat_cgi.cgi");
            if(data != null) {
                @SuppressWarnings("unused")
                PNRStatus pnr = check.parseHtml(data);
            }
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public StringBuffer getPNRResponse(String reqStr, String urlAddr) throws Exception {
        String urlHost = null;
        int port;
        String method = null;
        try {
            URL url = new URL(urlAddr);
            urlHost = url.getHost();
            port = url.getPort();
            method = url.getFile();

            // validate port
            if(port == -1) {
                port = url.getDefaultPort();
            }
        } catch(Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params, "UTF-8");
        HttpProtocolParams.setUserAgent(params, "HttpComponents/1.1");
        HttpProtocolParams.setUseExpectContinue(params, true);

        BasicHttpProcessor httpproc = new BasicHttpProcessor();
        // Required protocol interceptors
        httpproc.addInterceptor(new RequestContent());
        httpproc.addInterceptor(new RequestTargetHost());
        // Recommended protocol interceptors
        httpproc.addInterceptor(new RequestConnControl());
        httpproc.addInterceptor(new RequestUserAgent());
        httpproc.addInterceptor(new RequestExpectContinue());

        HttpRequestExecutor httpexecutor = new HttpRequestExecutor();
        HttpContext context = new BasicHttpContext(null);
        HttpHost host = new HttpHost(urlHost, port);
        DefaultHttpClientConnection conn = new DefaultHttpClientConnection();

        context.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
        context.setAttribute(ExecutionContext.HTTP_TARGET_HOST, host);
        @SuppressWarnings("unused")
        String resData = null;
        @SuppressWarnings("unused")
        String statusStr = null;
        StringBuffer buff = new StringBuffer();
        try {
            String REQ_METHOD = method;
            String[] targets = { REQ_METHOD };

            for (int i = 0; i < targets.length; i++) {
                if (!conn.isOpen()) {
                    Socket socket = new Socket(host.getHostName(), host.getPort());
                    conn.bind(socket, params);
                }
                BasicHttpEntityEnclosingRequest req = new BasicHttpEntityEnclosingRequest("POST", targets[i]);
                req.setEntity(new InputStreamEntity(new ByteArrayInputStream(reqStr.toString().getBytes()), reqStr.length()));
                req.setHeader("Content-Type", "application/x-www-form-urlencoded");
                req.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7");
                req.setHeader("Cache-Control", "max-age=0");
                req.setHeader("Connection", "keep-alive");
                req.setHeader("Origin", "http://www.indianrail.gov.in");
                req.setHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
                req.setHeader("Referer", "http://www.indianrail.gov.in/pnr_Enq.html");
                //req.setHeader("Accept-Encoding", "gzip,deflate,sdch");
                req.setHeader("Accept-Language", "en-US,en;q=0.8");
                req.setHeader("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.3");


                httpexecutor.preProcess(req, httpproc, context);

                HttpResponse response = httpexecutor.execute(req, conn, context);
                response.setParams(params);
                httpexecutor.postProcess(response, httpproc, context);

                Header[] headers = response.getAllHeaders();
                for(int j=0; j<headers.length; j++) {
                    if(headers[j].getName().equalsIgnoreCase("ERROR_MSG")) {
                        resData = EntityUtils.toString(response.getEntity());
                    } 
                }
                statusStr = response.getStatusLine().toString();
                InputStream in = response.getEntity().getContent();
                BufferedReader reader = null;
                if(in != null) {
                    reader = new BufferedReader(new InputStreamReader(in));
                }

                String line = null;
                while((line = reader.readLine()) != null) {
                    buff.append(line + "\n");
                }
                try {
                    in.close();
                } catch (Exception e) {}
            }
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            try {
                conn.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return buff;
    }

    public PNRStatus parseHtml(StringBuffer data) throws Exception {
        BufferedReader reader = null;
        if(data != null) {
            reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data.toString().getBytes())));
        } else {
            return null;
        }

        String line = null;
        TrainDetails trainDetails = new TrainDetails();
        List<PassengerDetails> passDetailsList = new ArrayList<PassengerDetails>();
        PassengerDetails passDetails = null;
        int i = 0;
        while ((line = reader.readLine()) != null) {
            if(line.startsWith("<TD") && line.contains("table_border_both")) {
                line = line.replace("<B>", "");
                line = line.substring(line.indexOf("\">")+2, line.indexOf("</")).trim();

                if(line.contains("CHART")) {
                    trainDetails.setChatStatus(line);
                    break;
                }
                if(i > 7) {//Passenger Details
                    if(passDetails == null) {
                        passDetails = new PassengerDetails();
                    }
                    switch(i) {
                    case 8 :
                        passDetails.setName(line);
                        break;
                    case 9 :
                        passDetails.setBookingStatus(line.replace(" ", ""));
                        break;
                    case 10 :
                        passDetails.setCurrentStatus(line.replace(" ", ""));
                        i = 7;
                        break;
                    }
                    if(i == 7 ) {
                        passDetailsList.add(passDetails);
                        passDetails = null;
                    }

                } else { // Train details
                    switch(i){
                    case 0 :
                            trainDetails.setNumber(line);
                            break;
                    case 1 :
                            trainDetails.setName(line);
                            break;
                    case 2 :
                            trainDetails.setBoardingDate(line);
                            break;
                    case 3 :
                            trainDetails.setFrom(line);
                            break;
                    case 4 :
                            trainDetails.setTo(line);
                            break;
                    case 5 :
                            trainDetails.setReservedUpto(line);
                            break;
                    case 6 :
                            trainDetails.setBoardingPoint(line);
                            break;
                    case 7 :
                            trainDetails.setReservedType(line);
                            break;
                    default :
                        break;
                    }
                }
                i++;
            }
        }

        if(trainDetails.getNumber() != null) {
            PNRStatus pnrStatus = new PNRStatus();
            pnrStatus.setTrainDetails(trainDetails);
            pnrStatus.setPassengerDetails(passDetailsList);
            return pnrStatus;
        } else {
            return null;
        }
    }

}

请帮助现在应该对代码进行哪些更改才能获得状态。提前谢谢大家。

【问题讨论】:

    标签: java android json parsing xmlhttprequest


    【解决方案1】:

    如果我们使用上面提到的方法,我们将得到 empty("") 字符串。那是因为如果我们查看生成的 HTML,我们会发现:

    <span id="txtCaptchaDiv" style="background-image:url(1.jpg); text-align:center;            
    border:none;font-weight:bold; font-family:Modernfont-size=12></span> 
    <input name="lccp_cap_val" value="78358" id="txtCaptcha" type="hidden">
    

    要提取验证码的值,我们可以使用这个

        int startOfSpanTag = data.indexOf("<span id=\"txtCaptchaDiv\"");
        int endOfSpanTag = data.indexOf("</span>", startOfSpanTag);
        int posOfValueAttr = data.indexOf("value=", endOfSpanTag);
        int startPosOfDoubleQuote = data.indexOf("\"", posOfValueAttr);
        int endPosOfDoubleQuote = data.indexOf("\"", startPosOfDoubleQuote + 1);
        String capatcha = data.substring(startPosOfDoubleQuote + 1, endPosOfDoubleQuote);
    

    希望您到现在为止一定已经找到了答案。如果您有更好的解决方案,请分享您的 cmets !!!!!!。

    【讨论】:

      【解决方案2】:

      分析您的目标服务器后,您可以像这样更改您的代码:

      String captcha = "37819";
      String pnr1 = "1154177041";
      String reqStr = "lccp_pnrno1=" + pnr1 + "&lccp_cap_val=" + captcha + "&lccp_capinp_val=" + captcha + "&submitpnr=Get+Status";
      PNRStatusCheck check = new PNRStatusCheck();
      StringBuffer data = check.getPNRResponse(reqStr, "http://www.indianrail.gov.in/cgi_bin/inet_pnstat_cgi_28688.cgi");
      

      他们正在向客户发送验证码,当您提交表单时,他们正在等待他们发​​送的验证码以及用户输入的值! :)

      【讨论】:

      • 感谢您的回复。我一定会检查并尽快回复。
      • 对不起,Rida.. 它仍然无法正常工作。真的很失望,我也没有得到关于这个问题的任何其他答复。
      • 我已经更新了我的代码,测试它并且它正在工作。他们已将网址更改为 http://www.indianrail.gov.in/cgi_bin/inet_pnstat_cgi_28688.cgi,但我认为您的 pnr 1154177041 不再有效;)
      • 有消息,你测试了吗?
      • 不走运里达。但是您对 URL 的看法是正确的。非常感谢你。我没有注意到。
      【解决方案3】:

      您可以从 html 文本中提取验证码answer

      <span id="txtCaptchaDiv" style="background-image:url(1.jpg); text-align:center; border:none;
           font-weight:bold; font-family:Modern font-size=12">59747</span>
      

      背景由http://www.indianrail.gov.in/1.jpg处的图片给出,你可以忽略它:)))))

      (HOWTO:在谷歌浏览器中打开页面,在 captha 上右击并选择“Inspect Element”)。

      更新: 尝试类似

      //StringBuffer data
      int start = data.indexOf("<span id=\"txtCaptchaDiv\"");
      int middle = data.indexOf(">", start);
      int end = data.indexOf("</span>", middle);
      String captcha = data.substring(middle+1,end);
      

      【讨论】:

      • 在 java 中,您必须在 xml 源中找到该字符串。或者解析输出并从解析的东西中获取它。
      • 查看 UPD。它只是找到一个子字符串。
      • 但是如何在上面给出的java文件中更新这个验证码。?我试过但没有结果。?你能帮我修改上面的java文件,以便发送正确的http请求吗?
      猜你喜欢
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多