简单的爬虫爬取教务网获取成绩

看到过一篇文章介绍爬虫,想着可以用爬虫上教务网爬取期末成绩,利用闲着的时间仔细研究了一下Java爬虫,发现网上很少用Java写爬虫,很多都是python,没有接触过这个语言,不做过多的评价。通过进一步的查询得到一个重要的信息,Java有一个专门处理网页源代码的类,这不就是写爬虫的重点吗,通常Java写爬虫用到的有Jsoup解析网页源代码。


对于需要登录才能访问数据的网站,一般情况下,当登录上网站的时候,用户会获取一个cookie,之后访问每个网页都会带着cookie,验证是否是该用户登录,可以获得数据。


刚刚开始爬取教务网的时候,登录就是个难题,一般登录的时候,访问的网址后面会带着用户名和密码,但是登录的时候只是一个网址,后来通过浏览器的查看元素的功能(博主用的是火狐浏览器,谷歌也可以)分析出,登录的时候,其实是带着好几个消息访问,其中就有用户名密码,通过查看登录网页的源代码,知道了表单输入框的name属性值,一切就迎刃而解了,只需要在登录的网址后面加上name属性值就可以登录进去。弄清楚登陆的时候,向下进行的时候走了很多的弯路,最后才弄明白,需要带着cookie,通过查看浏览器提供的消息,看到每次访问时候,都会带着cookie,我们用Java提供的类,获取到cookie,这样访问的时候服务器就可以验证用户登录了。利用好浏览器观察每次访问的网址。

本项目成型于一个月前,之前爬了所有学期成绩,经过修改变成了查本学期的。


jsoup-1.7.3.jar 下载:http://download.csdn.net/detail/qq_38663729/9909625

用到了一个Degree实体类,存科目名称和成绩

package demo_select;

public class Degree {
    public String name;
    public String degree;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDegree() {
        return degree;
    }

    public void setDegree(String degree) {
        this.degree = degree;
    }

    @Override
    public String toString() {
        return "Degree{" +
                "name='" + name + '\'' +
                ", degree='" + degree + '\'' +
                '}';
    }
}

下面的代码,我会把网址去掉,提供的只是一个思路,其实爬虫重要的是分析,利用好浏览器查看每次访问的网址,以及访问的时候带着的信息,其实不难。

package demo_select;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

public class Ben {

    public static void main(String[] args) throws UnsupportedEncodingException,
            IOException {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入学号:");
        String zjh = sc.next();
        // String mm = sc.next();
        // 带着用户名密码获取cookie,否则后面的网页不能验证,报空指针
        String surl = "http://*****************?zjh=" + zjh
                + "&mm=*******";
        // 创建url对象,就是可以理解打开网址
        URL url = new URL(surl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 获取cookie,由于网站不知道什么bug后面总是跟一个分号和path,所以截取
        int i = (connection.getHeaderField("Set-Cookie")).indexOf(";");
//        System.out.println(connection.getHeaderField("Set-Cookie"));
        String cookieVal = (String) (connection.getHeaderField("Set-Cookie"))
                .subSequence(0, i);
        // System.out.println(cookieVal);
        // 带着cookie打开成绩的网页
        String s = "http://60.219.165.24/bxqcjcxAction.do";
        // 重新打开一个连接
        url = new URL(s);
        HttpURLConnection resumeConnection = (HttpURLConnection) url
                .openConnection();
        if (cookieVal != null) {
            // 发送cookie信息上去,以表明自己的身份,否则会被认为没有权限
            resumeConnection.setRequestProperty("Cookie", cookieVal);
        }
        resumeConnection.connect();
        // 现在通过输出流对象构建对象输出流对象,以实现输出可序列化的对象。
        InputStream urlStream = resumeConnection.getInputStream();
        // 由于网站html代码中有中文,所以不能使用字节流,转换成字符流处理
        InputStreamReader u = new InputStreamReader(urlStream);
        int j = 0;
        StringBuffer str = new StringBuffer();
        while ((j = u.read()) != -1) {
            str.append((char) j);
        }
        /**
         * 利用Jsoup解析html网页,Jsoup可以打开一个网页获取html代码解析,也可以直接解析网页html的字符串
         * 用Jsoup类中的选择方法筛选标签
         *
         */
        String html = str.toString();
        Document doc = Jsoup.parse(html);
        Elements links = doc.select("tr[class]");
        // 解析成节点数组遍历筛选符合条件的标签,取值
        List list = null;
        Set<String> set = new HashSet<String>();
        for (Element link : links) {
            //一个节点的所有孩子节点是一个集合
            list = link.childNodes();
            for (int i1 = 0; i1 < list.size(); i1++) {
                //通过解析网页源代码得到的每个节点前面或者后面都带有不相关的字符床,需要截取
                Degree d = new Degree();
                String name = list.get(5).toString();
                String degree = list.get(13).toString();
                int begin = name.indexOf(">");
                int end = name.lastIndexOf("<");
                int begin1 = degree.indexOf(">");
                int end1 = degree.lastIndexOf("<");
                d.setName(name.substring(begin, end));
                d.setDegree(degree.substring(begin1 + 1, end1));
                set.add(d.toString());
            }
        }
        for (String string : set) {
            System.out.println(string);
        }
    }
}

posted @ 2017-11-10 21:29  In_new  阅读(1719)  评论(0编辑  收藏  举报