Android http实战模拟登录 okhttp/retrofit/jsoup/验证码获取

定义retrofit的接口

public interface ApiService {
    @GET("{part}/")
    Observable getNewsData(@Path("part") String part, @Query("key") String key, @Query("num") String num, @Query("page") int page);


    @FormUrlEncoded
    @POST("reader/redr_verify.php")
    Call getMyBookData(@Header("Cookie") String cookie,@FieldMap Map params);


    @FormUrlEncoded
    @POST("Default.aspx")
    Call allSeatSearch(@FieldMap Map params);


    @GET("FunctionPages/Statistical/LibraryUsedStat.aspx")
    Call getPhoto();

    @GET("reader/book_lst.php")
    Call getMyBookDataDetail(@Header("Cookie") String cookie);

    @GET("reader/captcha.php")
    Call getCookieData();

}

1.实现模拟登录图书馆,查看《我的借阅》
首先发现登录界面需要验证码,所以第一步获取验证码图片,拿到COOKIE保存起来。代码如下。

 public void requestTestOkhttp(){
        OkHttpClient okHttpClient=new OkHttpClient();
        Request request=new Request.Builder().get()
                .url("http://202.194.40.71:8080/reader/captcha.php")
                .build();
        okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
            @Override
            public void onFailure(okhttp3.Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
                Message message=handler.obtainMessage();
                if(response.isSuccessful()){
                    message.what=1;
                    message.obj=response.body().bytes();
                    handler.sendMessage(message);
                    String s=response.headers().get("Set-Cookie").toString();
                    String[] cookieArray=s.split(";");
                    Log.d("SearchMyBook",cookieArray[0]);
                    editor=pref.edit();
                    editor.putString("cookie",cookieArray[0]);//PHPSESSID=xxxxxxx;
                    editor.apply();
                }else{
                    Log.d("SearchMyBook","response is not successful");
                }
            }
        });
    }

因为okhttp的onresponse发生在子线程,无法进行UI操作,所以此处通过Handler进行图片的加载。通过response.body().bytes()转换成字节流传送,通过字节数组btye[]保存,通过BitmapFactory.decodeByteArray(result,0,result.length)将字节数组转换成bitmap图片,实现验证码获取下载。
(此处用retrofit转字节数组不成功,暂时搁置挖个坑以后过来填)

private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    byte[] result=(byte[])msg.obj;
                    Bitmap bitmap=BitmapFactory.decodeByteArray(result,0,result.length);
                    img.setImageBitmap(bitmap);
                    break;
            }
        }
    };

第二步携带COOKIE进行POST请求登录,此处通过RETROFIT完成。
通过Map携带参数。

 public void requestMyBook(Map params){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl("http://202.194.40.71:8080/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();
        ApiService service=retrofit.create(ApiService.class);
        Call call=service.getMyBookData(pref.getString("cookie",""),params);
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                //tv_mybook_search.setText(response.body().toString());
                requestMyBookDetail();
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                Toast.makeText(SearchMyBook.this,"请求失败",Toast.LENGTH_SHORT).show();
            }
        });
    }

第三步,登录后进行get请求获取具体的个人借阅页面,根据自己的需要新建实体类,此处我只需要借书名称,借出时间和应还时间。然后根据获得的H5代码通过JSOUP进行解析。添加对应的数据。

public void requestMyBookDetail(){
        Retrofit retrofit=new Retrofit.Builder()
                .baseUrl("http://202.194.40.71:8080/")
                .addConverterFactory(ScalarsConverterFactory.create())
                .build();
        ApiService service=retrofit.create(ApiService.class);
        Call call=service.getMyBookDataDetail(pref.getString("cookie",""));
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                if(response.isSuccessful()) {
                    StringBuilder sb=new StringBuilder();
                    Document doc= Jsoup.parse(response.body().toString());
//                    Elements content=doc.getElementsByAttributeValue("class","blue");
//                    for(Element link :content)
//                    {
//                        sb.append(link.getElementsByTag("a").text().toString()+"\r\n");
//
//                    }

                    //whitetext标签查询
//                    Elements content=doc.getElementsByAttributeValue("class","whitetext");
//                    for(Element link :content)
//                    {
//                        sb.append(link.getElementsByAttributeValue("width","35%").text().toString());
//                        sb.append(link.getElementsByAttributeValue("width","13%").text().toString());
//                    }
//                    tv_mybook_search.setText(sb.toString());

                    Element table=doc.getElementsByTag("table").get(0);
                    Element tbody=table.getElementsByTag("tbody").get(0);
                    Elements trs=tbody.getElementsByTag("tr");
                    for(int i=1;i call, Throwable t) {
                Toast.makeText(SearchMyBook.this,"请求失败",Toast.LENGTH_SHORT).show();
            }
        });
    }

第四步在BUTTON点击事件中进行请求,输入参数

 btn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Map params=new HashMap<>();
                params.put("number","******");
                params.put("passwd","******");
                params.put("captcha", editText.getText().toString());
                params.put("select","cert_no");
                params.put("returnUrl","");
                requestMyBook(params);
                Log.d("SearchMyBook",params.toString());
            }
        });

这样一个模拟登录请求就完成了。下面介绍今天做的另一部分,它让我浪费了很久的时间,感觉自己是真的蠢!!!!!!!
2.这一部分做的是座位的查询,主要卡在了post登录和图片的获取上。
我开始直接用post但是无法登录,后来发现先post一次获得返回的cookie,然后带着cookie才可以登录!(又栽在了cookie上),然后一层一层地访问,直到访问到最后一层发现图片格式很奇怪,百度发现是AJAX生成的,然后我就苦恼了,以为无法通过jsoup获取,因为发现在网页里无法通过输入链接打开,但是最后最后在ANDroid端竟然下载成功了,当我发现打印的Headers信息里,content-type变成了jpg,心情难以抑制的激动啊。。还好舍友提了一次,我抱着不太可能心态尝试了一下竟然成功了!此处先记一下,还是不太理解为什么在Android端可以访问,如果是因为cookie缘故pc上不是自动保存cookie了吗。。回头再去咨询一下大神。。
不管怎么说总算下载成功了,没白花费这么久,开心又希望下次能更快一点。。代码部分还是太冗余,明天尝试进行一下优化封装!!fight!

你可能感兴趣的:(Android http实战模拟登录 okhttp/retrofit/jsoup/验证码获取)