> 技术文档 > 277-基于Python的虚假新闻检测可视化分析系统

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,为持久化存储。
  • Q:如何避免重复导入?
    • A:导入脚本按标题去重,存在则 UPDATE,不存在 INSERT。
  • Q:如何去掉可视化中的“准确率”?
    • A:我们已在 VisualizationPage.vue 中移除该项,仅保留总量/来源数等。
  • Q:前端出现 nan
    • A:通过 displayUtils.js 统一兜底显示为“暂无描述/暂无内容”。

规划与扩展

  • 接入更多数据源(微博、新闻 API 等)
  • 模型升级(蒸馏/轻量化/中文大模型)
  • 规则 + 模型的混合判定策略
  • 运营面板:任务调度、清洗监控、异常告警
  • 权限体系完善与审计日志

结语与联系方式

如果本文对你有帮助,欢迎点赞、收藏与转发。

  • 联系方式:码界筑梦坊(各大平台同名)
  • 开源不易,感谢支持与反馈!