软工实践结对第二次作业
在文章开头给出结对同学的博客链接、本作业博客的链接、你所Fork的同名仓库的Github项目地址
给出具体分工
031602441:(2) 自定义输入输出文件;(3)加入权重的词频统计;(4)新增词组词频统计功能;(5)自定义词频统计输出;(6)多参数的混合使用;附加功能 2;单元测试和性能分析; 博客书写
031602408:(1) 使用工具爬取论文信息;附加功能 1,3;博客书写;wordcount测试修改
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分种) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
Estimate | 估计这个任务需要多少时间 | 1710 | |
Development | 开发 | ||
Analysis | 需求分析 (包括学习新技术) | 900 | 1000 |
Design Spec | 生成设计文档 | 10 | 10 |
Design Review | 设计复审 | 10 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 30 | 30 |
Coding | 具体编码 | 600 | 600 |
Code Review | 代码复审 | 10 | 10 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | ||
Test Repor | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 0 | 0 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 | 60 |
合计 | 1710 | 1840 |
解题思路描述与设计实现说明
- 爬虫使用
1.流程图
通过jsoup进行html解析(流程图如上)。
2.关键代码解析:
(1)、传递目标网站url进行连接返回一个Document。
Document document1 =Jsoup.connect(URL)
.header("Accept-Encoding", "gzip, deflate")
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0")
.maxBodySize(0)
.timeout(600000)
.get();
(2)、利用select容器过滤出论文所在链接。
Elements element3 = document1.select("[class=ptitle]");
Elements hrefs = element3.select("a[href]");
(3)、循环传递爬取的论文url并建立连接,返回一个目标论文所在的html页面。
for(Element element6:hrefs){
String url=element6.absUrl("href");
//运用爬取得链接进行二次爬取
Document document2 =Jsoup.connect(url)
header("Accept-Encoding", "gzip, deflate")
.userAgent("Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0")
.maxBodySize(0)
.timeout(600000)
.get();
//解析出想要爬取的内容
(4)、
Elements elements1 = document2.select("[id=papertitle]");
String title=elements1.text();
bi.write("Title: "+title+"\r\n");
Elements elements2 = document2.select("[id=abstract]");
String abstract1=elements2.text();
bi.write("Abstract: "+abstract1+"\r\n"+"\r\n"+"\r\n");
同样适用select()方法过滤出想要的Title及Abstract。
- 代码组织与内部实现设计(类图)
代码组织
031602441&031602222
|- src
|- Main.java(主程序,可以从命令行接收参数)
|- sort.java(排序)
|- export1.java(输出到文件)
|- Readwords.java(提取单词,字符数等)
|- cvpr
|- result.txt(爬虫结果)
|- Main.java(爬虫程序,可以爬取CVPR2018论文列表)
内部实现设计(类图)
- 说明算法的关键与关键实现部分流程图
流程图
算法关键
- 短语是由n个单词组成的,判断短语就是连续判断由字符串某个位置开始的n个单词。记录下字符串中单词的某次判断中上次结束的位置和这次结束的位置,再把字符串两个位置间的数据插到记录词组的字符串里,这样就能录入两个有效单词和他们间的分割符。如果最后确实连续判断了n个单词,则把该词组插入到map中。
附加题设计与展示
设计的创意独到之处
- 1.从网站综合爬取论文的除题目、摘要外其他信息
- 2.分析论文列表中各位作者之间的关系,论文A的第一作者可能同时是论文B的第二作者,不同论文多位作者之间可能存在着联系。对数据的图形可视化做出一些努力,比如对上一条功能可以形成关系图谱
- 3.统计各位作者发表的作品数,并得到发表数排名前十的名单,形成可视化数据。
实现思路
- 1.和之前爬取的过程一样,就是变一下select的内容
- 2.看到那个图的时候真的一脸懵,问了下学姐发现那个图是social network。然后去网上查了下,发现有自动分析的软件,只要生成作者信息的文本,就可以生成社交网路。我选取了Gephi进行操作。爬取出每一篇论文的作者,将文本导入Excel中,再导入Gephi生成作者间的关系图谱。
- 3.在爬取论文Title、Abstract代码的基础上新增Type、Author等信息写入本地文件“result.txt”。
读取result.txt文件分离出作品数排名前十的作者姓名,利用jfreeChart描绘出柱形图。
JFreeChart chart = ChartFactory.createBarChart3D("作者作品数排序", "作者姓名", "论文数", dataset, PlotOrientation.VERTICAL, true, true, true);
实现成果展示
- (1)
- (2)
边缘部分
密集部分
- (3)
关键代码解释
贴出你认为重要的/有价值的代码片段,并解释
String re="";
if(s.length()!=0)
{
if(s.charAt(0)=='T')//title
{
s=s.substring(7);
m = p1.matcher(s);
while(m.find())
{
s4=new StringBuffer();
s1 = m.group();//s1找到第一个单词
m1 = p.matcher(s1);
if(m1.find())//判断单词
{
s1=s1.toLowerCase();
s4.append(s1);//将找到第一个单词插入短语中
s2=s.substring(m.end());//句子中剩下的部分
Matcher m2 = p1.matcher(s2);//找短语其他成分
START1=0;
for(i=1;i<Numflag;i++)//判断短语
{
if(m2.find())
{
String s3=m2.group();//短语第二部分
m1=p.matcher(s3);//判断是否是单词
if(m1.find())
{
END1=m2.end();
re=s2.substring(START1,END1);
re=re.toLowerCase();
//是单词插入短语
s4.append(re);
START1=m2.end();
}
else
{
break;
}
}
else break;
}
if(i==Numflag)//满足短语要求,插入map
{
if(words.get(s4.toString())!=null)
{
words.put(s4.toString(),words.get(s4.toString())+weight);
}
else
{
words.put(s4.toString(),weight);
}
}
}
}
}
具体分析
- 单词判断
之前写个人项目的时候用的不是正则判断而我队友用的是正则,他的代码会比我快很多,所以这次我用的是正则表达式
Pattern p1 = Pattern.compile("[0-9a-zA-Z]+");//字符串
Pattern p = Pattern.compile("(^[a-zA-Z]{4}[a-zA-Z0-9]*)");//单词
p1:提取出由数字和字母组成的字符串
p:判断该字符串是否符合单词要求。
如果两次find()都符合则是单词
- 组成词组
START1=0;
for(i=1;i<Numflag;i++)//判断短语
{
if(m2.find())
{
String s3=m2.group();//短语第二部分
m1=p.matcher(s3);//判断是否是单词
if(m1.find())
{
END1=m2.end();
re=s2.substring(START1,END1);
re=re.toLowerCase();
//是单词插入短语
s4.append(re);
START1=m2.end();
}
else
{
break;
}
}
else break;
}
短语是由n个单词组成的,判断短语就是连续判断由字符串某个位置开始的n个单词。记录下字符串中单词的某次判断中上次结束的位置和这次结束的位置,再把字符串两个位置间的数据插到记录词组的字符串里,这样就能录入两个有效单词和他们间的分割符。如果最后确实连续判断了n个单词,则把该词组插入到map中。
性能分析与改进
描述你改进的思路
- 使用正则表达式判断单词,正则判断流程图如上。
- 使用map录单词
- 在统计频率时,原本想的是记下来每个单词出现的频率后再排序,这样会用到O(N*log N)。在查阅一些资料后,后来才发现可以直接保存频率最高的几个单词,遍历的同时替换就可以了,降到了O(N)。
展示性能分析图和程序中消耗最大的函数
单元测试
展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路
- 思路:正常运行退出返回0
代码覆盖率
贴出Github的代码签入记录
请合理记录commit信息
遇到的代码模块异常或结对困难及解决方法
问题描述
因为个人项目之前用的的是c++,就遇到了很多小问题。。。
- 1.读入文本是乱码
- 2.Junit4和JMC的使用
- 3.字符数统计出错
- 4.gephi环境配置,以及安装了java环境无法识别
做过哪些尝试
- 1.百度发现可以改变文本编码格式 参考资料 Java文件读写操作指定编码方式。。。。。
- 2.百度 参考资料 Java单元测试初体验(JUnit4) Java Mission Control(JMC)介绍
- 3.询问学姐的字符串计数方式
- 4.查阅网上资料,更改了环境变量
是否解决
1,2,4都已解决。3虽然知道了"\r\n"算"\n",但这次字符数结果每个人都不一样。。。不知道对不对。
有何收获
学会了对java程序进行单元测试和效能分析。
评价你的队友
- 优点:随叫随到,查资料能力强。
- 值得学习的地方:在各大论坛找资料能力
- 缺点:有点佛。。。缺乏斗志。。。。
- 需要改进的地方:要有斗志啊少年!
学习进度条
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 6 | 6 | 学会使用git和用markdown编写博客 |
2 | 612 | 612 | 14 | 20 | 学会读写文件,c++单元测试和效能分析 |
3 | 100 | 712 | 6 | 26 | 学会hashmap的使用 |
4 | 0 | 712 | 10 | 36 | 学会墨刀原型设计工具 |
5 | 297 | 1019 | 30 | 66 | 学会使用java以及使用java进行单元测试效能分析;绘制社交网络图;爬取数据 |