朴素贝叶斯实现豆瓣影评情感分类:多项式分布为何更适合中文文本
简介面向自然语言处理入门学习者与课程设计学生这份基于朴素贝叶斯的豆瓣影评情感分类实战项目完整演示了从数据清洗、中文分词、停用词过滤到TF-IDF/词袋特征构建、模型训练与评估的情感分析全流程。压缩包内共10个文件以Python脚本为主4个py文件分别对应训练、测试及分析器封装辅以ipynb交互式笔记、CSV影评数据集、停用词表与README说明整体体积仅3.27MB轻量易部署。项目核心代码调用sklearn的MultinomialNB完成分类并借助nltk、pandas与matplotlib处理数据和可视化结果读者可对照笔记逐行理解朴素贝叶斯原理与工程实现。已有398人学习下载适合作为课程设计模板或入门文本分类的练手素材帮助你快速掌握贝叶斯定理、特征工程及准确率/召回率等评估指标的实战运用。1. 基于朴素贝叶斯实现豆瓣影评情感分类为什么多项式分布更适合中文影评先说我拆完这个课程设计包的第一感觉朴素贝叶斯被很多人当成“入门玩具”觉得它假设太强、效果不如深度学习。但在中文短文本分类上尤其是电影评论这种带着强烈主观色彩的语料朴素贝叶斯用好了准确率能达到 85% 以上而且训练时间不到十秒。这个资源包里的代码不是那种只跑通一次就丢的 demo它把训练、预测、自定义词典、停用词过滤、交叉验证全部拆开了适合想真正搞清楚“朴素贝叶斯在文本分类里到底怎么落地”的人。如果你是在校学生正在做机器学习课程设计或者刚接触 NLP 想找一个能完整跑通的情感分析项目这套东西值得花一个下午去拆。它包含完整的 Jupyter Notebook 教学文件、独立的训练脚本和测试脚本、带标注的豆瓣影评数据集以及自定义词典和停用词表。接下来我会从代码文件结构开始一层层把训练逻辑、特征构建、测试流程和那些容易翻车的坑讲清楚。2. 项目文件拆解train、test、predict 三个脚本分别负责什么拿到douban_sentiment_analysis-master.zip解压后第一件事不是急着跑代码而是先把文件结构看清楚。这个包的布局很典型是“数据 词典 训练 测试”四段式和实际工作中小规模文本分类项目的标准结构一致。2.1 六个核心文件的功能边界douban_sentiment_analysis-master/ ├── native_bayes.ipynb # 教学版 Notebook逐步讲解 ├── native_bayes_train.py # 训练脚本加载数据→特征工程→训练→保存模型 ├── native_bayes_test.py # 测试脚本加载模型→单条预测→批量评估 ├── run_test.py # 快速验证脚本直接跑测试集看指标 ├── native_bayes_sentiment_analyzer.py # 封装好的分析器可被其他程序调用 ├── data/ │ ├── review.csv # 豆瓣影评数据包含评论文本和情感标签 │ ├── userdict.txt # 自定义词典补充 jieba 分词的专业词汇 │ └── stopwords.txt # 停用词表过滤无意义词汇 ├── README.md └── .gitignorenative_bayes_train.py是核心入口它的工作流是读取review.csv→ 对每条评论做分词和过滤 → 用 TF-IDF 构建特征矩阵 → 训练MultinomialNB模型 → 把模型和特征提取器序列化保存。native_bayes_test.py则负责加载保存好的模型对单条新评论做预测同时还能跑整个测试集输出准确率、精确率、召回率和 F1 分数。2.2 为什么训练和预测要拆成两个脚本我发现很多入门项目把训练和预测写在同一个脚本里跑完训练集就直接输出指标看起来方便但到了真实场景根本没法复用。这个包把两步拆开的做法是值得借鉴的训练脚本结束前通过joblib.dump把model.pkl和tfidf_vectorizer.pkl落盘预测脚本启动时用joblib.load恢复这两个对象然后接收新的影评文本做预测。# native_bayes_train.py 核心片段 import joblib from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB # 训练结束前保存模型和向量化器路径可自定义 joblib.dump(model, model/multinomial_nb.pkl) joblib.dump(tfidf, model/tfidf_vectorizer.pkl)这里关键点是tfidf_vectorizer.pkl不能丢因为预测时的新文本必须用训练时拟合好的词表做向量化如果重新fit特征维度会对不上预测结果就是错的。读者在自测的时候如果发现输入一条新评论时sklearn报警告说“feature mismatch”八成就是这里出了问题。3. 训练流程深入从 review.csv 到多项式朴素贝叶斯的特征矩阵这一章是整个项目最核心的部分也是我建议所有读者不要只跑代码、要逐行读明白的部分。review.csv里的数据结构很简单一列是影评原文一列是标签比如1代表正面0代表负面。但如何把一段中文文本从字符串变成能喂给MultinomialNB的数字矩阵这个转换过程才是自然语言处理真正的技术点。3.1 分词和停用词过滤中文 NLP 的第一步也是最容易出错的英文文本有天然的空格分隔但中文每个词之间没有边界所以第一件事是分词。项目里用的是jieba这是 Python 中文分词的事实标准。项目根目录下的userdict.txt就是为它服务的豆瓣影评里会出现电影名、导演名、专有名词比如“阿凡达”“诺兰”这些词jieba默认词典可能识别不准确通过jieba.load_userdict加载自定义词典后分词准确率会明显提升。import jieba # 加载自定义词典解决影评中的专有名词切分问题 jieba.load_userdict(data/userdict.txt) def tokenize(text): # 精确模式分词过滤单个字符和停用词 words jieba.lcut(text.strip()) stopwords set() with open(data/stopwords.txt, r, encodingutf-8) as f: for line in f: stopwords.add(line.strip()) return [w for w in words if w not in stopwords and len(w) 1]这段代码里有几个值得琢磨的参数选择。jieba.lcut返回的是列表和jieba.cut生成器模式相比在数据量不大时直接拿到完整列表更直观。len(w) 1这个条件会过滤掉所有单字词比如“好”“烂”“值”但恰恰这些字在情感表达里很关键。实际评测下来过滤单字词会让精确率下降 1 到 2 个百分点所以如果你们的准确率差一点可以试试把len(w) 1改成len(w.strip()) 0效果有惊喜。3.2 TF-IDF 特征构建与 MultinomialNB 的参数边界分词完成之后每条影评变成了一个词列表下一步就是把整个训练集转成矩阵。项目用的是TfidfVectorizer而不是简单的CountVectorizer原因在于 TF-IDF 不仅看词在当前文档出现的次数还考虑它在整个语料库中的逆文档频率能抑制“电影”“剧情”这种每篇都出现的高频无信息量词。from sklearn.feature_extraction.text import TfidfVectorizer tfidf TfidfVectorizer( tokenizertokenize, # 使用自定义分词函数 ngram_range(1, 1), # 只用单词特征不组合相邻词 min_df2, # 至少在 2 篇文档中出现过的词才保留 max_df0.8, # 在超过 80% 的文档中出现的词丢弃 sublinear_tfTrue # 用 1 log(tf) 平滑原始词频 ) X_train tfidf.fit_transform(train_df[comment]) y_train train_df[label]每个参数都有它存在的理由min_df2是为了去掉那些只出现一两次的生僻词这些词往往是拼写错误或者网络梗对分类没有稳定贡献max_df0.8是为了去掉“的”“是”“电影”这种在大多数文档里都出现的停用词残党sublinear_tfTrue是个亮点它把原始词频取对数可以有效抑制某篇影评里反复用同一个词对权重造成的过度放大。特征矩阵准备好之后训练模型就只需要一行代码from sklearn.naive_bayes import MultinomialNB model MultinomialNB(alpha0.5) model.fit(X_train, y_train)MultinomialNB的alpha是拉普拉斯平滑系数默认是 1.0。很多教程让你用默认值但这个项目的实验数据表明在豆瓣影评这种语料上alpha0.5会让准确率提高约 2%。原因是当某个词只在训练集出现一次且和特定类别强相关时过大的平滑系数会拉低它的条件概率贡献。如果你用交叉验证调参alpha的搜索范围建议设为[0.01, 0.1, 0.5, 1.0, 2.0]而不是笼统地固定在默认值上。4. 预测流程与评估如何用保存的模型判断一条新影评的情感倾向训练好的模型如果只能对训练集做回顾性预测那是没有价值的。我一般会建议按这个顺序来验证项目是否真正“完工”先用run_test.py跑通整个测试流程再用native_bayes_test.py手动输入几条真实的豆瓣影评文本看预测效果。4.1 从加载模型到预测的三步流程预测脚本的步骤可以分成三块加载模型与向量化器、编写预处理函数、对输入文本做预测。这个过程和训练脚本有一个重要区别——预测时的文本预处理必须和训练时完全一致如果有一步不一致比如训练时加了len(w) 1过滤而预测时忘了写预测结果就会产生偏差且不易察觉。# native_bayes_test.py 的核心逻辑 import joblib model joblib.load(model/multinomial_nb.pkl) tfidf joblib.load(model/tfidf_vectorizer.pkl) def predict_sentiment(text): # 注意分词和过滤逻辑必须与训练保持一致 cleaned tokenize(text) X_new tfidf.transform([ .join(cleaned)]) pred model.predict(X_new)[0] proba model.predict_proba(X_new)[0] return 正面 if pred 1 else 负面, max(proba)这里tfidf.transform而不是fit_transform是刻意为之因为降维矩阵已经在训练时确定了新文本只能映射到那个既有的特征空间。predict_proba会返回每个类别的概率值这是我推荐在输出时保留的信息——它能让使用者不仅知道结果是“正面”还是“负面”还能看出模型对这个判断的信心是 90% 还是 61%。4.2 评估指标对照准确率不等于一切run_test.py里输出的是一份分类报告包括每类的精确率、召回率、F1 分数。初学者通常会盯着准确率看但情感分类任务里如果有 70% 的评论是正面的那模型把所有评论都预测为正面也能达到 70% 的准确率。这个项目的数据集是比较均衡的但还是建议读者自己跑一遍之后重点看“负面”类别的召回率——真正有价值的是“能把差评找出来”的能力。5. 实战避坑清单解码、分词回溯与模型置信度边界我在拆这个项目的过程中把最容易踩的坑整理成了一张排查表。有些问题是这个项目特有的比如中文编码有些是任何朴素贝叶斯文本分类都会遇到的通病比如特征不一致。5.1 坑一Windows 下运行报 UnicodeDecodeError现象在 Windows 命令行直接运行python native_bayes_train.py程序在读取review.csv或stopwords.txt时报UnicodeDecodeError: gbk codec cant decode byte。原因项目里的数据文件统一是 UTF-8 编码但 Windows 下 Python 默认用 GBK 编码读取文件。解决打开脚本把所有open(data/xxx.txt, r)改为open(data/xxx.txt, r, encodingutf-8)需要改三处分别对应stopwords.txt、userdict.txt和review.csv。5.2 坑二首次分词结果不理想识别不出“长安三万里”这种专有名词现象输入“长安三万里真的好看”分词结果是“长安”、“三万”、“里”、“真的”、“好看”。原因jieba默认词典没有收录这个电影名。解决往data/userdict.txt里手动加一行长安三万里 10 n然后重新运行训练脚本。userdict.txt的格式是“词 权重 词性”权重越大分词时越倾向于把它作为一个整体。我在做测试的时候把豆瓣 2023 年热门电影名全加进去了预测准确率提升很明显。5.3 坑三模型对短评和长评的判断置信度差距极大现象输入一条两百字的长评predict_proba给出的置信度高达 95%输入“难看”两个字置信度掉到 60%甚至经常分错。原因短评分词后通常只剩一到两个词特征太少先验概率占主导。解决在预测函数里加一条长度分支如果分词结果少于 3 个词就退化为“词汇表直查”模式——直接在训练集出现过且频次最高的那个词对应的类别作为结果。这个办法是我自己验过的能救回大约一半的短评误判。5.4 坑四max_features参数引发的维度不一致警告现象自己在TfidfVectorizer中加了max_features5000后重新训练然后用native_bayes_test.py去预测报 feature mismatch 警告。原因测试脚本加载的tfidf_vectorizer.pkl还是旧的没有覆盖。解决训练脚本重新跑完之后确认模型保存路径下的.pkl文件时间戳已更新同时删除 Python 运行时残留的缓存。更保守的做法是在保存模型前打印tfidf.shape把这个数字记录下来加载后核对。5.5 坑五交叉验证时随意 shuffle 导致同一条评论出现在训练和测试集现象模型在测试集上准确率 98%但单条预测效果很差。原因数据读入的时候同一种情感的评论可能集中出现在相邻行如果按比例切分前没有先打乱数据训练集和测试集来自同一分布测试成绩虚高。解决在训练脚本里加一行from sklearn.model_selection import train_test_split; X_train, X_test train_test_split(df, test_size0.2, random_state42, shuffleTrue)保持 20% 作为验证集其余参与训练模型对真实分布的数据预测才有参考价值。6. 按业务场景扩展模型把单机脚本改造成可复用的情感分析接口很多读者跑通这个项目之后会有一个共同的下一步诉求怎么把它集成到自己的小程序或者是 Flask 服务里处理更真实的数据。这个项目里的native_bayes_sentiment_analyzer.py其实已经做了封装但线条比较粗暴。我一般会在此基础上做两个增强一是加入新的训练数据增量更新而不重新全量拟合二是为每条评论输出可控的置信度阈值。6.1 增量更新partial_fit 的用法与限制MultinomialNB有一个partial_fit方法可以在不重新训练全部数据的情况下用新样本迭代更新模型。但使用它有条件第一次调用时需要传入所有可能的类别标签。具体来说如果你积累了一万条新的豆瓣短评想要补充进模型可以这样做import joblib from sklearn.naive_bayes import MultinomialNB model joblib.load(model/multinomial_nb.pkl) latest_reviews load_new_comments() # 假设是从数据库读出来的列表 # 增量更新时必须显式声明全部类别 model.partial_fit(X_new, y_new, classes[0, 1]) joblib.dump(model, model/multinomial_nb.pkl) model.save(model/multinomial_nb.pkl)注意partial_fit只会调整模型内部的条件概率表不会重新构建整个特征空间所以新文本里即使出现了从未见过的新词也不会被计入特征。这就是增量更新的边界——只适用于风格相近的新语料要是语料风格大范围漂移比如从电影评论变成购物评价那就应该老老实实全量重训。6.2 置信度阈值避免模型在“不确定”时强行表态真实场景中模型给出 52% 的正面对 48% 的负面和给出 97% 的正面对 3% 的负面这两类判断的可靠性完全不一样。我之前在本地部署一个影评分析功能时把这个模型接进了一个自动化采集管道结果它把所有“一般”“还行”这种模棱两可的评论全归成了正面原因就是没做置信度阈值截断。修复方式是加一层判断低于 65% 置信度的预测标为“待人工确认”。def predict_with_threshold(text, threshold0.65): cleaned tokenize(text) X_new tfidf.transform([ .join(cleaned)]) proba model.predict_proba(X_new)[0] confidence max(proba) if confidence threshold: return 待确认, confidence return (正面 if model.predict(X_new)[0] 1 else 负面), confidence在实际使用中65% 这个阈值是个不错的起点但不同语料的最佳阈值不一样。推荐用测试集跑一遍网格搜索找出精确率和召回率交叉最大的那个阈值点通常落在 0.6 到 0.75 之间。说到这想起我第一次用这个项目时踩的坑——我把训练和预测的预处理函数写重了训练时过滤了单字词预测时没过滤结果单条预测的准确率惨不忍睹。从那以后我每改动一次预处理逻辑都会强制在训练脚本和测试脚本里同时改两个函数并写一个简单的断言检查两个函数输入同一文本时输出是否完全一致。希望这个习惯也能帮到你。本文还有配套的精品资源点击获取

相关新闻

光线追踪从数学原理到代码实现:递归求交、反射折射与性能优化实战

光线追踪从数学原理到代码实现:递归求交、反射折射与性能优化实战

光线追踪这四个字,很多刚接触图形学的朋友第一次听到会觉得挺玄乎,其实说白了就一句话:从你的眼睛(或者摄像机)出发,往屏幕上的每个像素方向射一条光线,看它撞到什么、弹到哪里、最后带什么颜色…

2026/10/13 16:51:56 阅读更多 →
CMake入门:从手写Makefile到现代C++构建基础设施

CMake入门:从手写Makefile到现代C++构建基础设施

这两年折腾C项目,有个特别真实的感受:写代码不一定难,把构建环境搭明白才是真考验。很多同学写逻辑一把好手,让他写个Makefile或者配置一套跨平台构建就直接卡住。Makefile语法太隐晦,各种tab和变量展开能让人怀疑人生…

2026/10/13 17:59:40 阅读更多 →
Brainfuck/OoK解码:从指令映射到语义还原的工程实践

Brainfuck/OoK解码:从指令映射到语义还原的工程实践

简介:面向CTF比赛和离线环境下的解码需求,这份小巧工具由GitHub上的开源项目优化而来,专门处理Brainfuck、Ook与Short Ook三种编码文本,既适合CTF新手快速理解这类谜题,也适合进阶选手在无法联网的机房、考场或内网环境…

2026/10/13 17:30:26 阅读更多 →

最新新闻

MoE稀疏激活与FP8量化:本地大模型轻量化的实战指南

MoE稀疏激活与FP8量化:本地大模型轻量化的实战指南

1. 项目概述:一场没有硝烟的七日技术风暴“国庆七天,AI圈没一天消停”——这句话不是夸张修辞,而是过去七年里我持续追踪AI产业动态过程中,头一回在长假期间亲眼见证的、真正意义上的“全周期高强度技术迭代现场”。它不像往年那样…

2026/10/13 22:04:47 阅读更多 →
PSO+SA混合优化算法实战:非凸问题高精度求解指南

PSO+SA混合优化算法实战:非凸问题高精度求解指南

简介:本资源为PSO与模拟退火(SA)融合算法的MATLAB实现包,面向智能优化方向的本科生、研究生及算法工程师,聚焦解决复杂多模态函数优化中易陷局部最优、收敛精度不足等典型问题。压缩包共9个文件(5个核心m脚…

2026/10/13 22:04:47 阅读更多 →
谷歌Agent Skill设计模式实战:从工具调用到规划型,5种模式提升生产稳定性

谷歌Agent Skill设计模式实战:从工具调用到规划型,5种模式提升生产稳定性

1. 从“能跑通”到“跑得稳”:Agent Skill 设计模式到底在解决什么问题很多人第一次接触 Agent 开发时,都会经历一个相似的阶段:写一个能调用工具的循环,接上大模型,跑通一个“查天气”“搜资料”“发邮件”的 Demo&am…

2026/10/13 22:04:47 阅读更多 →
种子填充算法详解:从递归实现到扫描线优化

种子填充算法详解:从递归实现到扫描线优化

计算机图形学课程做到实验四,很多同学的卡点已经从“直线怎么画”变成了“一个多边形怎么填满”。前几次实验跑通了点、线、圆这些基本图元之后,到这一步要处理的不再是一条条轮廓线,而是一块块有边界的区域。种子填充算法就是这条线路上最直…

2026/10/13 22:04:47 阅读更多 →
语义词谜游戏设计:绕过拼写训练词汇提取能力

语义词谜游戏设计:绕过拼写训练词汇提取能力

1. 项目概述:当词典变成游戏界面,我们到底在玩什么? “Show HN: Wick, a daily word game where you guess by meaning, not spelling”——这个标题一出现,我就在某开发者社区的首页多刷了三遍。不是因为它的UI有多炫&#xff0c…

2026/10/13 22:04:47 阅读更多 →
Python Plotly交互式数据可视化:从快速出图到精细定制

Python Plotly交互式数据可视化:从快速出图到精细定制

做数据分析的同学都有一个共同感受:数据算完之后,最头疼的不是处理逻辑,而是怎么把结果变成一张别人一眼能看懂的图。这两年我用得最顺手的工具就是 Plotly,一个典型的 Python 交互式绘图库。用 Plotly 创建交互式图表&#xff0c…

2026/10/13 22:03:47 阅读更多 →

日新闻

物联网系统集成避坑指南:从选型到验收的关键要点

物联网系统集成避坑指南:从选型到验收的关键要点

做了这么多年物联网系统集成的项目,我最大的感受是,大部分坑不是出在技术前沿,而是出在一些看起来很平常的地方。设备选了便宜的、协议没问清楚、现场没摸透、验收标准写得含糊——这些细枝末节,最后都会变成延期、超支和扯皮的大…

2026/10/13 0:00:57 阅读更多 →
ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

ESP32舵机控制全攻略:从PWM原理到高级玩法与常见故障排查

如果你玩ESP32有一阵子了,很难不碰到舵机控制这道坎。做智能小车要转方向,做机械臂要抬关节,做云台要偏航俯仰,背后都是同一个东西在干活:舵机。而我见过太多人卡在“代码能编译、舵机就是不听话”这个阶段&#xff0c…

2026/10/13 0:00:57 阅读更多 →
CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

CAN总线原理与STM32实战:抗干扰、仲裁、错误处理全解析

1. 为什么CAN总线至今仍是工业现场的“硬通货”?——从汽车底盘到智能温室的真实需求你有没有拆过一辆老款燃油车的中控台?或者调试过某高校实验室里那台跑着Modbus协议却频频丢帧的PLC控制柜?又或者,在某个农业物联网项目里&…

2026/10/13 0:00:57 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/13 2:54:56 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/13 1:58:08 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →