基于爬虫技术的新闻分类检索系统
实践报告
目录
目录
背景:随着互联网的迅速发展,新闻和信息的数量不断增加,用户需要一种有效的方式来浏览和查找感兴趣的新闻文章。然而,传统的新闻网站和搜索引擎在新闻分类和检索方面存在一些限制。本项目的背景是开发一个新闻分类检索系统,利用爬虫技术从互联网上获取新闻文章,对其进行自动分类,然后提供用户友好的界面来实现高效的新闻检索。
项目目标:本项目的主要目标是开发一个功能强大的新闻分类检索系统,以提供以下功能:
1.新闻爬取:利用网络爬虫技术从多个新闻网站获取新闻文章的文本数据,并且每隔一段时间就进行网站更新。
2.自动分类:利用自然语言处理(NLP)和机器学习技术,自动将新闻文章分类到相关的主题或类别中。
3.用户界面:提供用户友好的网页界面,使用户能够轻松查找和筛选新闻文章。
4.高效检索:开发高效的新闻检索引擎,支持关键字搜索、时间筛选和分类检索。
1.2 需求分析
1.用例图设计
基于爬虫技术的新闻分类系统用例图
2.用例说明
系统用户用例分析
用户用例分析
系统用户用例图
用户拥有注册登录,新闻浏览,新闻检索的功能。
(1)登录模块是适用于所有用户的,用例如表3-2所示。
表1-2 登录模块用例说明表
用例编号 | 001 |
用例名称 | 登录 |
角色名 | 用户 |
用例说明 | 用户在登录界面输入用户名密码进行登录 |
前置条件 | 无 |
基本流程 | 1、在对应框输入用户名密码 2、用户点击登录 |
后置条件 | 点击按钮后进入具体功能界面 |
(2)注册模块也是适用于所有用户的,用例如表3-2所示。
表1-3 注册模块用例说明表
用例编号 | 001 |
用例名称 | 注册 |
角色名 | 用户 |
用例说明 | 用户在注册界面输入用户名密码进行注册 |
前置条件 | 无 |
基本流程 | 1、在对应框输入用户名密码 2、用户点击注册 |
后置条件 | 点击后进入登录界面进行登录 |
(3)新闻浏览模块根据指定条件查询相关新闻。
表1-4 新闻里浏览模块用例说明表
用例编号 | 001 |
用例名称 | 新闻浏览 |
角色名 | 用户 |
用例说明 | 用户在首页可输入查询条件进行新闻查询 |
前置条件 | 无 |
基本流程 | 1、在对应框输入新闻标题、新闻来源、发布日期 2、用户点击搜索 |
后置条件 | 点击后可查询相关新闻内容 |
(4)新闻检索模块可以检索到指定分类的所有新闻列表。
表1-5新闻分类检索用例说明表
用例编号 | 001 |
用例名称 | 新闻分类检索 |
角色名 | 用户 |
用例说明 | 用户在分类搜索界面进行新闻分类检索 |
前置条件 | 无 |
基本流程 | 1、点击对应分类类别按钮 |
后置条件 | 点击后可浏览按指定分类检索到的新闻 |
系统管理员用例分析
系统管理员用例图
根据用例图,系统管理员负责的功能模块,以用例表进行说明:
(1)登录模块是适用于所有用户的,用例如表3-2所示。
表1-6 登录模块用例说明表
用例编号 | 001 |
用例名称 | 登录 |
角色名 | 系统管理员 |
用例说明 | 用户在登录界面输入用户名密码进行登录 |
前置条件 | 无 |
基本流程 | 1、在对应框输入账号密码 2、用户点击登录 |
后置条件 | 点击后进入具体功能界面 |
(2)用户管理模块,用例如表3-3所示。
表1-7 用户管理模块用例说明表
用例编号 | 002 |
用例名称 | 用户管理 |
角色名 | 系统管理员 |
用例说明 | 系统管理员在用户管理界面进行添加、删除、修改、查询用户 |
前置条件 | 登录用户为系统管理员 |
基本流程 |
|
后置条件 | 系统根据操作对数据库进行修改 |
-
1.3 技术选型
1.前端(Vue.js+Element)
Vue+Element框架
Vue是一款用于构建用户界面的JavaScript框架。它基于标准HTML、CSS和JavaScript构建,并提供了一套声明式的、组件化的编程模型,帮助开发者高效地开发用户界面。Vue.js是一套构建用户界面的渐进式框架,采用自底向上增量开发的设计,核心库只关注视图层。另一方面,Vue完全有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用。其最大的特点是易用、灵活、性能好。
Vue项目创建流程图
2.后端(Springboot + Mybatis-plus)
本系统开发采用java语言,java比较常见的主流框架有SpringMVC+Spring+MyBatis,SpringMVC+Struts2+Hibernate,Springboot+MyBatis等。
本系统采用Springboot+ MyBatis-Plus的框架,SpringBoot是由Pivota团队提供的全新框架,其设计目的是用来简化Spring应用的 初始搭建以及开发过程。
SpringBoot程序优点:①自动配置②起步依赖(简化依赖配置)③辅助功能(内置服务器,…)。下面将介绍各个框架以及它在系统中的应用。
Springboot
springboot项目创建流程图
Springboot的三层架构
- 表现层(Presentation Layer):
- 视图(View):负责用户界面的展示和用户交互。
- 控制器(Controller):接收用户的请求并协调调度其他层的处理。
- 业务逻辑层(Business Logic Layer):
- 服务层(Service):包含业务逻辑的实现,协调各个领域对象的交互。
- 模型层(Domain/model):包含业务领域对象(实体、值对象)以及相关的业务规则和行为。
- 数据访问层(Data Access Layer):
- 存储库(Repository)或数据访问对象(DAO):负责与数据存储(如数据库)进行交互,提供数据的持久化和检索。
在这个架构中,数据流从表现层开始,用户通过视图发起请求,请求被控制器接收并传递给服务层。服务层包含业务逻辑的实现,可能会涉及多个领域对象的协作。服务层通过调用存储库或数据访问对象来获取或持久化数据。
领域层是业务逻辑的核心,包含了业务领域对象(实体、值对象)以及相关的业务规则和行为。领域对象通过对数据进行状态变更、计算和验证等操作来实现业务功能。
数据访问层负责与数据存储进行交互,包括对数据库的访问和操作。它提供了数据的持久化和检索功能,并为领域层提供数据访问的接口。
Springboot整合前端Vue可以直接把整个Vue项目文件夹复制到Springboit项目的根目录文件夹下。
Mybatis-plus
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。以下是Mybatis-plus的搭建过程。
Mybatis-plus搭建过程
Mybatis-plus的核心组件包括:
Autogenerator:代码生成器,用于生成实体类、Mapper接口、Service和Controller等代码。这样可以加速开发过程并保持开发的一致性。(但是本文为了更好的学习框架并没有使用此组件)
BaseMapper:通用Mapper接口,包含了一系列通用的“Wrapper”:查询条件构造器,用于创建灵活的查询条件。只需继承此接口并使用注解来生成SQL,无需手动编写SQL语句。
QueryWrapper:查询条件构造器的一种具体实现,提供了“UpdateWrapper”:更新条件构造器,用于更新操作的条件床=创建。“LambdaQueryWrapper”:使用Lambda表达式进行条件构造的方式,类型更加安全。“LambdaUpdateWrapper”:使用Lambda表达式进行更新条件构造的方式。
Page:分页查询的封装,用于处理分页查询的结果。用户可以方便地进行分页查询操作。
1.4 系统架构设计
新闻分类系统的逻辑架构主要分为5层,分别是表示层,控制层,业务逻辑层,数据访问层,持久层。表示层用于前端展示,主要使用Vue框架和Element UI框架完成。实现接口由控制层完成,数据以json格式传输。业务逻辑层包括用户端和管理端,用户端实现新闻查询,新闻分类检索等功能;管理端实现对用户信息的增删改查功能。数据访问层主要用于类的编写。持久层以Mybatis-plus对数据库进行读写操作。
系统架构图
2.详细设计
2.1 数据库设计
数据库对应类图
为实现新闻网站内容的存储和检索功能,首先需要一个新闻文章表,用于存储每篇新闻文章的信息,然后需要一个主题分类表,和新闻分类关联表,存储每个分类的相关信息以及将新闻文章与其所属的主题分类关联起来。具体表定义如下。
表2-1 用户信息表user
序号 | 字段名 | 数据项 | 类型 | 长度 | 允许空 | 主键 | 说明 |
1 | user_id | 用户编号 | INTEGER | 20 | 否 | 是 | |
2 | username | 用户名 | VARCHAR | 20 | 否 | ||
3 | password | 密码 | VARCHAR | 20 | 否 | ||
4 | tel | 电话号码 | VARCHAR | 20 | 否 |
表2-2新闻文章表news
序号 | 字段名 | 数据项 | 类型 | 长度 | 允许空 | 主键 | 说明 |
1 | news_id | 新闻编号 | INTEGER | 20 | 否 | 是 | |
2 | title | 新闻标题 | VARCHAR | 20 | 否 | ||
3 | news_abstract | 摘要 | VARCHAR | 50 | 否 | ||
url | 原文链接 | VARCHAR | 50 | ||||
source | 来源 | VARCHAR | 20 | ||||
3 | content | 文章内容 | VATCHAR | 255 | 否 | ||
4 | publish_date | 发布日期 | date | 否 |
表2-3类别表category
序号 | 字段名 | 数据项 | 类型 | 长度 | 允许空 | 主键 | 说明 |
1 | category_id | 分类编号 | INTEGER | 20 | 否 | 是 | |
2 | category_name | 分类名称 | VARCHAR | 20 | 否 | ||
3 | description | 分类描述 | VARCHAR | 50 | 否 |
表2-4新闻分类关联表news_category
序号 | 字段名 | 数据项 | 类型 | 长度 | 允许空 | 主键 | 说明 |
1 | id | ID | INTEGER | 20 | 否 | 是 | |
2 | news_id | 新闻编号 | INTEGET | 20 | 否 | ||
3 | category_id | 分类编号 | INTEGER | 20 | 否 |
2.2 爬虫模块设计
Java开源的爬虫框架有Jsoup、WebMagic、Crawler4j、ApacheNutch、Spring Batch、Selenium、HttpClient、Jaunt、HtmlUnit、WebSphinix等等,为了更好地学习爬虫技术,分析了几种主流的爬虫框架,决定使用最原始的两大框架Jsoup+HttpUnit实现项目爬虫模块。
jsoup可以获取静态页面,并解析页面标签,最主要的是,可以采用类似于jquery的语法获取想要的标签元素。HttpUnit主要作用是帮助开发者执行自动化的 Web 应用测试和模拟用户操作,本文利用其进行请求模拟过程。具体来说,HttpUnit 提供了以下功能和作用:1. 模拟用户操作:HttpUnit 可以模拟用户在浏览器中执行的各种操作,如点击链接、填写表单等。2. 处理 HTTP 请求和响应:HttpUnit 允许开发者发送 HTTP 请求,并接收和处理 Web 服务器的响应。
爬虫基本步骤为以下四步:
(2)使用jsoup获取新闻<a>标签;
(3)从<a>标签中抽取基本信息,封装成News对象;
(4)根据新闻url访问新闻页面,获取新闻内容、图片等。
网页爬取:首先需要使用Jsoup和HtmlUnit的Java库来获取HTML内容。定义一个专门的类来处理页面抓取,并提供接口来定义抓取规则,以实现不同网站新闻内容的抓取。
页面解析:获取了页面内容后,进一步解析HTML以提取新闻信息,需要对不同的网站的HTML标签、CSS选择器进行解析。
数据存储:将解析得到的新闻数据存储到MYSQL数据结构中。
URL管理:为避免重复抓取同一页面,设计了一个URL列表作为URL管理器来跟踪已经访问过的URL,确保不会重复抓取相同的新闻页面。
深度控制:为了避免陷入死循环,需要控制爬虫的深度,即抓取到多少层的链接,本文将深度参数设置为5。
定时任务:为了定期更新新闻数据,需要使用一个定时任务来定期运行爬虫程序。
爬虫模块类关系图
设置定时任务定期更新新闻网站
Springboot进行定时任务一共有三种方式:第一种也是最简单的一种:基于注解 (@Scheduled)的方式;第二种:基于接口 (SchedulingConfigurer);第三种:基于注解设定多线程定时任务。
本项目采用第一种方式。在启动类中用注解 @EnableScheduling进行标注,表明此类存在定时任务。然后在定时执行的方法之上添加注解@Scheduled,使系统每隔24小时就运行一次爬虫程序,更新数据库数据,重新刷新新闻内容界面等等,实现新闻网站的自动更新。
2.3 分类模块设计
HanLP
HanLP是由一系列模型与算法组成的Java工具包,目标是普及自然语言处理在生产环境中的应用。HanLP是一款自然语言处理工具包,提供了一系列强大的算法和模型来处理中文文本。HanLP具备功能完善、性能高效、架构清晰、语料时新、可自定义的特点。HanLP提供中文分词、词性标注、命名实体识别、关键词提取、短语提取、拼音转换等多种功能。
本项目使用HanLP先对新闻文本进行预处理,包括中文分词、去除停用词、特征向量化表示等,可以更好地结合k-means算法实现文本聚类任务,提高对大规模文本数据的处理效率和分析能力。
k-means算法
机器学习分为“有监督学习”和“无监督学习”,主要区别在于有监督学习通常是利用带有专家标注的标签的训练数据,学习一个从输入变量X到输入变量Y的函数映射;而无监督学习问题处理的是,只有输入变量X没有相应输出变量的训练数据。它利用没有专家标注的训练数据,对数据的结构进行建模。
在“无监督学习”中,应用最广的是“聚类”,聚类就是将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇”。经过划分后,每个簇对应的概念语义需要自行命名。
基于本项目,需要将爬取到的新闻数据进行无专家标签的分类,明显属于无监督的机器学习模型,因此本文决定采用经典的原型聚类算法即K-means算法对新闻数据进行聚类分析。
K-means算法对聚类所得簇划分最小化平方误差,即计算簇内样本围绕簇均值向量的紧密程度,所得值越小则簇内相似度越高。聚类的依据是文本的相似性。具体来说,K均值聚类算法将新闻文本转化为特征向量,并根据这些特征向量将新闻分为不同的簇。每个簇包含在特征空间中相似的新闻。一个簇就算是一种类别。
为了更好地使用K-means算法,需要先对原始新闻数据进行分词、去停用词和特征值提取处理,然后运用聚类算法将新闻转为特征向量列表进行聚类,最终得到k个簇。
分类模块流程图
K-means算法的流程如下:
k-means算法流程图
用户点击登录按钮进入登录界面,输入用户名和密码,再次点击登录按钮,检查用户名和密码都正确后即可登录成功进入首页。
以下是登录注册模块的核心代码。
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @PostMapping("/login") public Result login(@RequestBody UserDTO userDTO){} @PostMapping("/register") public Result register(@RequestBody UserDTO userDTO){} } |
业务层主要负责新增、登录、注册、查询用户业务。
@Service public class UserService extends ServiceImpl<UserMapper,User> {//业务层 public boolean saveUser(User user){} public UserDTO login(UserDTO userDTO) {}//登录业务 public User register(UserDTO userDTO) { }//注册业务 private User getUserInfo(UserDTO userDTO){}//查询业务 } |
跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的。javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。
所谓跨域就是从 A 向 B 发请求,如若他们的地址协议、域名、端口都不相同,直接访问就会造成跨域问题(vue:8080;springboot:8023),跨域是非常常见的现象!请求是跨域的但并不一定会报错,普通的图片请求,css文件请求是不会报错的。报错的条件是浏览器的同源策略,且发送Ajax请求,跨域是客户端问题。
解决:
@Configuration public class CorsConfig { // 当前跨域请求最大有效时长。这里默认1天 private static final long MAX_AGE = 24 * 60 * 60; @Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("http://localhost:8080"); //1 设置访问源地址 corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头 corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法 corsConfiguration.setMaxAge(MAX_AGE); source.registerCorsConfiguration("/**", corsConfiguration); // 4 对接口配置跨域设置 return new CorsFilter(source); } } |
3.2 首页的实现
首页展示新闻列表,用户可以根据输入的新闻标题、新闻来源、新闻发布日期实现新闻查询。这部分主要使用Mybtais-plus的核心组件Page和QueryWrapper实现分页查询功能。
@RestController @RequestMapping("/news") public class NewsController { @Autowired private NewsService newsService; @GetMapping("/page")// 实现分页模糊查询新闻 public IPage<News> findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam String title, @RequestParam String source, @RequestParam String publishDate){ IPage<News> page = new Page<>(pageNum,pageSize); QueryWrapper<News> queryWrapper = new QueryWrapper<>(); if(!"".equals(title)){ queryWrapper.like("title",title); } .... return newsService.page(page, queryWrapper); } |
用户管理模块包括查询所有用户、批量删除、根据id删除、分页查询功能。
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; @GetMapping public List<User> findAll(){} @PostMapping("/del/batch") public boolean deleteBatch(@RequestBody List<Integer> ids){} @DeleteMapping("/{id}") public boolean delete(@PathVariable Integer id){} @GetMapping("/page") public IPage<User> findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize, @RequestParam String userName, @RequestParam String tel, @RequestParam String role){} } |
3.4 新闻爬取模块的实现
新闻爬取
定义一个名为NewsPuller的接口,接口有一个pullNews和getHtmlFromUrl的方法,其中getHtmlFromUrl方法可以获取制定url的网页内容。NetEasyNewsPuller、IfengNewsPuller、SohuNewsPuller分别为爬取网易新闻、凤凰新闻、搜狐新闻的工具类,都实现该接口方法对获取到的不同新闻网页进行分析,提取出对应的新闻内容。
以下是爬取新闻接口的部分核心代码
public interface NewsPuller { HashSet<News> pullNews(String url, int depth, Set<String> visitedUrls, Set<String> visitedNames); default Document getHtmlFromUrl(String url, boolean useHtmlUnit) throws Exception { …//Jsoup连接到指定url并模拟火狐浏览器的用户代理获取页面HTML内容 return Jsoup.connect(url) .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0") .get(); } else { //创建一个HtmlUnit的WebClient对象,并设置特定的配置选项,包括启用JavaScript、禁用CSS以及处理异常。 WebClient webClient = new WebClient(BrowserVersion.CHROME); webClient.getOptions().setJavaScriptEnabled(true); webClient.getOptions().setCssEnabled(false); webClient.getOptions().setActiveXNative(false); webClient.getOptions().setCssEnabled(false); webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); webClient.getOptions().setTimeout(10000); HtmlPage rootPage = null; try { //使用HtmlUnit从URL获取HTML内容。它等待后台JavaScript的执行,然后将页面内容转换为HTML字符串。最后,使用Jsoup解析HTML字符 rootPage = webClient.getPage(url); webClient.waitForBackgroundJavaScript(10000); String htmlString = rootPage.asXml(); return Jsoup.parse(htmlString); …… webClient.close(); …… // 如果获取页面失败,返回一个空的 Document 对象 return new Document(""); } |
爬取搜狐新闻数据
定期更新
Springboot提供了一种方便的方式来创建和管理定时任务,通过使用“@Scheduled”注解,可以创建定时任务。
首先需要创建一个定时任务的类,用“@Scheduled”注解设置任务的触发时间。
@Service public class NewsCrawlerService{ // 定时任务 @Autowired private NewsService newsService; @Autowired private CategoryService categoryService; @Scheduled(cron = "0 0 0 * * *") //设置任务触发时间,每24小时执行一次 public void updateNewsData() {} } |
然后在应用的主类上,使用“EnableScheduling”注解来启用Springboot的定时任务功能,在Springboot项目运行后,定时任务就会在指定的时间间隔内执
@EnableScheduling //启动定时任务 public class NewsSpingbootApplication { public static void main(String[] args) { SpringApplication.run(NewsSpingbootApplication.class, args); } } |
3.5 新闻分类模块的实现
实现k-means算法首先要进行新闻文本预处理,然后构建词汇表,统计所有新闻文本出现的不同的词语,再将新闻列表转化为特征向量,将新闻内容表示为一个特征向量,其中每个维度对应词汇表中的一个词语,而每个值表示该词语在新闻中出现的次数,然后执行k-means算法进行聚类。采用特征向量和簇的数量K作为参数,并返回一个包含K个簇的列表。
public class NewsClustering { private final HanLp hanLp = new HanLp(); public HashSet<Category> sort(HashSet<News> newsSet){ HashSet<Category> categoryHashSet = new HashSet<>(); for (News news : newsSet) { /* 1. 新闻文本预处理 */ String processedContent = hanLp.process(news.getContent()); news.setContent(processedContent); } List<News> newsList = new ArrayList<>(newsSet); /* 2. 构建词汇表 */ List<String> vocabulary = buildVocabulary(newsList); /* 3. 将newsList转化为特征向量 */ List<MyClusterable> featureVectors = convertToFeatureVectors(newsList, vocabulary); int k = 10; // 设置簇的数量 /* 执行K均值聚类 */ List<Cluster<MyClusterable>> clusters = performKMeansClustering(featureVectors, k); // 分析并输出结果 for (int i = 0; i < clusters.size(); i++) { System.out.println("Cluster " + (i + 1)); int cluster = i + 1; List<MyClusterable> clusterPoints = clusters.get(i).getPoints(); for (int j = 0; j < clusterPoints.size(); j++) { News news = newsList.get(featureVectors.indexOf(clusterPoints.get(j))); System.out.println("id"+ news.getTitle()); categoryHashSet.add(new Category(0,news.getNewsId(),cluster)); } System.out.println(); } return categoryHashSet; } /* 构建词汇表 */ private static List<String> buildVocabulary(List<News> newsList) { List<String> vocabulary = new ArrayList<>(); for (News news : newsList) { String content = news.getContent(); if(content == null){ System.out.println("有空的内容"); continue; } // 进行分词和处理文本 String[] words = content.split("\\s+"); // 简化分词 for (String word : words) { if (!vocabulary.contains(word)) { vocabulary.add(word); } } } return vocabulary; } /* 构建特征向量 */ private static List<MyClusterable> convertToFeatureVectors(List<News> newsList, List<String> vocabulary) { List<MyClusterable> featureVectors = new ArrayList<>(); for (News news : newsList) { String content = news.getContent(); if(content == null){ continue; } String[] words = content.split("\\s+"); RealVector vector = new ArrayRealVector(vocabulary.size()); for (int i = 0; i < vocabulary.size(); i++) { int count = 0; for (String word : words) { if (vocabulary.get(i).equals(word)) { count++; } } vector.setEntry(i, count); } featureVectors.add(new MyClusterable(vector)); } return featureVectors; } /* 方法执行K均值聚类。*/ private static List<Cluster<MyClusterable>> performKMeansClustering(List<MyClusterable> featureVectors, int k) { Clusterer<MyClusterable> clusterer = new KMeansPlusPlusClusterer<>(k, -1, new EuclideanDistance(), new JDKRandomGenerator()); List<?> clusters = clusterer.cluster(featureVectors); // 使用通配符捕获泛型类型 return (List<Cluster<MyClusterable>>) clusters; } } |
k-means算法得到簇分类
分类结果不均匀原因分析:
- 数据不平衡:爬取到的新闻某些类别的数量远远超过其他类别,k均值聚类就可能会倾向于将更多的样本分配给那些较大的类别。
- k值选择:k值设置的不合适也可能会导致不均匀的分类结果。
- 特征选择:特征向量的构建方式可能导致一些特征在聚类过程中占主导地位,从而影响了分类结果。
登录界面
注册界面
用户登录状态图
用户管理界面
首页新闻列表图示
新闻分类界面
待改进:
不需要将新闻文本数据存储在数据库里,而是只需要存储一个新闻原文链接,这样可以节约资源,而且相对安全,可以同步原文的修改与更新。
实践中遇到的问题及解决方法:
(1)技术框架难以选择。一开始技术选型的时候比较犹豫,不清楚哪些框架是合适的。
(2)需求不够清晰,一开始就想把所有可能的功能都实现,但实际上在短时间内只要实现最主要最核心的功能就好。
(3)刚开始分类模块的模型没有选对,选的是朴素贝叶斯算法,但是它是一种有监督的学习,不适用于对无标签的新闻文本分类,所以之后模型算法的选择需要充分了解其使用场景再使用。
总的来说,此次项目学习了Vue、Springboot、Mybatis-plus等框架的使用,在学习的过程中也遇到了很多困难和问题,但是通过问老师同学,上网搜索资料,查询书籍的方式最终都解决了出现的问题。
参考文献:
- 周志华.(2016)机器学习.清华大学出版社