• 软工实践-结对作业2


    福大软工1816 · 第五次作业 - 结对作业2

    分工以及代码规范

    PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 30 30
    · Estimate · 估计这个任务需要多少时间 30 30
    Development 开发 690 960
    · Analysis · 需求分析 (包括学习新技术) 30 240
    · Design Spec · 生成设计文档 30 30
    · Design Review · 设计复审 20 20
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 20
    · Design · 具体设计 30 30
    · Coding · 具体编码 360 450
    · Code Review · 代码复审 30 30
    · Test · 测试(自我测试,修改代码,提交修改) 180 140
    Reporting 报告 110 80
    · Test Repor · 测试报告 30 20
    · Size Measurement · 计算工作量 20 20
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 60 40
    合计 830 1070

    解题思路描述与设计实现说明

    爬虫的使用

    查看了C++的爬虫,差不多是基于WinSocket拿到HTML信息,爬下来再去分析即可,工作量可能不小。

    负责爬虫的队友国庆期间事情有点多,最后没有使用C++来实现爬虫

    • 爬虫环境:Python3.6 Windows 10
    • 爬虫代码链接
    • 使用的库包括requestsbeautifulsoup,其中requests库用来爬取HTML信息,beautifulsoup库用来美化HTML信息并从HTML中查找标签信息
    • 针对CVPR官网网络IO较慢,容易造成爬取中断的问题,使用及时存储方法, 大大增加了爬虫的健壮性
    • 考虑到CVPR多个论文中存在非ASCII码(主要是一些拉丁文)的问题,使用UTF-8编码保存相关信息,解决了部分拉丁文乱码问题

    代码组织与内部实现设计(类图)

    应作业要求,本次代码组织如下

    原谅本人并不认为文件越多就越好,我们的文件虽然少但结构还算清晰(#.#)

    031602345&031602321
    |- src
        |- WordCount.sln
        |- WordCount
            |- stdafx.h             预编译头文件
            |- WordCount.h          定义外部接口
            |- WordCount.cpp        main函数入口
            |- function.cpp         程序内函数的实现
            |- stdafx.cpp           预编译文件
            |- WordCount.vcxproj
    |- cvpr
        |- Crawler.py
        |- result.txt
    
    

    程序调用结构如图

    • 对程序执行过程的解释:

      1. 主程序首先执行参数解析函数
      2. 执行GetWordCountMap()函数,获得词频统计字典。为了减少不必要的文件IO,故在在获取词频统计字典的过程中顺路得到到characters、words、lines信息,并修改g_has_got_mapg_has_got_linesg_has_got_wordsg_has_got_characters四个标志位为True
      3. 由于在获取词频字典的时候已经修改了标志位,程序接下来可以直接获取到words、characters、lines信息,而不需要再读取文件
      4. 执行GetFirstNWords()函数,获取rank前N的单词
      5. 显示结果(输出到文件中)

    说明算法的关键与关键实现部分流程图

    这次的重点应该是带有指定长度的词组词频统计功能,剩下的功能只要在上一份代码的接口上做一些改动即可

    以下是用于实现词组词频的实现过程

    WordCount

    附加题设计与展示

    附加题1:基于英文分词技术的热词分析功能

    • 独到之处:使用英文分词技术,而不是傻大黑粗的指定长度的分词,尽量保留大家感兴趣的专有名词,方便大家看到年度热词(多为专有名词)

    • 实现思路:使用python的textblob库,对每篇论文分析得到英文词组,同时构建一套简单的规则去除一些常见词,进而得到词频统计。数据展示部分使用了seaborn库的功能

    • 实现成果展示:

    附加题2:年度最佳作者排行(基于发布的论文数)

    • 独到之处:你想知道CVPR最大牛的是谁吗?我们可以根据每个作者发表的论文数量,简单分析年度最佳作者。注:能力有限,没有考虑重名的问题(实际上这个问题如果要考虑进去,会变得很复杂)

    • 实现思路:在爬虫中只要把每篇文章的作者跟着爬取下来,根据作者名出现的次数进行排序即可。

    • 实现成果展示:

      附加题3:论文翻译工具(还是个半成品)

      • 独到之处:可以对爬取到的论文进行翻译, 暂时还是个半成品o(╥﹏╥)o

      • 实现思路:这里使用了一个境外服务器来实现翻译

      • 实现成果展示:

    关键代码解释

    头文件中定义的外部接口一览

    其中Init()SetParam()函数是为了能在测试程序中模拟命令行参数而设计的,在程序运行过程中没用

    词组词频统计部分(代码注释中有详细说明每一段代码的功能,其中部分代码被折叠)

    性能分析与改进

    原始的性能分析如图,其中GetFirstWordsGetWordCountMap函数的开销较大

    在查看WordCountMap函数的过程中,发现我本来使用的双端队列的push_back很慢啊,想了想当初干嘛要用双端队列呢,好像没啥用(可能是方便吧),想先改用队列来看一下

    CPU的总计算量从18588下降到了16728(速度提升10%)

    后来又想了想,感觉为啥要用队列呢?直接用两个指针不好吗?然后就开始更改成只用两个指针。不过改的过程中出了BUG,还在修复...等修复完了再更新博客

    程序中消耗最大的函数是GetWordCountMap这个家伙

    GetWordCountMap中占比最大的函数是AddWordWeight这个函数

    AddWordWeight这个函数中,我目前使用的是STL::Map

    在考虑自己手写一个字符串哈希来代替Map的功能,这部分在我改进完后再更新博客

    • 更新性能提升部分的博客

    本来在想自己手写哈希,无意间看到了陈柏涛同学关于unordered_map和map的性能比较这篇博客,突然想起,好像C++的STL里一直都有这个东西的,它就相当于一个使用了开散列的哈希一样,不用我们自己写哈希了。之前我还不知道为什么Dev 以及 CodeBlocks + mingw这样的方案比VC快很多,陈同学在他博客中分析了这个问题,涨了知识,给陈同学一个赞!

    那么接下来就是在我的项目中使用unordered_map来代替map(手写哈希并不难,还是写过几次的,并不是写不出来,等我写出来我会单独开一篇博客来做自己的哈希函数和STL中under_map的对比,尽请期待)

    以下是我使用map得到的性能分析报告,可以发现GetWordCountMap函数的花销比GetFirstNWords的开销还来的大,CPU的总开销大概16419,GetWordCountMap的开销为8281

    下面是我们使用了unordered_map代替map之后的性能分析

    可以看到,不管咋地,GetWordCountMap函数的开销已经比GetFirstNWords函数来的小了,小了很多好嘛!

    然后我们可以看CPU总计信息,从16419下降到了15643(提升4.7%),GetWordCountMap函数的开销从8281下降到了7514(提升9.2%)

    单元测试

    上次因为自己找了很久没找到我VS中的覆盖率分析工具,也怪自己没看到需要至少10组测试样例,吃了没做好单元测试的大亏。这次重新学习VS中单元测试部分,设计了10组测试。

    另外字符统计不应该统计/r,在这个版本中做了修正

    测试模块名 测试描述 预期结果
    EmptyFileTest 打开一个空文件 字符数、有效行数、单词数均为0
    CountCharTest 字符统计测试 字符数中'Title:' 'Abstract: ' 论文编号以及多余换行符不应该被统计
    CharTestForCr 字符测试 字符不应该被统计
    CountLineTest 统计有效行 只统计Title、Abstract打头的有效行
    WordInOtherLineTest 单词统计 用于测试其他行的单词是否被计数 只统计Tiltle、Abstract打头的行内的单词,出现在其它行的单词不予考虑
    WordGroupTest 词组判断测试,参数m设置为3来测一个含有4个单词的词组 理论词组的数量为2
    MultiListWordGroupTest 用于测试程序能否保存住中间的分隔符 需要保存住中间的分隔符
    WordGroupValidTest 词组合法性检查 用于测试中间存在不合法单词时的处理情况 当中间存在不合法单词时不应该组成词组
    WeightTest0 用于测试当m设置为1时title的权重是否改变 Title中的词组的权重应该为10
    WeightTest1 用于测试当m设置为0时title的权重是否为1 Title中的词组的权重应该为1

    测试代码例

    // 包含多个分隔符的词组检查
    namespace MultiListWordGroupTest
    {
    	TEST_CLASS(UnitTest1)
    	{
    	public:
    
    		TEST_METHOD(TestMethod1)
    		{
    			Init();
    			string input_path = "multilistwordgrouptest.txt";
    
    			// 设置词组长度为3
    			vector<map<string, int>::iterator> first_n_words = GetFirstNWords(input_path, 3, 10000);
    
    			/*
    			multilistwordgrouptest.txt文件中的内容为
    			Title: Word1 !  word2 + word3
    			*/
    
    			int number_word_groups = first_n_words.size();
    			// 理论上有1个词组
    			Assert::IsTrue(number_word_groups == 1);
    
    			string word = first_n_words[0]->first;
    			int equal = word.compare("word1 !  word2 + word3");
    			Assert::IsTrue(equal == 0);
    		}
    	};
    }
    

    代码覆盖率测试

    主函数所在的cpp文件的代码覆盖率为100%

    用于实现各个函数的具体功能的function.cpp代码覆盖率有点低,仅为71%,虽然不高但完完全全符合我的预期。覆盖率低主要是由于项目结构导致的,在获取完词频统计字典后,用于获取字符、获取有效行、获取单词总数的函数就不必调用了。可以发现在function.cpp中未被调用的大部分还是这部分函数

    另外由于init和SetParam函数主要是为了测试方便提供出来的接口,在程序运行过程中也没有被调用,和预期结果差不多(要是被调用了那就有鬼了o(╥﹏╥)o)

    Github的代码签入记录

    未能做到代码一有变更就立马上传,因为有时候改BUG的时候改入迷就忘了,所以有的迁入是多个功能一起迁入的,下次一定想办法改进!下次考虑给自己列一个列表,今天要改哪些功能,每改进一个功能就在git上迁入一次。

    遇到的代码模块异常或结对困难及解决方法

    遇到的困难 做过哪些尝试 是否解决 有何收获
    用C++写爬虫 查找有没有前辈写过可供参考的文档,看到了winsocket编程,迫于队友较忙个人时间有限,没有使用C++来编写爬虫 未解决 虽然没啥收获但是有感想
    重新学习Python爬虫 之前还是写过requests、bs4库的,重新学习了一下 解决 还是python做爬虫容易
    爬取过程中由于网络问题爬虫容易失败,失败了又要重来,重来的时候又可能被断掉... 对爬取到的文章做及时存储,已经在本地存在的文章下次就不爬了 解决 增加了点代码量
    附加题中的分词 尝试过nltk库、textblob库,最终使用了textblob库 解决 学到了新库的使用
    附加题分词中,在已经设置仅获取名词的情况下仍然出现了大量如different、learning这样的常用词 观察了词的结构,发现大部分的专有名词还是多个单词的复合,于是自己设置了一套规则,用于屏蔽differet、learning这样的单词 解决但不完美 自己动手解决问题
    附加题中需要做数据展示 接触pandas、matplotlib、seaborn库,学习csv文件的格式 解决但不完美 初步接触python数据分析与展示
    使用matplotlib时x轴标签会被挡住 查了matplotlib的文档以及多篇博客,尝试自己设置bottom属性,暂时只能通过手工调整来解决 未解决
    使用pyinstaller将python转成exe文件过程中报错 谷歌查了很多,还是未能解决这个问题。我成功用pyinstaller转成功了几个程序,只是我们附加题的py程序,暂时无法转成exe程序。 未解决 第一次知道python可以很方便的转成exe程序

    评价我的队友

    • 值得学习的地方:阳光幽默,在学生工作上有责任心
    • 需要改进的地方:可能由于太忙了,在学习上花的功夫不够吧,要多在学习上用心啊!

    个人学习进度条

    第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
    1 1000 1000 30 30 VS进阶操作、人脸识别程序完善
    2 500 1500 35 65 学习Axure RP的基本操作、flask后端框架的学习、与前端对接
    3、4 310 1810 50 115 完善人脸识别程序,配置服务器
    5、6 1320 31310 48 163 VS代码覆盖率插件的使用、英文分词、数据分析与展示、爬虫的复习
  • 相关阅读:
    Android触控屏幕Gesture(GestureDetector和SimpleOnGestureListener的使用教程)
    Cocos发展Visual Studio下一个libcurl图书馆开发环境的搭建
    使用DbUtils实现CRUD
    大约apache 2.4.X虚拟主机配置问题的版本号后,
    应对黑客攻击SQL SERVER数据库中的一个案例
    【Unity技能】做一个简单的NPC
    ViewRootImpl和WindowManagerService笔记
    Web Service简单入门示例
    Oracle Instanc Client安装命令工具
    ListView嵌套GridView显示不完整的解决方案
  • 原文地址:https://www.cnblogs.com/sxZhangYang/p/9768743.html
Copyright © 2020-2023  润新知