爬取学校教务网课表与成绩 java版

这篇博客介绍了如何使用Java编写爬虫来获取学校教务网的课表和成绩。重点讲解了利用Jsoup解析HTML、通过分析cookie和Referer获取登录状态、以及登录过程中的加密机制。博主分享了代码实现,包括登录过程、获取关键jsessionid以及后续数据爬取。最后,提供了相关依赖库的下载链接。
摘要由CSDN通过智能技术生成

爬取学校教务网的课表与成绩java版

​ 这是安卓课设时本人做的一个简单的app里面所涉及到的爬虫部分,由于android编程是用java语言来写的,为了兼容,本人也使用了java来写爬虫。

cookie

cookie 在存储上是一段键值对信息,服务器本身无法判断用户身份,cookie便是用来让服务器鉴别身份状态的。在这里服务器就会根据cookie的内容来辨别用户有没有登录,如果我们想获取我们自己的教务网信息,我们只需要拿到能够标识自己身份的cookie和请求放一起提交到服务端,便能拿到自己的信息。

请求头中的 Referer

referer 是 Http 请求header的一部分,它一般标识从哪一个地址发出的本次请求,我们可以通过Referer来找到发出本次的请求来进行分析

Jsoup

一种java第三方包,用来解析HTML,对于数据爬取有很大的帮助

寻找自己的身份标识 cookie(从后向前)

登陆成功的主界面,通过检查 Network,我们找到了里面两个我们比较关心的数据 referer 和 cookie(此时的cookie已经可以标识我们的身份了)

在这里插入图片描述
可以注意到cookie 里面有两个jsessionid。但我们并不知道原因,我们便将注意力先放在Referer上。

访问 referer 网址,再次进行检查时,我们再次找到了cookie,对比上面的cookie,我们可以发现这次的cookie比之前的少了一个 jsessionid,我们便可以大胆的猜测,这个缺失的jsessionid便是对身份标识的关键。
在这里插入图片描述

试图获取关键的jsessionid

​ 既然是表示身份的jsessionid,那必定与输入的密码与账户有关,我们现在可以看一下登录时发生了什么,下面为点击登录的函数,遗憾的是并没有发现什么有用的线索。
在这里插入图片描述

我们现在变换思路从前往后看,我们检查一下NetWork从登录界面到主界面传过来的doc文档,发现前两个doc是第一步我们检查没有发现的界面
在这里插入图片描述
我们观察到第一个doc的cookie并没有标识身份的jsessionid
在这里插入图片描述
第二个doc却出现了身份标识的jsessionid,并且Referer是第一个doc,我们可以猜测肯定是第二个doc从第一个里面获取到了什么数据。
在这里插入图片描述

再次观察第一个doc,发现里面有form表单,里面有三个数据,用户名,密码以及encoded,传过去的密码为空,账户为明码,这两个迹象表明传过去的encoded才是真正的有用的东西,可能是通过加密将密码账户加密成encoded,我们现在就可以开始找endcoded相关的东西了
在这里插入图片描述

通过搜索encoded 我们很快的找到了一个比较可疑的函数,这是一个局部刷新的函数,大致意思是向一个网址请求数据,返回的数据再进行一系列操作。其中,里面用到了我们所输入的账户以及密码。并进行了一系列的加密。
在这里插入图片描述
在这里插入图片描述

​ 通过对loginajax()函数的搜索,发现这里原来就是login()函数所调用的一个函数,之前没有仔细的观察,尴尬了QAQ。现在我们可以确定上面的加密函数确实是对密码账户以及对strUrl进行访问获取的一段string,共同加密得到的encoded。

获得jsessionid

当我们获得endcoded 之后我们便可以访问第二个doc,通过观察,我们可以发现第一个doc中的location便是第二个doc的url,这样就好办了,我们这样通过访问第二个doc便可以获得那个可以真正标识我们身份的cookie了。
在这里插入图片描述
通过获取到的cookies我们便可以对学校教务网的任意一个网页进行访问,结合Jsoup来对数据进行爬取!

获取cookie:

package spiderMethod;

import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class getCookies {

    public static String LOGIN_URL = "http://kdjw.hnust.edu.cn/";
    public static String url1 = "http://kdjw.hnust.edu.cn/Logon.do?method=logon&flag=sess";
    public static String url2 = "http://kdjw.hnust.edu.cn/Logon.do?method=logon";
    public static String url3 = "http://kdjw.hnust.edu.cn/jsxsd/xskb/xskb_list.do";
    public static String USER_AGENT = "User-Agent";
    public static String USER_AGENT_VALUE = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36";
    public static String user;
    public static String password;
    public static Map<String, String> cookies = new HashMap<>();
    public static int flag; // 标志是否拿取成功,可用于登录密码是否正确,也可直接判断cookies的值


    public getCookies(String user, String password) {
        this.user = user;
        this.password = password;

    }

    public int getFlag() {
        return flag;
    }

    public Map getCookies() throws IOException {
        return log(user, password);
    }

    //获得dataString
    public static String get_dataString(Connection.Response response) throws IOException {

        String s = response.header("Set-Cookie"); //获得Set-Cookie
        String[] array = s.split(";| |,|=|/");
//        System.out.println(s);
        String JSESSIONID = "", SERVERID = "";
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
            if (array[i].equals("SERVERID")) {
                SERVERID = array[i + 1];
                i++;
            }
            if (array[i].equals("JSESSIONID")) {
                JSESSIONID = array[i + 1];
                i++;
            }
        }
        //存入新的cookies中
        cookies.put("JSESSIONID", JSESSIONID);
        cookies.put("SERVERID", SERVERID);
        System.out.println(cookies);

        Connection connection = Jsoup.connect(url1);
        connection.header(USER_AGENT, USER_AGENT_VALUE);
        Connection.Response rs = connection.cookies(cookies).execute();
        Document doc = Jsoup.parse(rs.body());
        System.out.println(doc.select("body").text());
        return doc.select("body").text();
    }




    public static Map log(String user, String password) throws IOException {

        try {
            Connection connection1 = Jsoup.connect(LOGIN_URL);

            //print(LOGIN_URL);
            connection1.header(USER_AGENT, USER_AGENT_VALUE);   // 配置模拟浏览器
            Connection.Response rs = connection1.execute();     // 获取响应

            String dataString = get_dataString(rs);
            String encoded = get_code.get_encoded(dataString, user, password);

            Document d1 = Jsoup.parse(rs.body());       // 通过Jsoup将返回信息转换为Dom树
            List<Element> eleList = d1.select("form");  // 获取提交form表单,可以通过查看页面源码代码得知
            // 获取cooking和表单属性
            Map<String, String> datas = new HashMap<>();
            for (int i = 0; i < eleList.size(); i++) {
                for (Element e : eleList.get(i).getAllElements()) {
                    // 设置用户名
                    if (e.attr("name").equals("userAccount")) {
                        e.attr("value", user);
                    }
                    // 设置用户密码
                    if (e.attr("name").equals("userPassword")) {
                        e.attr("value", "");
                    }
                    if (e.attr("name").equals("encoded")) {
                        e.attr("value", encoded);
                    }
                    // 排除空值表单属性
                    if (e.attr("name").length() > 0 && !e.attr("name").equals("loginForm")) {
                        datas.put(e.attr("name"), e.attr("value"));
                    }
                }
            }
            Connection con2 = Jsoup.connect(url2);
            con2.header(USER_AGENT, USER_AGENT_VALUE);
            System.out.println(cookies);
            // 设置cookie和post上面的map数据
            Connection.Response login = con2.followRedirects(false)
                    .method(Connection.Method.POST)
                    .data(datas).cookies(cookies)
                    .header("ContentType", "application/x-www-form-urlencoded")
                    .execute();
//        System.out.println(login.body());
//        System.out.println(login.cookies());
            String location = login.header("Location");//空
            System.out.println(location);
            Connection connection3 = Jsoup.connect(location);
            Connection.Response cdx = connection3.followRedirects(false)
                    .method(Connection.Method.GET)
                    .header("ContentType", "application/x-www-form-urlencoded")
                    .cookies(cookies)
                    .execute();
            // 打印,登陆成功后的信息
            if (cdx.statusCode() != 302)
                System.out.println("登陆失败");
            else {
                System.out.println(cdx.cookies());
                Map<String, String> map = cdx.cookies();
                for (String s : map.keySet()) {
                    System.out.println(s + " : " + map.get(s));
                }
                Connection con7 = Jsoup.connect(url3);
                cdx.cookies().put("SERVERID", cookies.get("SERVERID"));
            }

            System.out.println(cdx.cookies());
            flag = 1;
            return cdx.cookies();
        } catch (Exception e) {
            Map<String, String> st = new HashMap<String, String>();
            flag = 0;
            return st;
        }
    }
}

这里给出获取cookie 的步骤,加密函数就不给出了哈~

我把具体代码放在GitHub上了,大家有兴趣自取
里面包含了对自己四六级,课程成绩,考试安排等方面的爬取,欢迎大家学习交流
在这里插入图片描述
下面给出jsoup以及其他的依赖包:

https://pan.baidu.com/s/1CxzKc3o7_RzrRfAYt71lLw 提取码: 6qms

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值