☰
Python文本相似度计算系统源码解析:Django+MySQL实现与二次开发
2026/10/19 2:21:43 网站建设 项目流程

简介:本资源为基于Python的文本相似度计算系统毕业设计源码与论文文档,面向计算机相关专业需要完成毕设的学生及自然语言处理入门开发者。内容围绕文本清洗、分词、TF-IDF关键词提取、词向量构建与余弦相似度计算展开,并借助Django搭建可视化界面,完整呈现从预处理到结果展示的技术链路,同时包含可行性分析、绪论与实验评估等论文章节。压缩包共1个docx文件,约749KB,以论文文档形式整合了系统设计说明、实现细节与目录结构,便于直接参考写作与二次开发。目前已有138人学习下载,适合需要借鉴选题思路、梳理算法流程或补充毕设材料的读者使用。

1. 从一份毕业设计源码说起:文本相似度计算系统能落地成什么

前阵子帮一个学弟看他做的文本相似度计算系统,需求很朴素:两段文本丢进去,给一个相似度分数,最好还能看到可视化结果。听起来像调个库就完事,但真动手才发现,从文本清洗、分词、去停用词,到特征向量构建、余弦相似度计算,再到 Django 页面把结果渲染出来,中间每一步都有坑。这套基于 Python 的文本相似度计算系统源码,本质上就是一个把 NLP 基础链路完整跑通的 Web 项目,技术栈是 Python + Django + MySQL,前端用 Bootstrap 搭界面,后端用 jieba 做中文分词、nltk 做英文处理,相似度算法默认走余弦相似度,同时保留了欧几里得距离、曼哈顿距离、Jaccard 相似度等可选方法。它适合两类人:一类是刚接触 NLP 想找一个能跑通的完整项目练手,另一类是要做毕业设计或课程设计,需要一套结构清晰、模块划分明确的参考实现。下面我按实际拆项目的顺序,把这份源码从架构到运行再到改造讲一遍。

2. 系统架构与模块拆解:一个请求从输入到相似度分数的完整链路

2.1 整体架构:B/S 结构下的前后端分工

这套系统采用的是典型的 B/S 架构,前端和后端通过 HTTP 协议通信。前端部分基于 Bootstrap 框架,页面包括系统首页、文本分析、文件分析、新闻管理、个人信息和用户管理几个模块。后端用 Django 做 Web 应用开发,MySQL 负责数据存储,包括预处理后的文本数据、关键词词向量表、用户信息和操作记录。

从请求链路来看,用户在文本框输入两段待比较的文本,点击“开始计算”按钮,前端通过 Ajax 把数据发到后端。后端接收到请求后,依次走预处理、特征提取、相似度计算三个核心模块,最后把相似度分数返回前端,在结果展示区域渲染出来。整个链路不算复杂,但每个环节都有值得注意的实现细节。

系统的模块划分大致是这样的:

模块职责关键技术
数据预处理模块文本清洗、分词、去停用词、词干提取jieba、nltk、正则表达式
特征提取模块词袋模型构建、词向量归一化词袋模型、TF-IDF 加权
相似度计算模块余弦相似度、欧几里得距离、Jaccard 等numpy、scikit-learn
结果展示模块相似度分数可视化、匹配结果展示Django 模板、Bootstrap
用户与新闻管理用户登录、新闻增删改查、操作记录Django ORM、MySQL

这个划分方式比较符合常规做法,预处理和特征提取分开,方便后续替换算法。比如你想把词袋模型换成 Word2Vec 或者 BERT embedding,只需要改特征提取模块,预处理和相似度计算模块基本不用动。

2.2 数据预处理模块:分词和去停用词是相似度准确率的第一道关

预处理模块是整个系统的地基。文本相似度算得准不准,很大程度上取决于这一步做得好不好。系统对输入文本的处理流程是:先清洗掉无关字符和标点符号,然后分词,再去停用词,最后做词干提取(英文场景)。

中文分词用的是 jieba 库,英文分词用 nltk。停用词过滤依赖一份停用词表,把“的”、“了”、“和”、“在”这类没有实际语义贡献的词去掉。词干提取主要针对英文,把“running”、“runs”、“ran”归到“run”这个基本形式,避免同一个词的不同形态被当成不同特征。

import jieba import re from nltk.stem import PorterStemmer def preprocess_text(text, lang='zh'): # 清洗:去掉标点、数字、特殊符号 text = re.sub(r'[^\w\s]', '', text) text = re.sub(r'\d+', '', text) if lang == 'zh': # 中文分词 words = jieba.lcut(text) else: # 英文分词 + 词干提取 words = text.lower().split() stemmer = PorterStemmer() words = [stemmer.stem(w) for w in words] # 去停用词 stopwords = load_stopwords(lang) words = [w for w in words if w not in stopwords and len(w) > 1] return words

这段代码里几个参数值得注意:lang控制中英文处理分支,len(w) > 1过滤掉单字,因为单字在中文里往往是噪声。停用词表我一般会准备两份,中文一份英文一份,放在项目目录下的stopwords/文件夹里,加载的时候按语言选择。实际跑的时候如果发现相似度分数偏高或偏低,第一个要检查的就是停用词表是不是覆盖够了。

2.3 特征提取与相似度计算:词袋模型和余弦相似度的配合

特征提取模块把分词后的结果转成向量。系统用的是词袋模型:先收集整个文本库里的所有单词,构成一个词汇表,然后对每篇文本,统计词汇表中每个词是否出现(或者出现次数),得到一个向量。之后对向量做归一化处理,方便后续计算。

相似度计算默认用余弦相似度。余弦相似度的核心思想是计算两个向量夹角的余弦值,值越接近 1 表示越相似。公式是两向量点积除以各自模长的乘积。系统里也提供了欧几里得距离、曼哈顿距离和 Jaccard 相似度作为可选方法,用户可以在界面上切换。

import numpy as np from sklearn.metrics.pairwise import cosine_similarity def compute_similarity(vec1, vec2, method='cosine'): vec1 = np.array(vec1).reshape(1, -1) vec2 = np.array(vec2).reshape(1, -1) if method == 'cosine': # 余弦相似度:值域 [-1, 1],文本场景通常 [0, 1] return cosine_similarity(vec1, vec2)[0][0] elif method == 'euclidean': # 欧几里得距离转相似度:距离越小越相似 dist = np.linalg.norm(vec1 - vec2) return 1 / (1 + dist) elif method == 'jaccard': # Jaccard:交集除以并集 set1, set2 = set(vec1[0]), set(vec2[0]) return len(set1 & set2) / len(set1 | set2)

这里有个容易翻车的地方:词袋模型构建的向量维度取决于词汇表大小,如果两段文本的词汇表不一致,直接算余弦相似度会报维度不匹配。常见做法是在预处理阶段就把整个语料库的词汇表固定下来,所有文本都映射到同一个向量空间。我一般会在项目启动时先跑一遍全量文本,生成词汇表存到数据库或本地文件,后续计算都基于这个固定词汇表。

2.4 Django 视图与表单:把算法包装成可交互的 Web 服务

后端算法写好了,接下来要把它接到 Django 的视图和表单上。系统定义了一个TextSimilarityForm表单类,包含一个文本输入框,前端用 Bootstrap 的form-control类做样式适配。

from django import forms class TextSimilarityForm(forms.Form): text1 = forms.CharField( label='文本一', widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) ) text2 = forms.CharField( label='文本二', widget=forms.Textarea(attrs={'class': 'form-control', 'rows': 4}) ) method = forms.ChoiceField( label='计算方法', choices=[ ('cosine', '余弦相似度'), ('euclidean', '欧几里得距离'), ('jaccard', 'Jaccard 相似度'), ], initial='cosine' )

视图函数接收到表单数据后,调用预处理和相似度计算模块,把结果放到 context 里渲染到模板。结果展示页面用一个只读的 textarea 显示相似度分数,同时可以加一个进度条或者仪表盘做可视化。文件分析模块的逻辑类似,只是输入从文本框变成了文件上传,限制只能选 txt 文件,读取内容后走同样的处理链路。

提示:Django 的 CSRF token 别忘了加,否则表单提交会直接 403。文件上传的 enctype 要设成multipart/form-data,不然文件读不到。

3. 本地跑起来:环境配置、数据库初始化和启动步骤

3.1 环境依赖与安装

这套系统的运行环境要求不算高:Python 3.x、Django 3.x、MySQL 数据库,加上 jieba、nltk、numpy、scikit-learn 这几个库。我一般会先建一个虚拟环境,避免和系统 Python 的包冲突。

# 创建虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装核心依赖 pip install django==3.2 pip install jieba nltk numpy scikit-learn pip install mysqlclient # MySQL 驱动 # 下载 nltk 必要数据 python -c "import nltk; nltk.download('punkt'); nltk.download('stopwords')"

mysqlclient在 Windows 上安装有时会报编译错误,常见做法是换成pymysql,然后在__init__.py里加两行pymysql.install_as_MySQLdb()做兼容。这个坑我踩过不止一次,后来干脆在 requirements 里同时写上两个,哪个能装用哪个。

3.2 数据库配置与迁移

MySQL 里先建一个库,字符集用utf8mb4,不然中文分词结果存进去可能乱码。然后在 Django 的settings.py里配置数据库连接:

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'text_similarity', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', }, } }

配置好之后执行迁移命令,Django 会自动建表:

python manage.py makemigrations python manage.py migrate python manage.py createsuperuser # 创建后台管理员 python manage.py runserver

启动后访问http://127.0.0.1:8000就能看到登录界面。系统首页会显示总用户数、总新闻数量、总操作数量这些统计信息,这些数据都是从 MySQL 里实时查出来的。

3.3 初始数据准备与功能验证

系统跑起来之后,新闻管理模块是空的,需要先录入一些新闻文本作为语料库。可以通过 Django admin 后台批量导入,也可以写一个 management command 从 txt 文件批量读取。语料库准备好之后,文本分析模块才能做“输入一段文本,匹配最相似新闻”的功能。

验证的时候建议按这个顺序走:先测两段完全相同的文本,相似度应该是 1.0;再测两段完全不相关的文本,相似度应该接近 0;最后测两段语义相近但用词不同的文本,看看分数是否合理。如果完全相同文本算出来不是 1.0,大概率是预处理阶段把某些词过滤掉了导致向量不一致,回头检查停用词表和分词逻辑。

注意:jieba 首次加载词典会慢一点,如果响应时间要求 1 秒内,建议在 Django 启动时做一次预热,或者用jieba.initialize()提前加载。

4. 避坑与排查:跑这套源码时最容易翻车的几个地方

4.1 中文乱码:从数据库到页面的编码链路

现象是页面上显示的中文变成问号或者方块。原因通常出在三个地方:MySQL 建库时字符集不是 utf8mb4、Django 数据库配置里没加 charset 选项、HTML 模板没声明 UTF-8。解决方法是逐层检查,建库语句用CREATE DATABASE text_similarity CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,settings 里加'OPTIONS': {'charset': 'utf8mb4'},模板头部加<meta charset="UTF-8">。

4.2 相似度分数异常:向量维度不一致

现象是计算时报shapes not aligned或者结果明显不对。原因是两段文本各自构建词袋向量,词汇表不一致导致维度不同。解决办法是在预处理阶段统一词汇表,把所有文本映射到同一个向量空间。我一般会在项目初始化时先遍历一遍语料库,生成全局词汇表存到本地 JSON 文件,后续每次计算都加载这个词汇表。

4.3 文件上传失败:enctype 和文件类型限制

现象是选择 txt 文件后点击计算没反应,或者后端收不到文件。原因是表单没有设置enctype="multipart/form-data",或者视图函数里没有从request.FILES取文件。另外系统限制只能上传 txt,如果传了其他格式要在前端做校验,后端也要做二次校验,避免报错。

4.4 停用词表加载失败:路径问题

现象是预处理结果里停用词没被过滤掉。原因是停用词表的文件路径写成了相对路径,Django 运行目录和项目目录不一致时找不到文件。解决办法是用os.path.join(BASE_DIR, 'stopwords', 'zh.txt')拼绝对路径,或者在 settings 里配置一个STOPWORDS_DIR变量统一管理。

4.5 性能问题:大文本计算卡顿

现象是输入几千字的文本后页面转圈很久。原因是词袋模型维度爆炸,余弦相似度计算量随词汇表大小线性增长。常见优化手段是限制词汇表大小(只保留 TF-IDF 最高的 N 个词),或者用稀疏矩阵存储向量。如果只是做毕业设计演示,限制输入文本长度在 500 字以内也能缓解。

5. 二次开发与改造:从能跑到好用,几个具体方向

这套源码跑通之后,如果想继续改,有几个方向比较实用。第一个是把词袋模型换成 TF-IDF 加权,甚至换成 Word2Vec 或 BERT 的句向量。词袋模型最大的问题是忽略词序和语义,两段意思相近但用词不同的文本算出来相似度可能很低。换成预训练词向量之后,语义相似度会准很多。具体做法是在特征提取模块加一个embedding分支,用sentence-transformers或者jieba配合word2vec生成句向量,相似度计算模块不用动。

第二个方向是加缓存。相似度计算是 CPU 密集型操作,同样的文本对反复计算很浪费。我一般会在视图层加一个基于文本哈希的缓存,用 Django 的cache框架或者 Redis,key 是两段文本的 MD5 拼接,value 是相似度分数。这样第二次请求同样的文本对就能直接返回。

第三个方向是把算法模块抽成独立的 API。现在算法逻辑和 Django 视图耦合在一起,如果想给移动端或者其他系统调用,得把预处理、特征提取、相似度计算封装成 RESTful 接口,用 Django REST framework 暴露出去。改造的时候注意把算法模块的依赖(jieba、nltk)和 Web 框架的依赖分开,方便单独部署。

# 改造示例:带缓存的相似度计算视图 from django.core.cache import cache import hashlib def calculate_similarity(request): if request.method == 'POST': text1 = request.POST.get('text1', '') text2 = request.POST.get('text2', '') method = request.POST.get('method', 'cosine') # 生成缓存 key cache_key = hashlib.md5( f"{text1}|{text2}|{method}".encode('utf-8') ).hexdigest() score = cache.get(cache_key) if score is None: words1 = preprocess_text(text1) words2 = preprocess_text(text2) vec1, vec2 = build_vectors(words1, words2) score = compute_similarity(vec1, vec2, method) cache.set(cache_key, score, 3600) # 缓存 1 小时 return render(request, 'result.html', {'similarity': score})

这段改造代码的关键点是缓存 key 的生成方式,把两段文本和计算方法拼在一起做 MD5,保证不同输入对应不同 key。缓存时间设 1 小时,对于演示场景够用了。如果文本量特别大,还可以考虑把预处理结果也缓存起来,避免重复分词。

最后一个建议是加日志。相似度计算这种模块,出问题的时候如果没有日志,排查起来就是黑匣子。我习惯在预处理和计算两个环节各加一条 debug 日志,记录输入文本长度、分词后词数、最终分数,这样一旦分数异常,翻日志就能定位是哪一步出了问题。从那以后我每次改算法模块,都强制走一遍“相同文本→不相关文本→语义相近文本”的验证流程,确认三个基准 case 都正常才继续往下做。希望帮到你。

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询