一,结对成员
- 分工
我负责写代码,柯同学负责写单元测试。
二,psp
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 10 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 10 |
Development | • 开发 | 1210 | 1670 |
• Analysis | • 需求分析 (包括学习新技术) | 400 | 500 |
• Design Spec | • 生成设计文档 | 10 | 10 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 20 | 20 |
• Coding | • 具体编码 | 500 | 600 |
• Code Review | • 代码复审 | 60 | 120 |
• Test | • 测试(自我测试,修改代码,提交修改) | 200 | 400 |
Reporting | 报告 | 30 | 40 |
• Test Repor | • 测试报告 | 10 | 10 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 20 |
合计 | 1250 | 1710 |
三,解题思路描述与设计实现说明
- 爬虫使用
爬虫我用java实现,一开始找资料的时候在看SeimiCrawler,后来觉得太复杂换了jsoup。
因为有导入外部jar包,为了方便新建了maven工程。
添加pom依赖:
<dependency> <!-- jsoup HTML parser library @ http://jsoup.org/ --> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.10.2</version> </dependency>
接下来是具体实现部分,思路是先爬取每个文章的链接,再逐个爬取每个链接,获取标题和摘要。
package cvpr; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /**爬虫实现 * * @author xyq * @since 2018 10 10 * @version 1.0 */ public class clawler { /**爬取cvpr网站 * * @return Map<String, String> * */ public Map<String, String> getPaperInfo() { Map<String, String> paperInfo = new HashMap<String, String>(); ArrayList<String> htmlLinks = new ArrayList<String>(); String head = "http://openaccess.thecvf.com/";//html链接前半部分 try { Document doc = null ; doc = Jsoup.connect("http://openaccess.thecvf.com/CVPR2018.py#").get(); //Document document = Jsoup.parse(new File("C:/Users/zkpkhua/Desktop/yiibai-index.html"), "utf-8"); Elements links = doc.select("dt a[href]"); for (Element link : links) { //System.out.println("link : " + link.attr("href")); htmlLinks.add(head+link.attr("href"));//得到html链接 //System.out.println(head+link.attr("href")); } } catch (IOException e) { e.printStackTrace(); } try { for (String htmlLink : htmlLinks) { Document doc = null ; doc = Jsoup.connect(htmlLink).get(); Elements titleInfo = doc.select("div#papertitle"); Elements abstractInfo = doc.select("div#abstract"); //System.out.println(titleInfo.text()); paperInfo.put(titleInfo.text(), abstractInfo.text()); } } catch (IOException e) { e.printStackTrace(); } return paperInfo; } public void writeResult() throws Exception { Map<String, String> paperInfo = new HashMap<String, String>(); clawler clawler = new clawler(); paperInfo = clawler.getPaperInfo(); String path = System.getProperty("user.dir")+"\\src\\main\\java\\cvpr\\result.txt"; File file = new File(path); StringBuilder result = new StringBuilder(""); int count = 0; FileWriter filewriter = new FileWriter(file.getAbsoluteFile()); //System.out.println("absolutely path:"+file.getAbsolutePath()); BufferedWriter bufferedWriter = new BufferedWriter(filewriter); for (Entry<String, String> entry : paperInfo.entrySet()) { result.append(count); count++; result.append("\r\n"); result.append("Title:"+entry.getKey()); result.append("\r\n"); result.append("Abstract:"+entry.getValue()); result.append("\r\n"); result.append("\r\n"); result.append("\r\n"); //System.out.println("title: "+entry.getKey()); //System.out.println("abstract: "+entry.getValue()); } bufferedWriter.write(result.toString()); bufferedWriter.close(); } }
UML类图
流程图
关键实现部分流程图
这次的关键在于新增的词组统计功能,一下是实现的流程图。
四,附加题设计与展示
设计的创意独到之处
爬取每篇文章的作者信息,统计各个作者的文章数量。
实现思路
先爬取每篇文章的链接,再对这些链接爬取获取作者的名字,将结果排序输出至文件。
成功展示
五,关键代码展示
/**排序,按权重降序 * * */ private static void sort(ArrayList<HashMap.Entry<String, Integer>> wordList) { Collections.sort(wordList, new Comparator<HashMap.Entry<String, Integer>>() { public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) { if (o1.getValue() < o2.getValue()) { return 1; } else { if (o1.getValue().equals(o2.getValue())) { if (o1.getKey().compareTo(o2.getKey()) > 0) { return 1; } else { return -1; } } else { return -1; } } } }); }
获取命令行参数
/* * 这里先取默认值,因为不是所有参数都会被用户提供 */ String in = " "; String o = " "; int m = 1; int n = 10; int w = 1; long charNum = 0; long lineNum = 0; long wordNum = 0; /* * 设置一个offset变量,用来定位相关信息 */ int optSetting = 0; for (; optSetting < args.length; optSetting++) { if ("-i".equals(args[optSetting])) { in = args[++optSetting]; } else if ("-o".equals(args[optSetting])) { o = args[++optSetting]; } else if ("-m".equals(args[optSetting])) { m = Integer.parseInt(args[++optSetting]); } else if ("-n".equals(args[optSetting])) { n = Integer.parseInt(args[++optSetting]); } else if ("-w".equals(args[optSetting])) { w = Integer.parseInt(args[++optSetting]); } }
六,性能分析与改进&单元测试&签入记录
- 思路
因为第一次测试的结果不理想,知道了是在分词方面出了问题。所以这次的分词部分不再偷懒用自带方法,而是运用了自动机的思想逐字符地拼凑单词。
for(;i < str.length();i++) { //大写字母转为小写字母 temp = str.charAt(i); if ((temp >= 65) && (temp <= 90)) { temp += 32; } if(state == 0) { if ((temp >= 97) && (temp <= 122)) { word.append(temp); state = 1; } }else if (state == 1) { if ((temp >= 97) && (temp <= 122)) { word.append(temp); state = 2; } else { word.setLength(0); state = 0; } }else if (state == 2) { if ((temp >= 97) && (temp <= 122)) { word.append(temp); state = 3; } else { word.setLength(0); state = 0; } }else if (state == 3) { if ((temp >= 97) && (temp <= 122)) { word.append(temp); state = 4; } else { word.setLength(0); state = 0; } }else if (state == 4) { if (((temp >= 97) && (temp <= 122)) || ((temp >= '0') && (temp <= '9'))) { word.append(temp); } else { wordlist.add(word.toString()); word.setLength(0); state = 0; } } } if (state == 4) { wordlist.add(word.toString()); }
- 单元测试
思路就是用白盒测试,事先计算好测试用例的期望值,与输出对比
@Test public void testPhraseFrequency2_1() { phraseFrequencyCounter phraseFrequencyCounter = new phraseFrequencyCounter(); int topPhrasenum = 0; ArrayList<HashMap.Entry<String, Integer>> wordList = new ArrayList<HashMap.Entry<String, Integer>>(); HashMap<String, Integer> wordlistMap = new HashMap<String, Integer>(); wordlistMap = phraseFrequencyCounter.countPhraseFrequency("D:\\java_project\\031602435&031602414\\src\\test\\java\\wordCount2_031602435\\"+"result.txt",1,3); wordList = phraseFrequencyCounter.topFrequentPhrases(wordlistMap); topPhrasenum = wordList.get(0).getValue(); assertEquals(97, topPhrasenum); } @Test public void testWordNum1() { wordNumberCounter wordNumberCounter = new wordNumberCounter(); long wordnum =wordNumberCounter.countWord("D:\\java_project\\031602435&031602414\\src\\test\\java\\wordCount2_031602435\\"+"text1.txt"); System.out.println(wordnum); assertEquals(9, wordnum); } @Test public void testPhraseFrequency1_1() { phraseFrequencyCounter phraseFrequencyCounter = new phraseFrequencyCounter(); int topPhrasenum = 0; ArrayList<HashMap.Entry<String, Integer>> wordList = new ArrayList<HashMap.Entry<String, Integer>>(); HashMap<String, Integer> wordlistMap = new HashMap<String, Integer>(); wordlistMap = phraseFrequencyCounter.countPhraseFrequency("D:\\java_project\\031602435&031602414\\src\\test\\java\\wordCount2_031602435\\"+"text1.txt",1,3); wordList = phraseFrequencyCounter.topFrequentPhrases(wordlistMap); topPhrasenum = wordList.get(0).getValue(); assertEquals(11, topPhrasenum); }
- commit记录
这次的用时虽然有20多小时,但是完成总时间是在两天半(不包括学习技术)。。所以只有一条记录。
七,遇到的代码模块异常或结对困难及解决方法
- 问题
一开始没接触过爬虫,不知道怎么使用 - 尝试
找资料,看博客,按上面的方法摸索,结合着看文档。 - 是否解决
已经解决 - 收获
学习到了爬虫的简单使用
八,评价队友
认真负责
九,进度
java:2->2.4
自主学习能力:2->2.6
来源:https://www.cnblogs.com/daydreams/p/9781184.html