我的第一个开源项目:Java爬虫爬取旧版正方教务系统课程表、成绩表

Java爬虫爬取旧版正方教务系统课程表、成绩表

一、项目展示

1.正方教务系统

  • 首页

    正方教务系统首页

2.爬虫系统

  • 首页:

    爬虫系统首页

  • 成绩查询:

    成绩查询展示

  • 课表查询:

mark

二、项目实现

1.爬取思路描述

无论是成绩查询或课表查询亦或者其它的信息查询,都必须是要在登录状态下才能进行。而要登录教务系统,就要先获取登录的验证码,然后输入学号密码和验证码,向教务系统发起登录请求,登录成功后,需要保存登录状态,即记录cookie。有了登录成功后的cookie,就能对其他页面发起请求,旧版的正方系统返回的是Html,所以拿到请求结果后,还要再进行Html的解析,进而筛选出自己所需要的信息。

2.代码实现的总体思路

(1)爬虫、数据解析工具
  • HttpClient:用于像浏览器发起http请求,支持长连接
  • Jsoup:用于解析Html,支持DOM,CSS以及类似于jQuery的操作方法来取出和操作数据
  • 正则表达式:按需求提取字符串的特定部分,也是用于解析Html
(2)项目框架

项目用的是Springboot搭建项目,因为当时简单用Vue搭了个前台,所以数据传输都是用的Json,实现了前后端的分离,主要是用到了Spring的IoC容器管理bean还有控制器类。第三方依赖是用Maven来管理。实际上,这个项目不一定要用SpringBoot,可以根据自己的需要进行迁移。代码包结构如下:

代码包结构

(3)核心类简介
  • GloabalConstant类:全局常量类,存放了所有的请求URL,包括教务系统首页、登录请求地址、验证码请求地址等,这些URL需要根据自己的实际情况进行手动更改,把域名部分换成自己学校正方系统首页的地址就行。另外就是登录页的错误信息,为了方便调试代码,也进行了保存。
  • HttpService类:Http服务类,封装了get请求、post请求,以及HttpClient的初始化,同时所有关于爬取逻辑的代码都是在这个类里,包括登录、验证码获取与识别、课表表获取、成绩表获取等。
  • JavaOCR类:验证码识别类,包括验证码识别的整个过程,**由于验证码识别训练涉及到数据集、测试集、结果集,启动代码时,请根据自己的实际情况,在配置文件执行修改trainSetDirtrainTestDirtrainResultDir这几个目录所在的位置。**验证码识别的训练与使用是分开的,项目运行时只会在HttpService中读取训练结果集,如果要自己进行验证码的训练(理论上测试集验证码图片越多,识别率越高,我总共用了近700张,识别率稳定在62%左右),在src.test.java.*下有代码示例。
(4)配置文件说明

配置文件用的是yml格式,application-dev.yml是开发环境的配置文件,application-prod.yml是生产环境(linux下)的配置文件,可以自定义端口以及JavaOCR目录。

application-dev.yml

application-prod.yml

(5)要注意的细节
  • 在获取Cookies后,以后的每一次请求都要把Cookies带上。

  • 请求时要注意目标请求是否需要Referer。Referer告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理,有网页会限定请求的上一个地址。

3.模拟登录

(1)分析登录页面

我用的Google Chorm,在首页按F12打开浏览器自带的页面审查工具,随便输入学号密码和验证码,点击登录后,浏览器会向服务器提交一个post请求,请求地址为:http://xxxxxxxxxx/default2.aspx。

登录页面请求分析

仔细观察上面的Form Data表单,发现有以下几个关键表单项:

  • __VIEWSTATE:一个隐藏表单项,可以在页面源码中找到
  • txtUserName:学生学号
  • TextBox2:登录密码
  • txtSecretCode:验证码
  • RadioButtonList1:结合登陆页面知,这是身份选项,value值为%D1%A7%C9%FA(”学生”经过以Gb2312格式URL编码后的字符串 )

其他像Textbox1、Button1这些表单项的value值都是空白的,说明在登录中并不起作用。

(2)登陆前的准备:获取cookie和__VIEWSTATE

获取到cookie和__VIEWSTATE后要进行保存,项目中是采用session的方式,存放在服务器端,在之后的请求中,每次请求都要带上cookie,比如获取验证码。HttpService类已经封装好了get请求和post请求,每次请求都会自动带上cookie。

	/**
     * 初始化,主要用于收集cookie和viewState
     */
    public HttpBean init() {
   
        CloseableHttpResponse requestResponse = sendGetRequest(GlobalConstant.INDEX_URL, "");
        String cookie = requestResponse.getFirstHeader("Set-Cookie").getValue();//  获取cookie
        HttpBean httpBean = new HttpBean();
        try {
   
            String html = EntityUtils.toString(requestResponse.getEntity(), "utf-8");
            httpBean.setViewState(getViewState(html));//提取页面表单中的__VIEWSTATE的值
            httpBean.setCookie(cookie);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
        System.out.println("完成初始化,获取到的cookie为" + httpBean.getCookie()
                + ",获取到的viewState为" + httpBean.getViewState());
        return httpBean;
    }

    /**
     * @param html 登录页面源码
     * @return 登录页的__VIEWSTATE
     */
    public String getViewState(String html) {
   
        return Jsoup.parse(html).select("input[name=__VIEWSTATE]").val();
    }
(3)验证码的获取与自动识别
 	/**
     * 获取验证码
     *
     * @return 验证码图片
     */
    public byte[] getCheckImg() {
   
        String url = GlobalConstant.SECRETCODE_URL;
        byte[]
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值