第二次结对作业:班级成绩表

作业要求 https://edu.cnblogs.com/campus/fzzcxy/2018SE2/homework/11248
作业目标 <由网页解析数据并累加,进行排序>
作业源代码 https://gitee.com/chenbartender/pair
陈少龙 <211806306>
黄龙骏 <211806386>

结对过程

由于是舍友也是要好的朋友,这使得我们的交流十分的轻松且方便,再加上在上一次的结对作业中,我们对彼此的合作十分满意,也取得了还算不错的成绩,所以这一次我们决定延续上一次的结对,希望能取得更好的成果。

时间统计

  • 需求分析:1.5小时

  • 编码时间:7小时

  • 代码行数:167行

需求分析

在对本次作业的要求进行分析后,我们制作出了如下的思维导图

这样一来,需要解决的问题就显而易见了

  1. 从网页爬取数据

  2. 获取全班同学的学号,姓名,经验值

  3. 进行累加获得总经验值

  4. 进行排序,计算出最高分,最低分和平均分

接下来,就是一个一个的去解决问题了

编码过程

*获取全班同学的学号,姓名,经验值

为保证能够准确地获取到以上信息,我们先将html文件保存到了本地进行提取

在这一次的作业中我们仍然使用Jsoup进行提取,由于云班课网页的代码格式相同,我们先使用class选择器选择出每个同学信息所在的类

Elements allel = all.getElementsByClass("homework-item");

然后找到class中对应的姓名,学号所在的子节点,使用text()函数将其进行类型转换并输出

   Element name = allel.get(i).child(0).child(1).child(0); //获取姓名
   Element num = allel.get(i).child(0).child(1).child(1); //获取学号
   String textname = name.text();
   String textnum = num.text();

这样就完成了姓名和学号的提取

然后找到经验值所在的子节点,但在提取时我们发现,没有提交作业的同学和没有被评分的同学在这个子节点的数值是不一样的

对于有分数的同学,我们采用replaceAll的函数处理字符串,然后将其转换为整型

text2=text2.replaceAll("分","").replaceAll(" ","");
int text3 = Integer.parseInt(text2);

对于没有分数的同学,直接将值设置为0,并转换为整型,方便后续的成绩计算

if(text2.contains("尚无评分")||text2.contains("批注")) {
	text2="0";
	int text3=Integer.parseInt(text2);
	System.out.println(text3);
}

这样就完成了成绩的提取

*获取网页url和使用cookies登录

我们采用了使用cookies进行登录的方法,虽然这个方法需要经常更换cookies,但是不用考虑页面是否有验证码的问题,还是具有一定实用性的

直接从页面f12获取cookie之后,就可以十分简单快捷的使用cookie登录了

Document index = Jsoup.connect(url).header("Cookie", cookiexx).get();// 设置cookies

然后使用和第一次编程作业一样的方式,使用类名选择器获得课堂完成部分的类,再从中选择到它们的url

Elements textall = index.getElementsByClass("interaction-row");//提取所有作业

每个课堂完成部分作业的url其实就是data-url的部分,直接将其获取即可

Element NowDiv = NowUrl.select("div").first();
String NextUrl = NowDiv.attr("data-url");

按照我们本来的想法,在这一步只要按照上面的方法爬取学号、姓名、学号即可,但是却出现了意外

姓名学号只爬取了一部分就结束,并且还报了错,在之前的测试中,这种错误一般是在子节点选取错误时才会出现,但是无论本地解析还是url解析,网页的源代码结构按理说时不会变的,于是我们就请教了万能的百度,果然

解决问题的方法也很简单,将使用Jsoup的解析网页函数稍作改变即可

Document index = Jsoup.connect(url).header("Cookie", cookiexx).maxBodySize(Integer.MAX_VALUE).get();

到这里就完成了对信息的提取部分,接下来就是解决存取和排序的问题

*存储信息以及排序计算最大最小值、平均值

对于如何存储学生信息的问题,我们展开了激烈的讨论,想过使用数组、链表进行存储,但最后我们决定使用集合来实现

先创建一个Students的POJO类,定义StudentName, StudentNum, StudentScore三个基本参数,然后存储数据即可

而在对任意一次作业进行遍历过后,我们就已经可以得到所有学生的姓名,学号和单次成绩,在之后的遍历中,只需要将姓名学号进行比对,就可以实现成绩的累加

for(Students stu:stulist) {//遍历集合
if (stu.getNumber().equals(StudentNum)) {//用学号来获取集合中学号相同的位置
stu.setScore(stu.getScore()+StudnetScore);//将该分数加入该学生的成绩中
sum+=StudnetScore;//累加全班成绩
}

完成上述部分后,使用sort函数即可进行排序,排序完成后第一个集合即为最高经验值,最后一个即为最低经验值,直接输出即可

而平均值,在每一次计算经验值时设置一个变量进行累加,最后再除以全班人数即可

*输出为txt文件

这一过程相对简单,创建好txt文件后定位文件位置,再更改输出目标后即可输出

PrintStream pStream = new PrintStream("D:\\Javaworkp\\Team\\score.txt");//定位txt文件位置
System.setOut(pStream);//更改输出目标为txt文件

*到这一步,这一次作业要求的功能都已经基本实现,我们重新整理了一下所需要的流程:

然后我们将每一个制作完成的零件拼装在一起,就顺利的完成了本次作业

commit记录

结对照片

由于国庆放假我们都选择了回家,所以我们采用屏幕共享和远程协助的方式进行讨论和编写代码

结对感受

本次的结对作业由于涉及了代码部分,本身难度就高于上次的原型设计,而两个人共同完成一份代码,考验的也不仅仅是编程能力,对我们的交流能力,写作能力更是很大的挑战。与上次结对相同,本次作业我们并没有太明确的分工,作业的每一项任务我们都是共同参加,共同付出努力来完成。这一次的结对过程我们也都十分满意,若还有下次结对我们会再接再厉。

结对评价:

对陈少龙同学的评价:陈少龙同学对于学习的认真程度我一直看在眼里,在结对的过程中积极思考,遇到问题不气馁,积极寻求解决办法,并且执行力满分,是非常令人满意的结对伙伴。

对黄龙骏同学的评价:黄龙骏同学善于思考,提出问题且善于总结。在这次结对的过程中给了我许多帮助和鼓励,期待下一次和他合作。

一些心得:

这一次的作业其实可以算是第一次个人编程作业的升级版,除了多出了几个功能外,总体来说没有非常大的区别,难度也没有到完成不了。我们都有认真对待上一次的个人编程作业,所以在完成这次作业时也使用到了上次编程作业的方法,这让我们感受到每一次踏实学习的收获,都是一次次的积累,在以后的学习中我们会更加的认真。

资料网站:

jsoup 获取文档不全的解决方法
ArrayList用法解析与遍历
将Java程序的输出结果写到txt文件中的方法
posted @ 2020-10-03 21:27  icen  阅读(289)  评论(0编辑  收藏  举报