277-基于Python的虚假新闻检测可视化分析系统
基于 Python + Vue3 的智能谣言检测与可视化分析系统实战
一套从数据采集、AI 判别、到可视化展示、后台管理的完整解决方案。
摘要
本文详细分享“智能谣言检测与可视化分析系统”的整体设计与落地实践。内容涵盖:
- 系统功能与技术选型
- 目录结构与核心模块
- 后端(Flask + SQLite + BERT)实现要点
- 爬虫与数据导入方案
- 前端(Vue3 + ECharts)可视化展示
- 运行部署与常见问题
- 后续规划与扩展建议
文末附联系渠道:码界筑梦坊(各大平台同名)。
为什么要做这个系统
信息爆炸时代,网络谣言传播快、影响广。我们希望用一套“可复用、可扩展、可视化”的工程化方案:
- 自动采集权威平台的辟谣数据
- 使用 AI 模型对文本进行真假判定
- 用多维度图表进行数据洞察
- 提供后台管理与人工干预能力
功能总览
- 数据采集与导入
- 自动爬取权威辟谣平台
- CSV/Excel 批量导入(支持去重与增量更新)
- 智能谣言检测
- 基于 BERT 的文本二分类(真实/谣言)
- 实时检测接口与置信度输出
- 数据库与后台管理
- 新闻增删改查、分页搜索
- 用户/反馈管理(可扩展)
- 可视化分析
- 真假新闻分布、来源 TOP10、类型分布、热词词云
- 虚假新闻主题聚类(力导向图)
- 前端交互
- 热点新闻列表与详情弹窗(图片智能展示)
- 谣言检测页(展示 AI 技术说明)
- 响应式设计,移动端友好
技术栈
- 后端:Python 3.x、Flask、SQLite、Requests、BeautifulSoup、Pandas、Transformers (BERT)、PyTorch
- 前端:Vue3(Vite)、ECharts(含 wordcloud)、FontAwesome、原生 CSS
- 其他:JWT 鉴权、CORS、Mermaid(架构草图)
目录结构(精简版)
虚假新闻/├── app.py# Flask 后端主程序(API、AI 检测、可视化数据)├── piyao_crawler_fixed.py # 辟谣平台爬虫(列表/详情解析,入库)├── spider.py # JSON 接口采集(批量高效)├── import_news_csv.py # CSV 批量导入(含去重/更新)├── view_database.py # 快速查看/统计数据库├── instance/│ └── news.db # SQLite 数据库(持久化)├── output_data/│ └── 中国互联网联合辟谣平台.csv # 采集数据导出├── saved_model/ # BERT 模型文件│ ├── model.safetensors│ ├── config.json│ ├── tokenizer_config.json│ └── vocab.txt├── fake-news-detector/ # 前端工程(Vue3 + Vite)│ ├── src/│ │ ├── views/ # 页面:热点新闻/可视化/检测/后台等│ │ ├── components/ # 组件:Header、管理表格等│ │ ├── utils/ # displayUtils 等工具│ │ └── main.js # 入口│ └── vite.config.js└── README.md # 工程说明
核心架构(Mermaid 草图)
#mermaid-svg-3nfZcSB4fD1qxI0K {font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .error-icon{fill:#552222;}#mermaid-svg-3nfZcSB4fD1qxI0K .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3nfZcSB4fD1qxI0K .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-3nfZcSB4fD1qxI0K .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3nfZcSB4fD1qxI0K .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3nfZcSB4fD1qxI0K .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3nfZcSB4fD1qxI0K .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3nfZcSB4fD1qxI0K .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3nfZcSB4fD1qxI0K .marker.cross{stroke:#333333;}#mermaid-svg-3nfZcSB4fD1qxI0K svg{font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3nfZcSB4fD1qxI0K .label{font-family:\"trebuchet ms\",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .cluster-label text{fill:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .cluster-label span{color:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .label text,#mermaid-svg-3nfZcSB4fD1qxI0K span{fill:#333;color:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .node rect,#mermaid-svg-3nfZcSB4fD1qxI0K .node circle,#mermaid-svg-3nfZcSB4fD1qxI0K .node ellipse,#mermaid-svg-3nfZcSB4fD1qxI0K .node polygon,#mermaid-svg-3nfZcSB4fD1qxI0K .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3nfZcSB4fD1qxI0K .node .label{text-align:center;}#mermaid-svg-3nfZcSB4fD1qxI0K .node.clickable{cursor:pointer;}#mermaid-svg-3nfZcSB4fD1qxI0K .arrowheadPath{fill:#333333;}#mermaid-svg-3nfZcSB4fD1qxI0K .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3nfZcSB4fD1qxI0K .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3nfZcSB4fD1qxI0K .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-3nfZcSB4fD1qxI0K .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-3nfZcSB4fD1qxI0K .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3nfZcSB4fD1qxI0K .cluster text{fill:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K .cluster span{color:#333;}#mermaid-svg-3nfZcSB4fD1qxI0K div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\"trebuchet ms\",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3nfZcSB4fD1qxI0K :root{--mermaid-font-family:\"trebuchet ms\",verdana,arial,sans-serif;}规范化写入REST APIJSONECharts文本爬虫/导入SQLite: news.dbFlask 后端Vue3 前端数据可视化BERT 模型
项目演示
*** 💻项目源码获取,码界筑梦坊各平台同名,博客底部含联系方式卡片,欢迎咨询!***
后端实现要点(Flask + SQLite + BERT)
1)数据库模型与初始化
# app.py 片段app.config[\'SQLALCHEMY_DATABASE_URI\'] = \'sqlite:///news.db\'app.config[\'SQLALCHEMY_TRACK_MODIFICATIONS\'] = Falsedb = SQLAlchemy(app)class News(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(200), nullable=False) description = db.Column(db.Text) content = db.Column(db.Text) date = db.Column(db.String(20)) source = db.Column(db.String(100)) isTrue = db.Column(db.Boolean, default=True)def init_db(): with app.app_context(): db.create_all() # 仅在不存在时创建
2)AI 模型加载与预测接口
# app.py 片段(BERT 加载)from transformers import BertForSequenceClassification, BertTokenizerimport torchmodel_path = \'./saved_model\'model = BertForSequenceClassification.from_pretrained(model_path)tokenizer = BertTokenizer.from_pretrained(model_path)# 预测函数def predict(text: str): model.eval() inputs = tokenizer(text, return_tensors=\'pt\', padding=True, truncation=True, max_length=512) with torch.no_grad(): outputs = model(**inputs) probs = torch.nn.functional.softmax(outputs.logits, dim=-1) label = torch.argmax(probs).item() # 0=谣言, 1=真实 conf = probs[0][label].item() return label, conf# API: /api/check-news@app.route(\'/api/check-news\', methods=[\'POST\'])def check_news(): data = request.get_json() label, confidence = predict(data[\'text\']) return jsonify({ \'result\': \'真实\' if label == 1 else \'谣言\', \'confidence\': f\"{confidence:.2%}\", \'isTrue\': label == 1 })
3)可视化数据接口
# app.py 片段(来源 TOP10、真假分布等)@app.route(\'/api/visualization/news-stats\', methods=[\'GET\'])def get_news_stats(): all_news = News.query.all() true_count = sum(1 for n in all_news if n.isTrue) fake_count = len(all_news) - true_count # 来源统计 ... 返回 JSON return jsonify({...})
爬虫与数据导入
1)JSON 接口抓取(高效批量)
# spider.py 片段headers = {\'user-agent\': \'Mozilla/5.0 ...\'}url = \'https://www.piyao.org.cn/ds_d0dcbc84f3f54742beb26cf3f86ddb1f.json\'resp = requests.get(url, headers=headers)for m in resp.json()[\'datasource\']: title = m[\'showTitle\'] link = \'https://www.piyao.org.cn/\' + m[\'publishUrl\'] source = m[\'sourceText\'] date = m[\'publishTime\'][:10] # 如需正文可再请求详情页
2)DOM 解析(适配复杂结构)
# piyao_crawler_fixed.py 片段(列表与详情解析)soup = BeautifulSoup(html, \'html.parser\')list_container = soup.find(\'ul\', id=\'list\')# ...content_div = soup.find(\'div\', class_=\'con_txt\')content = content_div.get_text(strip=True) if content_div else \'\'# 图片收集、来源/时间正则兜底提取
3)CSV 批量导入(支持更新)
# import_news_csv.py 片段for _, row in df.iterrows(): title = str(row[\'标题\']).strip() # 存在则 UPDATE,不存在则 INSERT cursor.execute(\'SELECT id FROM news WHERE title = ?\', (title,)) if cursor.fetchone(): cursor.execute(\'\'\' UPDATE news SET description=?, content=?, date=?, source=?, isTrue=? WHERE title=? \'\'\', (description, content, date, source, 0, title)) else: cursor.execute(\'\'\' INSERT INTO news (title, description, content, date, source, isTrue) VALUES (?, ?, ?, ?, ?, ?) \'\'\', (title, description, content, date, source, 0))
前端可视化与交互(Vue3 + ECharts)
1)可视化页面(来源 TOP10 美化与反转)
// VisualizationPage.vue 片段(来源 TOP10)sourceChart.setOption({ title: { text: \'新闻来源TOP10\', left: \'center\', top: \'5%\' }, grid: { left: \'15%\', right: \'5%\', top: \'15%\', bottom: \'15%\', containLabel: true }, yAxis: { type: \'category\', data: data.source_distribution.sources.reverse() }, series: [{ type: \'bar\', data: data.source_distribution.counts.reverse(), barWidth: \'65%\' }]})
2)谣言检测页(展示 AI 技术说明)
使用的AI技术
BERT模型预训练语言模型 深度学习序列分类任务 中文分词jieba分词处理 置信度评估Softmax 概率输出
3)热点新闻详情(图片智能展示)
0\" class=\"news-images\">
运行与部署
后端
pip install -r requirements.txtpython app.py
前端
cd fake-news-detectornpm installnpm run dev
访问
- 前端开发地址:http://localhost:5173/
- 后端 API 地址:http://localhost:5000/
可视化展示(预留占位)
- 真假新闻分布饼图(截图占位)
- 新闻来源 TOP10 条形图(截图占位)
- 新闻类型分布玫瑰图(截图占位)
- 热词词云(截图占位)
- 虚假新闻主题聚类(截图占位)
建议配合生产数据截图替换占位,或使用 ECharts 保存为 PNG。
常见问题(FAQ)
- Q:重启后数据会丢失吗?
- A:不会,数据库文件位于
instance/news.db
,为持久化存储。
- A:不会,数据库文件位于
- Q:如何避免重复导入?
- A:导入脚本按标题去重,存在则 UPDATE,不存在 INSERT。
- Q:如何去掉可视化中的“准确率”?
- A:我们已在
VisualizationPage.vue
中移除该项,仅保留总量/来源数等。
- A:我们已在
- Q:前端出现
nan
?- A:通过
displayUtils.js
统一兜底显示为“暂无描述/暂无内容”。
- A:通过
规划与扩展
- 接入更多数据源(微博、新闻 API 等)
- 模型升级(蒸馏/轻量化/中文大模型)
- 规则 + 模型的混合判定策略
- 运营面板:任务调度、清洗监控、异常告警
- 权限体系完善与审计日志
结语与联系方式
如果本文对你有帮助,欢迎点赞、收藏与转发。
- 联系方式:码界筑梦坊(各大平台同名)
- 开源不易,感谢支持与反馈!