文章目录

  • 一、项目概述
    • 1、效果展示
    • 2、核心技术
    • 3、设计思想
  • 二、诗词数据获取部分
    • 1、请求和解析列表页
    • 2、请求和解析详情页
    • 3、SHA256算法去重
    • 4、计算分词
    • 5、存入数据库
  • 三、数据可视化部分
    • 1、前端页面渲染工具echatrs
    • 2、RankServler处理作者作诗数
    • 3、wordServlet提供给前端处理用词统计
    • 4、前后端交互jQuery
  • 四、项目改进办法
    • 1、原始方法单线程
    • 2、改进方法一多线程
    • 3、改进方法二线程池
  • 五、对项目的具体测试
    • ①功能测试
    • ②性能测试
    • ③界面测试
    • ④兼容性测试
    • ⑤安全性测试
    • ⑥易用性测试

文章较长,想看哪儿请直接点目录

先奉上源码链接项目源码

一、项目概述

1、效果展示

先来看一下项目最终的效果什么样子的,从项目名称可以看出来这个项目是对唐诗的数据进行分析,实现两个功能,也就是我们的需求
功能一:图一这样,以作者创作数量的大小进行排序
功能二:将作者用的高频词汇统计出来,看看古人爱用哪些词
最终用户看到的就是一个分析好的结果。

2、核心技术

①、第三方库的使用,比如HtmlUtil、Servlet、ansj_seg等
②、JavaEE,JAVA和数据库的综合英勇
③、多线程和线程池的理解使用
④、SHA256去重算法
⑤、HTTP协议
⑥、echarts、jQuery、ajax前端展示的使用
⑦、GSON数据格式
⑧、软件测试的基本思想应用
⑨maven的使用
为什么选择maven开发?

1、maven一个命令就可以完成项目构建过程
2、他可以进行强大的依赖管理
3、可以分阶段进行构建
4、提供web项目的模式

3、设计思想

想一下现在需求明确了,就该着手去考虑怎么下手做,我要分析数据,那数据从哪儿来?往哪儿存?怎么存?这是第一个大方面;第二个方面,我有数据了,那用户会去看你找到的数据吗?用户是最懒得,他只想看到上图统计好的结果,那问题来了,怎样展示?所以就可以分为两大模块去做,数据获取和数据展示。

数据的来源应该是公开的,就比如我们不能去获取教务系统存的学生信息,所以选择唐诗三百首,这里的诗词信息都公开
我是要把数据存的数据库,所以表怎么建,要是存进来的数据重复了怎么处理?要统计高频词的前提是知道怎样分词?存进来了怎么让前端获取数据去可视化。

二、诗词数据获取部分

请求列表页->解析列表页->下载详情页->解析详情页->想办法去重->计算分词->存入数据库

1、请求和解析列表页

引入HtmlUnit这个第三方库来帮我们解析,它是一个无界面的浏览器,它自带http客户端,给他一个url,它就会去请求页面。用它里面的webclient类,就可以完成请求和解析,从列表页里筛选我们需要的标签进入详情页,它的一些api使用案例里面有

<dependency><groupId>net.sourceforge.htmlunit</groupId><artifactId>htmlunit</artifactId><version>2.36.0</version></dependency>

HtmlUnit使用案例

public class HtmlUnitDemo {public static void main(String[] args) throws IOException {//无界面的浏览器(HTTP客户端),假装自己是谷歌浏览器WebClient webClient=new WebClient(BrowserVersion.CHROME);//可能第三方库里写的css和js不标准,运行会报警告,所以先关了。关闭浏览器css执行引擎webClient.getOptions().setCssEnabled(false);webClient.getOptions().setJavaScriptEnabled(false);//把url放进去,它会返回HtmlPage类型的数据HtmlPage page = webClient.getPage("https://so.gushiwen.org/gushi/tangshi.aspx");//保存列表页html文档,放到文件里page.save(new File("唐诗三百首\\列表页.html"));//html的bodyHtmlElement body=page.getBody();//筛选包含我们所需内容的标签,保存标签的内容,3个参数:元素名称,标签名称。标签值,List<HtmlElement> elements = body.getElementsByAttribute("div","class","typecont");HtmlElement divElement = elements.get(0);List<HtmlElement> aElement = divElement.getElementsByAttribute("a","target","_blank");//一个详情页的URLString str=aElement.get(0).getAttribute("href");}
}

2、请求和解析详情页

跟上面的道理是一样的,用HtmlPage/HtmlElement,这次用Xpath来获取

标题xpath="//div[@class='cont']/h1/text()";
朝代   (第一个 a 标签,下标从一开始)
xpath="//div[@class='cont']/p[@class='source']/a[1]/text()";
作者 (第二个 a 标签)
xpath="//div[@class='cont']/p[@class='source']/a[2]/text()";```
正文xpath="//div[@class='cont']/div[@class='contson']";

3、SHA256算法去重

public class SHA256Demo {public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {MessageDigest messageDigest=MessageDigest.getInstance("SHA-256");String s="你好世界";//转成字节数组,通过update传进去,调用digestbyte[] bytes = s.getBytes("UTF-8");messageDigest.update(bytes);byte[] result = messageDigest.digest();System.out.println(result.length);for (byte b : result) {System.out.printf("%02x",b);}System.out.println();}
}

4、计算分词

引入第三方库,给它一句话,可以帮你分成词,而且使用很方便,AnsjSeg提供了四种分词调用的方式:基本分词(BaseAnalysis)、精准分词(ToAnalysis)、NLP分词(NlpAnalysis)、面向索引分词(IndexAnalysis) NLP分词方式是未登录词,但速度较慢:

<dependency><groupId>org.ansj</groupId><artifactId>ansj_seg</artifactId><version>5.1.6</version></dependency>
public class DetailPartDemo {public static void main(String[] args) throws IOException {try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {webClient.getOptions().setCssEnabled(false);webClient.getOptions().setJavaScriptEnabled(false);String url = "https://so.gushiwen.org/shiwenv_45c396367f59.aspx";HtmlPage page = webClient.getPage(url);//url传进去得到body部分HtmlElement body = page.getBody();/*List<HtmlElement> elements = body.getElementsByAttribute("div",//输出正文对应的id"class","contson");for (HtmlElement element : elements) {System.out.println(element);}System.out.println(elements.get(0).getTextContent().trim());//输出正文内容*/// 标题  朝代 作者 正文{String xpath = "//div[@class='cont']/h1/text()";Object o = body.getByXPath(xpath).get(0);//取第一个就行DomText domText = (DomText) o;//文档对象树System.out.println(domText.asText());}//1就代表第一个 a[1]{String xpath = "//div[@class='cont']/p[@class='source']/a[1]/text()";Object o = body.getByXPath(xpath).get(0);DomText domText = (DomText) o;System.out.println(domText.asText());}{String xpath = "//div[@class='cont']/p[@class='source']/a[2]/text()";Object o = body.getByXPath(xpath).get(0);DomText domText = (DomText) o;System.out.println(domText.asText());}{String xpath = "//div[@class='cont']/div[@class='contson']";Object o = body.getByXPath(xpath).get(0);HtmlElement element = (HtmlElement) o;System.out.println(element.getTextContent().trim());}}}
}

5、存入数据库

分为建库建表在连接,要完整的描述一首诗,肯定要有作者、朝代、标题、正文、分词这些信息,连接数据库我们引入第三方库来连接

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>


到这里数据获取部分就算是完成了

三、数据可视化部分

1、前端页面渲染工具echatrs

一个免费的js可视化库,上面的项目效果就是它做出来的。写起来简单,这个项目比较简单,基本碰不上它的bug,支持国产

2、RankServler处理作者作诗数

提供一个接口给前端处理作者作诗数的统计

<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency>
public class RankServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json; charset=utf-8");//用的get方法String condition = req.getParameter("condition");if (condition == null) {condition = "5";}JSONArray jsonArray = new JSONArray();try (Connection connection = DBConfig.getConnection()) {String sql = "SELECT author, count(*) AS cnt FROM tangshi GROUP BY author HAVING cnt >= ? ORDER BY cnt DESC";//把作者全部统计出来try (PreparedStatement statement = connection.prepareStatement(sql)) {statement.setString(1, condition);try (ResultSet rs = statement.executeQuery()) {while (rs.next()) {String author = rs.getString("author");int count = rs.getInt("cnt");JSONArray item = new JSONArray();item.add(author);item.add(count);jsonArray.add(item);System.out.println(author+":"+count);}resp.getWriter().println(jsonArray.toJSONString());}}} catch (SQLException e) {e.printStackTrace();JSONObject object = new JSONObject();object.put("error", e.getMessage());resp.getWriter().println(object.toJSONString());}}
}在这里插入代码片

3、wordServlet提供给前端处理用词统计

public class WordServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws  IOException {String condition=req.getParameter("condition");if(condition==null){condition="5";}HashMap<String,Integer>map=new HashMap<>();Connection connection = DBConfig.getConnection();String sql="SELECT word FROM tangshi";PreparedStatement statement=null;try {statement = connection.prepareStatement(sql);ResultSet rs = statement.executeQuery();while (rs.next()){String word=rs.getString("word");String[] split = word.split(",");for (String s : split) {int count=map.getOrDefault(s,0);map.put(s,++count);}}// System.out.println(map.toString());} catch (SQLException e) {e.printStackTrace();JSONObject object = new JSONObject();object.put("error", e.getMessage());resp.getWriter().println(object.toJSONString());}finally {DBConfig.close(connection,statement);}JSONArray jsonArray=new JSONArray();for (String s : map.keySet()) {JSONArray item=new JSONArray();item.add(s);item.add(map.get(s));jsonArray.add(item);}resp.setContentType("application/json ; charset=utf-8");resp.getWriter().println(jsonArray.toJSONString());System.out.println(jsonArray.toJSONString());}
}

4、前后端交互jQuery

利用$.ajax()发起一个HTTP请求,后台收到请求时返回给前端一个index.html文件,这个文件里面的Script标签又会主动向后台发送http请求,得到json格式的数据,js中的代码把数据写到echart中,页面就展示出来了也引入第三方库,js请求交给相对应的servlet去处理(创作数量排行榜用RankServlet()去处理,诗词用词云图用wordServlet()去处理)
这里也引入servlet第三方库

 <dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency>在这里插入代码片

四、项目改进办法

1、原始方法单线程

所有工作只有主线程一个人在做,线程安全但速度太慢了

2、改进方法一多线程

增加速度,列表页的请求和解析整个项目只执行一次,所以放在主线程中去做而;详情页的请求和解析需要执行320次,在多线程中去做,同理提取诗词信息(标题,作者,内容)、计算 sha256 的值、计算分词、信息插入数据库等步骤放到多线程中去做
引入的问题:线程不安全,webclient messagedigest ,preparedstament、datasource都线程不安全,加锁的话达不到高效率的目的,所以让每个线程建立自己的对象,

3、改进方法二线程池

线程池可以减少线程创建和销毁的次数,但线程池中的线程不会结束,因为jvm在所有非后台线程都结束后才会结束,我们用CountDownLatch,在主线程中调用countDownLatch,作为参数传给线程,调用pool.shutDown();让线程池结束

五、对项目的具体测试

①功能测试

1、点击创作数量排行榜,页面正常显示,如上图
2、二次点击创作数量排行榜,同名次的人会被替换
3、点击诗词用词云图,页面正常显示
4、多次点击诗词用词云图可将所有字展示出来
5、没有网络时,功能不可用
6、运行过程中关闭tomcat,显示失败
7、获取数据部分写完运行可以存进数据库
8、数据的过滤清洗得到了预期的结果
9、数据库异常时访问失败
10、统计到得到诗人作诗数量经测试一致
11、在进行结果分析时断网
12、超过数据库字段设置的最大长度会报错
13、多次启动爬取数据会报错
14、爬的过程中执行truncate table

②性能测试

1、响应时间都、在三秒以内,符合358原则
2、单线程版本数据从爬取到插入数据库需要38秒
3、多线程版本数据从爬取到插入数据库需要5秒
4、线程池版本数据从爬取到插入数据库需要4秒
5、多个用户同时点击时,系统会不会崩溃

③界面测试

1、页面排版符合预期效果
2、页面字体大小是否合适
3、页面的整个布局是否合理
4、界面按钮在预期位置
5、页面文字显示正确

④兼容性测试

1、在谷歌浏览器可正常显示
2、在搜狗浏览器可正常显示
3、在IE浏览器可正常显示
4、在火狐浏览器可正常显示
5、在linux环境下可运行
6、在win7环境下可运行
7、在winxp环境下可正常显示
8、手机可正常显示
9、每一个浏览器的不同版本也要测试
10、在苹果系统运行正常

⑤安全性测试

1、数据库方面的安全
2、反爬虫方面

⑥易用性测试

1、不能用上下左右键操作功能切换,对没有鼠标的人不方便
2、页面功能按钮设计直观,用户很容易理解
3、输入一个简单的url就可以展示结果

【唐诗分析器】实现思想代码+具体测试相关推荐

  1. mysql 查询分析器中使用if_查询分析器中开发代码测试检查_MySQL

    如果您像我一样,则可能已经花费了很多时间在查询分析器中开发代码.在您对代码感到满意之后,可以立即对开发服务器上的测试数据库运行一个或两个专设 测试.如果看起来没有什么问题,您便可以将代码投入生产.如果 ...

  2. 代码运行时间测试C++

    代码运行时间测试 #include<iostream.h> #include<time.h> void main() {clock_t start,finish;double ...

  3. 【camera】自动泊车-基于深度学习的视觉车位检测项目(课程设计--训练代码、测试代码、部署demo)(2)

    **基于深度学习的点定位回归和角度预测的车位检测 基于深度学习的点定位回归和角度预测 基于深度学习的角点检测和角度回归 ** 项目下载地址:训练代码.测试代码.部署demo 数据集百度网盘下载:数据集 ...

  4. TDD代码驱动测试基础

    测试驱动开发(TDD)知识调研 文章目录 测试驱动开发(TDD)知识调研 TDD的核心目标 处理遗留代码问题的核心法则如下. 不良测试的死亡漩涡(亦称为 SCUMmy 周期) 警惕撤回迈入死亡漩涡的步 ...

  5. 为数据访问代码编写测试–不测试框架

    当我们向数据访问代码编写测试时,是否应该测试其公共API的每种方法? 一开始听起来很自然. 毕竟,如果我们不对所有内容进行测试,那么如何知道我们的代码可以按预期工作呢? 这个问题为我们提供了重要的线索 ...

  6. mvn编写主代码与测试代码

    maven编写主代码与测试代码 3.2 编写主代码 项目主代码和测试代码不同,项目的主代码会被打包到最终的构件中(比如jar),而测试代码只在运行测试时用到,不会被打包.默认情况下,Maven假设项目 ...

  7. android 传感器ceshi,Android代码-传感器-测试手机支持那几种传感

    Android代码----传感器-----测试手机支持那几种传感 一个小小Demo检测手机支持那几种传感: 具体代码如下: [Java代码]DemoSensorActivity.java packag ...

  8. SAP开源Java SCA工具,提供静态代码安全性测试功能

    SAP发布了Vulnerability Assessment Tool的源代码,这是一个软件组合分析(SCA)工具,已经在内部测试了两年,对600多个项目进行了20,000次扫描. Vulnerabi ...

  9. 测试用什么编译java代码_java – 测试编译器

    我参与了一个项目,其中Java AST被翻译成另一种语言OpenCL,使用Eclipse编译器,并且有类似的问题. 我没有为你提供神奇的解决方案,但我会分享我的经验以防万一. 您使用预期输出(使用ou ...

最新文章

  1. autoware加载地图数据与使用rosbag包建图(三)
  2. 比特币现金(BCH)独立日一周年庆!里程碑一览!
  3. Windows下以Local模式调试SparkStreaming的WordCount例子
  4. Java小结(五)——进制转换
  5. Ubuntu 16.04下使用gcc输出汇编的.0文件为可执行文件时出现:`_start'被多次定义
  6. 安卓学习笔记---Activity
  7. 数据导入时遭遇 ORA-01187 ORA-01110
  8. _event_phase_team
  9. Charles配合手机模拟器抓取APP数据包教程
  10. 个人如何申请支付宝支付接口(免签约支付)
  11. java 异常 ppt_Java程序设计基础与实践 第6章 异常处理.ppt
  12. 隧道代理ip使用流程
  13. lanczos bidiagonalization(1)
  14. AGC012 - E: Camel and Oases
  15. autosar中bsw架构组成_AUTOSAR架构深度解析
  16. 聊聊SQL语句中 DDL 、DML 、DQL 、DCL 分别是什么
  17. 【系统管理】清理任务栏的已删除程序的图标缓存
  18. 【elasticsearch】search type 含义与使用
  19. STM32F407ZGT6单片机连接ST_LINK和USB转TTL的接线方法+舵机接线方法
  20. 用python给游戏加上音效_pygame游戏之旅 添加icon和bgm音效的方法

热门文章

  1. php(magento),magento在本地php7上安装方法
  2. iOS开发中的锁实现猜测
  3. 8 . STM32固件库介绍
  4. expect 中的回车和换行
  5. 82.【LibraryManger】
  6. 苹果6运行内存是多少_安卓手机12GB运行内存为何打不过苹果的4GB?有哪些原因?...
  7. Renix签名字段详解——网络测试仪实操
  8. 红米NOTE8PRO拍照技巧
  9. 推荐 6 个本月 yyds 的开源项目
  10. 网站频繁抓取IP被封