news 2026/9/28 6:09:35

基于Python的虚假新闻检测实战:从TF-IDF文本分类到Flask接口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Python的虚假新闻检测实战:从TF-IDF文本分类到Flask接口

简介:面向毕业设计、课程设计与项目开发场景的Python虚假新闻检测工程,覆盖文本预处理、模型训练、效果评估与Web可视化全链路。压缩包共16个文件,以9个Python脚本为核心,分别实现CNN、LSTM、BERT及传统机器学习等模型构建与训练流程,另有4个CSV数据集、环境依赖列表和开发文档,包体约6.07MB,目录划分简洁,便于直接定位关键模块。目前已有204人学习下载。源码已经过严格测试,可直接运行参考;项目包含数据构造训练集/测试集、多种模型对比、AUC指标计算以及基于Web的检测界面,适合掌握Python基础、希望深入理解文本分类或快速产出课程设计成果的开发者。在完成现有流程后,还可替换数据集、调整模型参数或扩展为实时新闻检测接口,留有充足提升空间。

1. 虚假新闻检测到底是什么:一个文本分类项目凭什么能撑起毕业设计

很多同学拿到“基于python开发的虚假新闻检测”这个题目,第一反应是写爬虫去抓新闻,再去第三方平台一条条求证真伪,做着做着把自己绕成了一个舆情系统。实际上,它本质是一个文本二分类任务:给定一条新闻文本,让模型判断它是真实还是虚假。这个题目能成为毕业设计、课程设计里的常客,是因为它把自然语言处理、机器学习和 Web 接口三件事揉在了一起,难度可控、演示效果好,而且无论你以后走算法方向还是开发方向,都能从中提取出能写进简历的产出。适合谁做?想入门 NLP 的学生、需要交一个完整课设作品的人,以及想用最短路径体验“数据—模型—接口—文档”全流程的初学者。下文按我实际做这类项目的顺序展开,照着复现即可。

2. 技术选型和数据准备:把“检测”拆成可实现的分类任务

2.1 为什么选 Python:从语言生态到交付效率

选语言这件事,很多学生是随手选的 Python,但答辩时被问到“为什么不用 Java”就卡住了。我的答案一般是三条:第一,NLP 生态几乎全在 Python 这边,做文本分类要用的 sklearn、jieba、transformers、pandas 全是 Python 系的,Java 那边要么封装不全要么你得自己造轮子;第二,模型训练和评估阶段的交互效率高,写几行代码就能看到指标变化,这对课程设计的时间预算非常友好;第三,Python 写 Web 接口不拖后腿,Flask 起一个服务只要十几行代码,和训练代码统一语言,不用像 C++ 那样搞两套工程。

这里有个新手常踩的坑:装 Python 时没勾选“Add Python to PATH”,导致命令行里python命令失效,后面所有安装步骤都跟着翻车。我一般建议用 Anaconda 管理环境,创建独立环境给项目用,避免把系统 Python 弄乱。IDE 方面,pycharm 配置 python 环境比较省心,但要确认解释器选的是 conda 环境里的那个,不是系统自带的老版本;vscode 配置 python 环境也简单,只要右下角选对解释器即可。语言版本建议 3.8 到 3.10,太新的版本偶尔会和旧版第三方库有兼容问题。

2.2 数据怎么来:公开数据集与自建口径

虚假新闻检测的数据集,业内常见做法是用公开的 fake news 数据集,结构一般是两列:新闻文本、标签 0/1(0 代表真实,1 代表虚假)。课程设计级别 5000 到 1 万条足够跑通流程,毕业设计建议准备 2 万条以上,否则模型很容易过拟合。国内场景如果要自己做,常见做法是用爬虫采集新闻网站的公开内容再人工标注,但要注意采集合规和标注口径统一,工作量比想象中大。

我的建议是:第一优先用现成公开数据集,把时间省给模型和文档;第二要检查数据集的类别分布,很多公开数据里真假比例接近 1:1,但实际场景中虚假新闻永远是少数,训练时你心里要有这个数;第三,统一字段命名,项目里所有脚本只认title(标题)、text(正文)、label(标签)三个字段,后面处理会省很多事。数据文件建议按下面的结构组织,源码、数据、文档分开,这也是答辩老师比较认可的项目结构。

目录用途说明
data/raw/原始数据集从公开渠道拿到的原始 CSV,不做任何修改
data/processed/清洗后的数据去重、去空、标签映射之后的训练/测试集
src/源码目录数据处理、训练、评估、预测的脚本都放这里
models/模型输出训练好的模型文件和评估报告
docs/开发文档设计说明、接口文档、答辩 PPT 素材

2.3 数据清洗与标签构造:先把脏数据处理成模型能吃的样子

拿到原始 CSV 之后,第一步不是训练,而是清洗。这里面最容易翻车的点是:标签列里混了字符串(比如'True'/'Fake')、正文里有大量空值、同一篇新闻重复出现。我一般用 pandas 一把梭处理:

import pandas as pd from sklearn.model_selection import train_test_split # 加载原始数据,指定列为 title/text/label df = pd.read_csv("data/raw/news.csv", usecols=["title", "text", "label"]) # 标签统一为 0/1:字符串映射到数值 label_map = {"true": 0, "fake": 1, "True": 0, "Fake": 1} df["label"] = df["label"].astype(str).str.lower().map(label_map) # 去掉标签缺失或无效的行 df = df.dropna(subset=["label"]) # 正文和标题都为空的行直接丢弃 df = df.dropna(subset=["text"], how="all") df = df[df["text"].str.strip() != ""] # 按正文去重,保留第一条 df = df.drop_duplicates(subset=["text"], keep="first") # 构造模型输入:标题 + 正文拼接 df["content"] = df["title"].fillna("") + " " + df["text"] # 按标签分层划分训练集和测试集,保证类别比例一致 train_df, test_df = train_test_split( df, test_size=0.2, random_state=42, stratify=df["label"] ) train_df.to_csv("data/processed/train.csv", index=False) test_df.to_csv("data/processed/test.csv", index=False) print(train_df["label"].value_counts())

代码里几个关键点说明一下:usecols只读需要的列,避免把无关字段读进来干扰判断;astype(str).str.lower()先把标签统一成小写字符串再做映射,能兼容'True'和'true'两种写法;drop_duplicates(subset=["text"])按照正文去重,因为很多假新闻会被反复转载,不去重会导致模型在重复样本上“背答案”。train_test_split的stratify=df["label"]参数很重要,它保证切分后训练集和测试集里真假样本比例一致,否则测试集里如果恰好全是真实新闻,指标会虚高。

3. 模型训练与系统封装:从 TF-IDF 到深度学习的落地路径

3.1 快速基线:TF-IDF + 逻辑回归能跑多高

很多教程一上来就让学生用深度学习,但我做课程设计项目的习惯是先跑一个传统基线。TF-IDF + 逻辑回归在虚假新闻检测上通常能到 85% 以上的准确率,训练只要十几秒,而且模型可解释性很强——你打印权重最高的几个词,就能看到模型是根据哪些词做出的判断。这套方案用来交课程设计已经够用,毕业设计则把它作为基线,后面用深度模型去对比。

import joblib from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression from sklearn.pipeline import Pipeline from sklearn.metrics import classification_report, accuracy_score import pandas as pd train_df = pd.read_csv("data/processed/train.csv") test_df = pd.read_csv("data/processed/test.csv") # 使用 TfidfVectorizer 做特征提取 vectorizer = TfidfVectorizer( max_features=20000, # 只保留出现频率最高的 2 万个词 ngram_range=(1, 2), # 同时考虑单个词和相邻两个词 min_df=2, # 至少在 2 篇文档中出现过才保留 sublinear_tf=True, # 用 1+log(tf) 平滑词频,减轻高频词主导 ) model = Pipeline([ ("tfidf", vectorizer), ("clf", LogisticRegression(C=1.0, max_iter=1000)), ]) # 训练并用测试集评估 model.fit(train_df["content"], train_df["label"]) pred = model.predict(test_df["content"]) print("accuracy:", accuracy_score(test_df["label"], pred)) print(classification_report(test_df["label"], pred, target_names=["real", "fake"])) # 保存模型,后续预测和 Web 接口都要用到 joblib.dump(model, "models/lr_baseline.joblib")

参数说明:max_features=20000控制特征维度,过小会丢失低频有用词,过大会让训练变慢且容易过拟合,我一般从 2 万起步再调;ngram_range=(1, 2)是效果提升最明显的参数,因为“不是假新闻”这类否定表达要靠双词组合才能捕获;C=1.0是逻辑回归的正则化强度,C 越小正则越强,避免模型过度依赖少数词;sublinear_tf=True做了词频压缩,让“的”“了”这类高频词对权重的影响变小。训练完之后打印classification_report,要重点看 fake(阳性)类的 precision 和 recall,对一个检测系统来说,漏掉一条假新闻比误伤一条真新闻通常更严重。

3.2 进阶:用预训练模型提升效果

如果基线的准确率到不了你想要的分数,或者导师明确要求用深度学习,常见做法是上预训练模型。两个路线:一是 LSTM,训练快、对显存要求低,但效果一般只比 TF-IDF 高两个点左右;二是用中文预训练模型比如 BERT 系列,效果最高但需要 6GB 以上显存,训练时间按小时算。我一般建议课程设计选 LSTM,毕业设计有服务器的话再考虑 BERT。

import torch from torch.utils.data import Dataset, DataLoader from transformers import BertTokenizer, BertForSequenceClassification # 加载中文预训练模型的分词器和模型 model_name = "bert-base-chinese" # 按需替换为实际可用的模型名称 tokenizer = BertTokenizer.from_pretrained(model_name) model = BertForSequenceClassification.from_pretrained(model_name, num_labels=2) # 把新闻文本编码成模型输入格式 def encode_texts(texts, labels, max_len=128): encodings = tokenizer( texts, truncation=True, padding=True, max_length=max_len, return_tensors="pt" ) return encodings, torch.tensor(labels) # 注意:这里只演示数据装载逻辑 train_texts = train_df["content"].tolist()[:100] # 实际训练不应截断 train_labels = train_df["label"].tolist()[:100] inputs, label_tensor = encode_texts(train_texts, train_labels) # 后续用 DataLoader 封装,按 batch=16 喂给模型

这里要强调:truncation=True和max_length=128必须设置,否则长新闻会被模型当作超长输入导致显存溢出;padding=True把同一批次的文本补到等长,是 GPU 批量计算的前提。预训练模型的输入长度和 TF-IDF 相比更敏感,我踩过 512 长度的坑——显存直接爆掉,后来改成 128 长度,指标只掉了零点几个点,训练速度却快了三倍。如果你的计算机配置一般,老老实实max_length=128。

3.3 把模型包成 Web 接口:用 Flask 跑一个能演示的检测服务

模型训练完毕,项目还差最后一环:把它变成能演示的东西。答辩现场不可能打开 Jupyter Notebook 跑训练,更常见做法是用 Flask 起一个本地服务,输入新闻文本,返回检测结果。这个接口同时会写进开发文档,是“源码 + 开发文档”交付物里最能体现工程能力的部分。

import joblib from flask import Flask, request, jsonify app = Flask(__name__) # 加载训练好的模型,路径和 3.1 节保存的一致 model = joblib.load("models/lr_baseline.joblib") @app.route("/predict", methods=["POST"]) def predict(): data = request.get_json() text = data.get("text", "") if not text.strip(): return jsonify({"error": "text 不能为空"}), 400 prob = model.predict_proba([text])[0] # 预测为真/假的概率 label = int(model.predict([text])[0]) # 0=真实,1=虚假 return jsonify({ "label": label, "probability": round(float(prob[label]), 4), "result": "fake" if label == 1 else "real", }) if __name__ == "__main__": # 本机演示用 5000 端口,生产部署时换 gunicorn app.run(host="0.0.0.0", port=5000, debug=False)

这段接口逻辑里有几个工程细节:用request.get_json()解析请求体,前端传入{"text": "新闻内容"}这样一条 JSON;空文本返回 400 错误,避免无意义的预测;predict_proba返回的是两个类别的概率数组,下标 0 对应真实、1 对应虚假,取prob[label]得到模型当前判断的置信度。启动后可以用 curl 做一次冒烟测试(注意 Windows 下 curl 需留引号格式):

curl -X POST http://127.0.0.1:5000/predict \ -H "Content-Type: application/json" \ -d "{\"text\": \"某地今日开始实施新交通规则,所有车辆单双号限行\"}"

4. 避坑指南:虚假新闻检测项目最常翻车的 6 个节点

4.1 现象:训练集准确率 99%,测试集只有 60%

这是最典型的翻车现场,原因基本是两个:一是数据泄漏,清洗时把标签相关的信息带进了特征里;二是过拟合,模型把训练集里的新闻标题背了下来。解决方法是先检查特征构造,content里只能有标题和正文文本,绝不能拼接来源域名、发布时间这类字段;然后看训练样本量,如果只有一两千条,先加数据,加不了就把max_features和C往小调,用更强正则。

4.2 现象:标题和正文拼接后效果反而变差

原因在于拼接顺序和权重失衡。新闻标题通常很短但信息密度高,正文很长却充斥着套话,直接title + " " + text会让模型被正文的长文本淹没。我一般把标题重复一遍拼在前面,比如f"{title} {title} {text}",或者单独对标题计算 TF-IDF 特征后和正文特征拼接,这两种做法都能明显提升 F1。参数上可以把ngram_range上限从 2 调到 3,标题里常见的“据传”“辟谣”“紧急”往往以三词短语形式出现。

4.3 现象:模型把“来源缺失”当成了虚假信号

如果数据里有“来源链接”字段,清洗时顺手拼进了特征,模型会学到“有链接 = 真实,没链接 = 虚假”这种捷径。测试集里一旦出现带链接的虚假新闻,模型直接判断为真实。解决方法是清洗时把字段白名单收紧,只保留title和text,其他字段一律不进入模型输入。这个坑在答辩时被导师问到的概率极高,因为它反映的是对数据泄漏的理解深度。

4.4 现象:环境反复装不上,torch 或 transformers 一直报错

来源多是两个:一是 conda 环境和 pip 环境混用,包装到了不同的地方;二是 Python 版本和 CUDA 版本不匹配,导致 torch 装上了但 GPU 用不了。我的建议是删掉重来,新建一个干净的 conda 环境,然后按顺序安装:先装 CPU 版 torch(哪怕机器有 GPU,也先跑通流程再考虑 GPU 加速),再装 transformers 和 sklearn,最后装 Flask。装依赖时注意pip install的输出,看到ERROR: No matching distribution就确认是不是源的问题。

4.5 现象:开发文档写成实验报告,答辩时答不上来“你做了什么”

很多同学把开发文档写成了“数据预处理用了什么函数、模型用了什么算法”的流水账。实际的开发文档要有问题定义、方案对比、实验表格、接口文档和部署说明,重点回答“为什么这么设计”而不是“我用了什么”。例如写特征选择,你想用 TF-IDF 不是因为它比 BERT 好,而是因为它能在小数据量下稳定达标、训练快速、可解释性强——这是工程权衡,不是技术崇拜。源码和文档必须在同一台干净机器上能重跑,答辩时这是我最爱检查的一件事。

5. 把项目做成能演示、能答辩、能交付的完整作品

5.1 一键运行的预测脚本

前面 Flask 接口是给别人看的,自己调试时更常用的是一个独立预测脚本,输入一句新闻直接打印判定结果和置信度。我把这个脚本命名为predict.py,放在项目根目录,一句话就能跑:

# predict.py 使用训练好的模型对单条文本预测 import joblib import sys model = joblib.load("models/lr_baseline.joblib") if len(sys.argv) > 1: text = " ".join(sys.argv[1:]) else: text = input("请输入要检测的新闻文本: ") prob = model.predict_proba([text])[0] label = int(model.predict([text])[0]) print(f"判定结果: {'虚假' if label == 1 else '真实'}") print(f"置信度: {prob[label]:.4f}")

运行方式就是python predict.py 你的新闻文本内容,无需启动 Web 服务也能完成演示。这个脚本的价值在于,演示时不需要建前端页面,直接在终端里输入一句话就能看到结果;答辩现场网络环境不稳定时,这是最可靠的兜底方案。

5.2 开发文档的黄金结构

开发文档是毕业设计和课程设计评分的重要组成部分,不写或写成流水账都会很吃亏。我给自己项目定的文档结构是七章,你可以直接套用:

章节内容要点
1 项目概述背景、问题定义、目标说清楚“检测虚假新闻”具体是什么任务
2 需求分析功能需求、非功能需求接口输入输出、准确率目标、运行环境
3 总体设计系统架构、模块划分数据模块/训练模块/接口模块的依赖关系
4 详细设计与实现数据处理、特征工程、模型选型为什么选 TF-IDF + 逻辑回归,实验对比表格
5 测试与评估测试集上的准确率、F1、样例展示放 3 到 5 条真实预测结果截图
6 项目总结与展望不足与改进方向写明当前模型对短文本和反讽句识别差
7 附录环境依赖、运行说明pip install -r requirements.txt可一键重建环境

我做这类项目的个人习惯是,每次调完参数就把旧的模型文件备份成lr_baseline_v2.joblib再覆盖,不直接删除,因为答辩时导师如果问“你调过哪些参数、效果怎么变化的”,有历史文件作证比口头描述可信得多。这个习惯帮我避免过好几次“调参调丢了最佳模型”的悲剧。

无论你最后选 TF-IDF 还是预训练模型,这个项目的核心价值是让你完整走了一遍“拿到真实数据、清洗、建模型、评估、包接口、写文档”的闭环。源码能跑通是及格线,能解释每个设计决策才是拿高分的关键。希望这篇实战笔记帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 6:09:32

3个实战案例教你搞定wordpress附件地址

3个实战案例教你搞定wordpress附件地址 备案流程一头雾水,改完代码服务器直接白屏?别慌。我见过太多新手在WordPress后台上传个图,前台显示404,或者图片路径带了一堆乱七八糟的域名参数,导致SEO权重分散。今天不讲虚的,直接上 实战案例 。我们拿三个真实踩坑场景,拆解…

作者头像 李华
网站建设 2026/9/28 6:08:55

临沂网站建设教程:2026最新安全加固避坑指南

临沂网站建设教程:2026最新安全加固避坑指南 做临沂本地网站,最怕的不是代码报错,而是上线后备案卡壳,或者更糟——刚备案下来,网站就被黑客挂马。很多老板觉得安全是大厂的事,其实中小站点因为防护薄弱,反而成了攻击者的“首选目标”。2026年的网络环境,自动化扫描工具更加泛滥,如果你的网站还在用五年前…

作者头像 李华
网站建设 2026/9/28 6:08:48

YOLOv5灯光检测实战:数据构建、anchor重聚类与训练避坑指南

简介:本资源是一套基于YOLOv5实现的灯光检测项目完整训练工程,面向计算机视觉初学者与工业检测场景开发者,解决夜间/复杂光照下路灯、车灯等光源目标的精准定位与识别问题。压缩包共1580个文件,含696张标注图像(jpg&am…

作者头像 李华
网站建设 2026/9/28 6:08:33

高校大学生公寓管理系统毕设完整设计与避坑指南

高校大学生公寓管理系统设计,毕设不想掉坑就这样做说到毕业设计,每年都有大量同学选“管理系统”这类题目,特别是什么“高校大学生公寓管理系统”“高校宿舍管理系统”之类的。说实话,这个选题确实很经典——业务场景贴近校园生活…

作者头像 李华
网站建设 2026/9/28 6:08:05

2026最新什么网站教人做3d效果图报价揭秘

2026最新什么网站教人做3d效果图报价揭秘 改个需求建站公司拖一周,这种憋屈感相信不少做过网站的朋友都懂。尤其是当你急需上线一个展示3D效果图能力的作品集,或者想通过网站引流学员时,外包商的拖延简直让人抓狂。…

作者头像 李华
网站建设 2026/9/28 6:07:29

避坑指南:公司网站设计建议图解步骤与选型全解

避坑指南:公司网站设计建议图解步骤与选型全解 域名注册要选谁?服务器配置怎么搭?很多老板找建站公司,第一句话就是“我搞不懂域名和服务器”,结果被销售忽悠着买了一年期的域名,配了最贵的云服务器,网站上线后打开还要转圈。别慌,今天不聊虚的,直接上 图解步骤…

作者头像 李华