安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)

通过HttpURLConnection模拟登录

最近打算做一个课表的APP,准备爬取湖北工业大学的课表,因为学校教务系统是http协议的,所以就先拿学校练手了。废话不多说,开工。

登陆前检查

首先项目中请添加网络权限,要使用http网络也需要进行单独设置,这部分就不占用版面了,但是灰常重要。
打开教务系统,我这里是火狐浏览器,按下F12捕获,登陆后,可以看到登录的POST操作里包含账号密码和验证码。
安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)_第1张图片

cookie管理

要登陆成功我们首先要搞懂cookie的用途,简单的理解(可能不准确),cookie可以比喻成服务器放在你那里准考证,每次你要考试(登录)的时候,发给你一套试卷(验证码),试卷号绑定你的准考证,你做完这套卷子后填好你的信息后上交给老师(服务器),老师检查后确定你做的是自己的试卷(发的验证码和交的一样),信息也是正确的,就准许你毕业(登陆成功)。
所以在操作前我们要先做cookie的管理,我们这里可以使用自带CookieManager,在工具类的构造函数里,新建CookieManager并将其设置为接受所有的cookie。

public class Login_download {
    Context context;
   
    Login_download(Context context) {
        this.context = context;
        CookieManager cookieManager = new CookieManager();
        CookieHandler.setDefault(cookieManager);
        //接受所有cookie
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
    }
}

验证码爬取和保存

再次回到登陆界面,这时候我们要查找登录界面中获取到验证码的操作。验证码一般是图片,所以我们只需要重点寻找类型是图片的。

安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)_第2张图片在响应中可以看到这是验证码,这里只需要我们记录请求网址和方法是“GET”就好
安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)_第3张图片然后是代码部分和使用方法,获取到输入流后就可以直接用BitmapFactory将流中的图片转换为Bitmap。图片可以显示到主页面也可以保存到本地。

public Bitmap getimage(final String line) {
        try {
            URL url = new URL(line);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置为GET
            conn.setRequestMethod("GET");
            //超时为6000ms
            conn.setConnectTimeout(6000);
            InputStream inStream = conn.getInputStream();
            conn.connect();
            bitmap = BitmapFactory.decodeStream(inStream);
           
        } catch (SocketTimeoutException e3){
        	Log.e("LoginActivity", e3.toString());
            return null;
        } catch (Exception e) {
            Log.e("LoginActivity", e.toString());
            return null;
        }
        return bitmap;
    }

使用:

   private Login_download dct=null;
   private Bitmap bitmap2=null;//在前面定义的全局变量
   private void DoGetVerifation(String url_s) {
                dct = new Login_download(login.this);
                //网络访问这类费时操作不能放到主线程中
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if (url_s != null) {
                        	这里的bitmap就是我们要的验证码
                            bitmap2 = dct.getimage(url_s);
                            if (bitmap2 == null) {
                                  Looper.prepare();
                                  Toast.makeText(login.this, "无法连接到教务系统", Toast.LENGTH_SHORT).show();
                                  Looper.loop();
                            }
                        }else{
                            Message msg = new Message();
                            changeimage.sendMessage(msg);
                            //将验证码显示到主界面
                        }
                    }
                }).start();
            }

登录操作

通过第一步我们已经知道了post里面需要的信息,这里我们找到post对用的网址,进行登录废话少说,放代码。

//po是post的网址,post_words是post的信息,Stringmood是字符的编码(工地英语)
public String postinf(final String po, final String post_words,final String stringmood) {
        StringBuilder buffer = new StringBuilder();
        if(po.contains("https")){
		//https网址的处理,后期会再写一篇博客说这个
        }else {
            HttpURLConnection connection = null;
            try {
                URL url = new URL(po);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("POST");
                //允许输入输出
                connection.setDoOutput(true);
                connection.setDoInput(true);
                //不使用缓存和重定向设置
                connection.setUseCaches(false);
                connection.setFollowRedirects(true);
                //设置消息头,如果登陆失败可以根据学校网站添加修改
                connection.setRequestProperty("Connection", "keep-alive");
                connection.connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
            assert connection != null;
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()))) {
            //写入登录信息
                writer.write(post_words);
                writer.flush();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
            try {
            //如果返回值为200
                int responseCode = connection.getResponseCode();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = connection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, stringmood);
                    BufferedReader ddd;
                    String line;
                    ddd = new BufferedReader(inputStreamReader);
                    while ((line = ddd.readLine()) != null) {
                        buffer.append(line);
                    }
                    //返回相应数据
                    return buffer.toString();
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        //否则返回null
        return null;
    }

使用:

  private void nlogin() {
                Minf="开始登陆";
                Message msgg = new Message();
                setMinf.sendMessage(msgg);
                handler.postDelayed(refrush, 100);
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                    //这里的sc用来储存网址和拼接登录信息
                    //POST拼接的数据大概长这个样子,大家可以根据自己学校进行更改
                    //String body01 = "isRemember=1";
                	//String body02 = "Role=Student";
                	//String body03 = "UserName=" + user;
                	//String body04 = "Password=" + password;
                	//String body05 = "ValidateCode=" + verifation;
                	//body = body01 + "&" + body02 + "&" + body03 + "&" + body04 + "&" + body05;
                        String a=dct.postinf(sc.get_class_login_URL(),sc.log_body(dct,username.getText().toString(),password.getText().toString(),pwdin.getText().toString()),sc.get_class_login_code());
                        //打印post操作的返回数据
                        System.out.println(a);
   						
   						//登陆成功后获取课程表
                        //String myclass = dct.getinf(sc.get_class_URL(), sc.get_class_code());
                        //解析课程表部分省略
                        //Document doc = Jsoup.parse(myclass);
                        //Elements title=doc.getElementsByAttributeValue("align","center");
  						//解析课程表部分省略
                        }
                       
                    }
                }).start();
            }

获取课表

同样的,F12,然后在火狐里查看自己的课表,找到获取课表的那一项,记下网址,操作是GET,部分学校可能是post操作
安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)_第4张图片代码代码:

public String getinf(final String po,final String stringmood) {
        StringBuilder getbuffer = new StringBuilder();
        if(po.contains("https")){
       //https省略,下篇文章再讲一下爬取方正教务的
        }else {
            HttpURLConnection connection = null;
            try {
                URL url = new URL(po);
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                //get不需要输入
                connection.setDoOutput(false);
                connection.setDoInput(true);
                connection.setUseCaches(false);
                connection.setRequestProperty("Connection", "keep-alive");
                connection.connect();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                int responseCode = connection.getResponseCode();
                System.out.println(responseCode);
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = connection.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream, stringmood);
                    BufferedReader ddd;
                    String line;
                    ddd = new BufferedReader(inputStreamReader);
                    while ((line = ddd.readLine()) != null) {
                        getbuffer.append(line);
                    }
                    return getbuffer.toString();
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return null;
    }

使用方法在上面的POST部分有,已经被注释了,这里不再展示。
总的爬取过程其实不太复杂,有耐心找对网址,把需要的信息都找对其实很简单就可以实现爬取。

预告一下:下一篇会写爬取上海理工大学的方正教务系统

最后附一张我自己的app截图 ,可以酷安搜一下《T课表》
安卓开发-带验证码模拟登陆教务系统(HttpURLConnection)_第5张图片

你可能感兴趣的:(app,android,java,web,app,爬虫)