主流博客文章数据分析系统+springboot+vue3实现
前言
大家好,今天给大家带来了一个博客文章分析系统,支持目前各大主流博客(CSDN,博客园,知乎,思否,掘金), 系统可以分析文章的内容, 评论,点赞,访问。具体内容请见下面视频。
解决了登录,环境异常等问题。这是一个完整的商用系统,不是demo,是定制开发的线上版本。
视频演示
https://githubs.xyz/show/71f17896-1112-4246-b66c-453a4c309960.mp4
图片演示




系统功能描述
1. 博客配置管理
- 支持多个博客平台的数据爬取(博客园、思否、CSDN、知乎、掘金)
- 爬取文章标题,内容,评论,点赞量,访问量
2. 爬虫任务管理
- 支持创建和管理博客爬取任务
- 实时显示任务执行状态和进度
- 提供任务日志查看功能
3. 数据分析功能
- 展示文章访问量、点赞量、评论量等数据
- 支持分析被封博客预警
- 支持和上一次分析对比评论上升量,点赞上升量,访问上升量
4. 系统配置
- 支持WebDriver配置管理
- 提供元素选择器字典配置
使用说明
- 首先在【博客设置】中配置需要爬取的博客信息
- 在【驱动配置】中确保WebDriver配置正确
- 通过【任务列表】创建新的爬取任务
- 在【任务结果】中查看数据分析结果
部署搭建
将文件解压到D盘的根目录:
文件我已经整理清楚了,移步获取:
gitee( 典 ) C 〇 M/qiqi915/java01.git

按顺序启动1,2,3,4 bat 文件就可以了, 启动 “0.rundb.bat” , 如果启动失败,可能是3306端口被占用了,自行解决。

启动 “1.run_server.bat” , 启动会启动一个浏览器,不要动它。

启动 “2.run_font.bat” , 这个启动会等待一段时间,然后会自动关闭。
启动 “3.run_font2.bat” :

访问:
http://localhost:4000/
技术实现
源码我已经整理清楚了,移步获取:
gitee( 典 ) C 〇 M/qiqi915/java01.git
1. 动态配置元素定位
后端使用的是java版本的selenium ,元素的定位信息都是存储到t_blog_element_settings表里面的:

这样的好处就是,页面更新后,只需要在后台修改下元素定位就可以了,不用改代码。
2. 优秀的隐藏机制
selenium 运行时, 很容易被识别出来,我使用了如下代码来隐藏,下面是构造驱动的部分代码:
// 添加更多的浏览器指纹
Map<String, Object> prefs = new HashMap<>();
prefs.put("profile.default_content_settings.images", 2);
prefs.put("profile.managed_default_content_settings.javascript", 1);
prefs.put("credentials_enable_service", false);
prefs.put("profile.password_manager_enabled", false);
options.setExperimentalOption("prefs", prefs); // 用来解决 登录智能 验证
Map<String, Object> parameters = new HashMap<>();
parameters.put("source", "Object.defineProperty(navigator, \"webdriver\", {get: () => undefined})");
driver.executeCdpCommand("Page.addScriptToEvaluateOnNewDocument",
parameters);
尤其是遇到知乎时,一打开就是环境异常!!!!
我也是搞了好久,java还是解决不了这个问题,最终用一个脚本解决,脚本使用python写的,然后用java调用exe执行。
下面是部分代码:
Process process = null;
try {
List<String> command = new ArrayList<>();
command.add(exePath.toFile().getAbsolutePath());
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "开始执行脚本:" + exePath.toFile().getAbsolutePath());
command.add(env.get("in")); TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "脚本参数:" + env.get("in")); ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true); // 合并错误流到标准输出流
process = processBuilder.start();
// 创建单独的线程来读取进程输出
final Process process1 = process;
Thread outputThread = new Thread(() -> { System.out.println("知乎脚本输出线程开始: ");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process1.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println("知乎脚本输出: " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
//
System.out.println("==================输出流线程退出========================");
});
outputThread.start();
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "脚本执行中,请耐心等待..."); // 等待进程完成,设置超时时间
if (!process.waitFor(5, TimeUnit.HOURS)) {
throw new InterruptedException("进程执行超时(" + 5 + "小时)");
}
// 检查进程退出码
int exitCode = process.exitValue();
if (exitCode != 0) {
System.out.println("脚本执行退出码错误," + exitCode);
setError("脚本执行退出码错误," + exitCode); TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "脚本内部异常,exitCode:" + exitCode); return;
}
} catch (Exception e) {
e.printStackTrace();
setError("脚本执行异常");
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "脚本执行异常, msg:" + e.getMessage()); return;
} finally {
if (process != null && process.isAlive()) {
process.destroy(); // 确保进程被终止
try {
// 等待一段时间让进程正常结束
if (!process.waitFor(5, TimeUnit.SECONDS)) {
process.destroyForcibly(); // 强制终止
}
} catch (InterruptedException e) {
process.destroyForcibly(); // 强制终止
}
}
}
3. 驱动支持配置
我设计了一个驱动设置表,可以支持用户自定义浏览器版本,不过一般用默认的就可以了。
CREATE TABLE `t_driver_settings` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`chrome_driver_path` varchar(2000) COLLATE utf8mb4_bin NOT NULL COMMENT '驱动路径',
`chrome_exe_path` varchar(2000) COLLATE utf8mb4_bin NOT NULL COMMENT '浏览器EXE路径',
`headless` int(11) DEFAULT '0' COMMENT '是否显示浏览器,0-显示 1-不显示',
`driver_count` int(11) DEFAULT '0' COMMENT '驱动数量',
`user_id` int(11) DEFAULT NULL COMMENT '用户id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='驱动设置表';

4. 文章分析系统
文章不仅仅可以显示文章数据列表,还可以自动进行分析,将被封的文章和评论上升量等分析出来:

实现就是通过对比上一次的任务结果数据进行计算。
5. 优秀的异常处理
总所周知,页面元素会出现偶尔的查找错误,比如登录,我这里进行了重试和 每一段代码都是异常try,保证了流程的正常进行,和数据提取。
比如下面部分代码:
@Override
public boolean crawlLogin() {
boolean success = false;
final String loginUrl = settings.getLoginUrl();
String userName = settings.getUserName();
String pwd = settings.getPassword();
int retryCount = 0;
while (retryCount < 10) {
try {
retryCount++;
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "开始第" + retryCount + "次登录"); if (!driver.get(loginUrl, (msg) -> setProgress("博客园登录页访问错误,url:" + loginUrl + ",进行重试"))) {
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "页面访问错误,url:" + loginUrl); continue;
}
setProgress("博客园访问登录页面成功,url:" + loginUrl); // 判断是否已经登录
driver.sleep(1); WebElement loginOut = driver.findElement(By.id("loginOut"), null);
if(loginOut != null){
//已经登录过 ,直接返回
success = true ;
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "已经登录");
return success ;
} // 输入用户名和密码
WebElement usernameInput = driver.findElement(finder.findBy(1), msg -> setProgress("错误:" + finder.findAlias(1)));
if (usernameInput == null) {
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "元素查找错误,名称:" + finder.findAlias(1)); continue;
}
WebElement passwordInput = driver.findElement(finder.findBy(2), msg -> setProgress("错误:" + finder.findAlias(2)));
if (passwordInput == null) {
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "元素查找错误,名称:" + finder.findAlias(2)); continue;
}
usernameInput.clear();
passwordInput.clear(); usernameInput.sendKeys(userName);
passwordInput.sendKeys(pwd); TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "输入用户名:" + userName); // 点击登录按钮
WebElement loginButton = driver.findElement(finder.findBy(3), msg -> setProgress("错误:" + finder.findAlias(3)));
if (loginButton == null) {
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "元素查找错误,名称:" + finder.findAlias(3));
continue;
}
try{
loginButton.click();
}catch(Exception e){
e.printStackTrace();
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "元素点击错误,名称:" + finder.findAlias(3));
continue; }
// 等待登录完成,检查是否存在登录成功的标志(比如用户头像) // 出现智能验证 //*[@id="rectMask"]
try{
WebElement ver = driver.findElement(finder.findBy(4), msg -> setProgress("错误:" + finder.findAlias(4)));
if (passwordInput != null) {
ver.click();
getCrawlerListener().onProgress("点智能验证");
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "点击智能验证成功");
}
}catch (Exception e){
e.printStackTrace();
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "点击智能验证错误, msg:" + e.getMessage());
} // https://www.cnblogs.com/
WebElement user = driver.findElement(finder.findBy(5), msg -> setProgress("错误:" + finder.findAlias(5)));
if (user == null) {
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "主页找不到头像,需要重新登录");
continue;
}
success = true;
getCrawlerListener().onProgress("登录成功");
break;
} catch (Exception e) {
e.printStackTrace();
}
}
if(!success){
setError("登录失败");
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "登录失败");
}else{
TaskLogService.add(task.getTaskId(), "[" + alias() + "] " + "登录成功");
}
return success;
}
结尾语
有问题联系小编。或者注意文章内容,能看到 响应的 你想要的 源代码信 息。
主流博客文章数据分析系统+springboot+vue3实现的更多相关文章
- 一文搭建自己博客/文档系统:搭建,自动编译和部署,域名,HTTPS,备案等
本文纯原创,搭建后的博客/文档网站可以参考: Java 全栈知识体系.如需转载请说明原处. 第一部分 - 博客/文档系统的搭建 搭建博客有很多选择,平台性的比如: 知名的CSDN, 博客园, 知乎,简 ...
- SQL Sever 博客文章目录(2016-07-06更新)
SQL Server方面的博客文章也陆陆续续的写了不少了,顺便也将这些知识点整理.归纳一下下.方便自己和他人查看. MS SQL 数据类型 三大数据库对比研究系列--数据类型 MS SQL 表和视图 ...
- 基于Metaweblog API 接口一键发布到国内外主流博客平台
之前的生活 之前一直使用evenote写博客和日志,其实还是挺方便的.但是我一直都希望能够同步到国内的博客和国外的blogspot等主流博客平台.而强大everote只提供了facebook.twit ...
- 年度十佳 DevOps 博客文章(后篇)
如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.在上篇文章中我们了解到 15 年十佳 DevOps 博客文章的第 6-10 名,有没有哪一篇抓住了您的眼球,让您 ...
- 年度十佳 DevOps 博客文章(前篇)
如果说 15 年你还没有将 DevOps 真正应用起来,16 年再不实践也未免太落伍了.国内 ITOM 领军企业 OneAPM 工程师为您翻译整理了,2015 年十佳 DevOps 文章,究竟是不是深 ...
- 一文搞定scrapy爬取众多知名技术博客文章保存到本地数据库,包含:cnblog、csdn、51cto、itpub、jobbole、oschina等
本文旨在通过爬取一系列博客网站技术文章的实践,介绍一下scrapy这个python语言中强大的整站爬虫框架的使用.各位童鞋可不要用来干坏事哦,这些技术博客平台也是为了让我们大家更方便的交流.学习.提高 ...
- Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理
转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Jav ...
- 利用爬虫将Yuan先生的博客文章爬取下来
由于一次巧遇,我阅读了Yuan先生的一篇博客文章,感觉从Yuan先生得博客学到很多东西,很喜欢他得文章.于是我就关注了他,并且想阅读更多出自他手笔得博客文章,无奈,可能Yuan先生不想公开自己得博客吧 ...
- 使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理
原文:使用IntelliJ IDEA开发SpringMVC网站(五)博客文章管理 摘要 通过对博客文章的管理,实现外键操作. 目录[-] 八.博客文章管理 1.查看文章 2.添加博客 3 ...
- 一个 "开箱即用" 个人博客全栈系统项目!vue+node+express+mysql+sequlize+uniapp
" MG'Blog " 一个 "开箱即用" 个人博客全栈系统项目! 探索本项目的源码 » 前台预览 · 管理端预览 v1.0.2 小程序预览 v1.0.2 介绍 ...
随机推荐
- 如何选择最适合企业的ETL解决方案?
在今天的大数据时代,企业的数据管理和处理变得愈发重要.企业也越来越依赖于数据仓库和数据湖来提取.转换和加载(ETL)关键业务信息.一个高效.灵活的ETL解决方案不仅能提升数据处理能力,还能为企业决策提 ...
- Previously on Assassin's Creed Ⅱ
My name is Desmond Miles. I'm a prisoner of war. A war I never knew existed, waged by two groups I n ...
- P5026 Lycanthropy(差分)
洛谷链接:https://www.luogu.com.cn/problem/P5026 P5026 Lycanthropy 题目背景 小正方形亲眼看见了自己昔日的朋友被卷进了黑暗的深渊,然而它无力阻止 ...
- AX-MES生产制造管理系统-可视化看板
可视化看板最主要的目的是为了将生产状况透明化,让大家能够快速了解当前的生产状况以及进度,通过大数据汇总分析,为管理层做决策提供数据支撑,看板数据必须达到以下基本要求: 数据准确--真实反映生产情况 数 ...
- Integer缓存IntegerCache详解
Integer缓存IntegerCache详解 例子代码 public class IntegerCacheTest { public static void main(String[] args) ...
- 学习理论:代理损失函数的泛化界与Rademacher复杂度
3月份以来的科研基本围绕推导代理损失函数的一致界展开,证明现已基本完工(关于代理损失函数的一致界的介绍可参见之前的博客<学习理论:预测器-拒绝器多分类弃权学习>).导师建议我可以的话把泛化 ...
- 浅谈 RAG 并基于 NodeJS 实现基础向量检索服务
RAG Retrieval-Augmented Generation是一种用于自然语言处理的模型架构,结合了检索Retrieval和生成Generation两种技术.而RAG服务在知识问答.代码生成. ...
- 关于G - Naive Operations的一些试探性想法
https://vjudge.net/contest/310809#problem/G 只是一些瞎想 没学过线段树,不会区间更新,不会做维护(我就是一条咸鱼花了五分钟在网上看了一下线段树的思想,大概明 ...
- LangGraph学习笔记——Agent的输入输出
目录 一.输入格式 二.输出格式 示例 三.对比与应用场景 **四.延伸 LangGraph文档解释:https://github.langchain.ac.cn/langgraphjs/agents ...
- 题解:P1000 超级玛丽游戏
P1000 题解 欢迎来到 AstralNahida 的题解频道! 这题我会给出三种解法. 首先上场的是 PHP,我们知道,PHP 会直接输出标签外的字符,所以我们直接把需要输出的东西复制粘贴即可. ...