ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Python微博情感分析系统源码拆解:Scrapy爬虫+BERT+LSTM全栈实战

Python微博情感分析系统源码拆解:Scrapy爬虫+BERT+LSTM全栈实战 简介这是一套面向计算机专业学生与NLP入门者的微博情感分析完整源码围绕微博数据爬取、清洗、情感判别与结果可视化展开可用于课程设计、毕业设计或情感分析实战练手。压缩包共73个文件约517KB以20个Python源码为核心辅以15个pyc编译文件、5个Vue组件、4个JavaScript脚本及若干svg、xml、json配置与图标资源前后端结构清晰。系统采用Scrapy框架抓取微博推文与用户信息通过自定义脚本完成繁简转换、URL去除与表情包处理并构建BERT与LSTM混合模型进行情感分类最后以柱状图展示各情感标签下的模型表现。前端基于Vue搭建后端提供爬虫、模型训练与预测模块目录划分明确便于按数据流逐步阅读与二次开发。目前已有113人学习适合希望掌握从数据采集到模型部署全流程的读者参考。1. 微博情感分析系统拆包一份能跑通的 Python 全栈源码长什么样微博评论区的情绪风向做舆情和运营的同行都懂——一条热搜底下几万条博文靠人眼翻根本翻不完。这份基于 Python 的微博情感分析系统源码解决的正是「爬下来 → 洗干净 → 判情绪 → 看分布」这条链路。它把 Scrapy 爬虫、BERTLSTM 混合模型、Vue 前端和 Flask 后端打包在一起属于少见的端到端可复现项目。适合谁正在做 python 爬虫 数据分析毕设的学生、想给舆情监控搭原型的工程师、以及需要一份能改能扩的情感分类代码库的从业者。下面按「资源是什么 → 怎么用 → 坑在哪」的顺序拆开讲每一步都落到能抄的参数和命令上。2. 环境搭建与依赖安装从 requirements.txt 到能启动的 Flask 服务拿到一个 zip 源码包第一件事不是急着python app.py而是先把目录结构和依赖关系摸清楚。这份项目的目录分三块webapps是 Vue 前端back-end是爬虫和模型根目录下还有pipelines.py、app.py这类入口文件。很多人翻车就翻在「依赖装错版本」上尤其是 BERT 相关的 transformers 和 torch版本差一个号就报一堆看不懂的错。2.1 目录结构与模块职责先把关键文件认全后面排错才知道该看哪个路径职责back-end/spiders/Scrapy 爬虫tweet.py抓博文user.py抓用户信息back-end/models/MyModel.py定义 BERTLSTMTrainer.py训练循环MyDataSet.py数据集封装back-end/predictor/Predictor.py加载模型做推理的入口back-end/CleanData.py繁简转换、去 URL、表情转文字back-end/app.pyFlask 接口层前端调它拿结果webapps/src/Vue 组件与路由App.vue是根组件认目录的意义在于当模型报错时你能立刻判断是数据问题MyDataSet.py还是网络结构问题MyModel.py而不是满项目乱搜。2.2 Python 环境与依赖安装建议用 conda 建独立环境别污染系统 Python。python 安装教程网上一大把这里只说这个项目要的# 建环境Python 版本建议 3.7源码里有 cpython-37 的 pyc说明作者用的 3.7 conda create -n weibo_sa python3.7 conda activate weibo_sa # 装后端依赖requirements.txt 在 back-end 目录下 cd back-end pip install -r requirements.txt # 如果 torch 装得慢指定国内镜像 pip install torch1.8.0 -i https://pypi.tuna.tsinghua.edu.cn/simple逻辑说明requirements.txt里通常锁了 Scrapy、transformers、torch、flask 这几类。参数上Python 版本别乱升到 3.11老版本 transformers 在新解释器上容易出ImportError。装完先pip list核对 torch 和 transformers 版本这是后面模型能不能加载的前提。2.3 前端依赖与启动前端是标准 Vue 工程package.json里定义了脚本cd webapps npm install # 装依赖node 建议 14 或 16 npm run serve # 启动开发服务默认 8080npm install卡住多半是网络问题可以配npm config set registry https://registry.npmmirror.com。启动后前端会去请求 Flask 后端所以后端得先跑起来否则页面数据是空的——这个顺序别搞反。3. 数据爬取与清洗Scrapy 抓博文 繁简/表情归一化情感分析的上限由数据质量决定。爬下来的微博文本里混着 URL、表情符号、繁体字、 提及直接喂给模型准确率会掉一大截。这一章讲爬虫怎么配、清洗脚本怎么改。3.1 Scrapy 爬虫配置与运行爬虫入口是run_spider.py它调用 Scrapy 的CrawlerProcess启动tweet这个 spider# run_spider.py 核心逻辑 from scrapy.crawler import CrawlerProcess from scrapy.utils.project import get_project_settings from spiders.tweet import TweetSpider process CrawlerProcess(get_project_settings()) process.crawl(TweetSpider) process.start() # 阻塞式启动跑完才退出逻辑说明get_project_settings()会读settings.py里的配置包括并发数、下载延迟、User-Agent 和 pipelines。参数上重点看两个DOWNLOAD_DELAY控制请求间隔设太小容易被限流CONCURRENT_REQUESTS控制并发抓公开数据时别开太高。middlewares.py里通常放了随机 UA 中间件这是降低被封概率的常见做法。抓取目标在tweet.py里定义一般会拼搜索接口的 URL把关键词、页码作为参数传进去。想换关键词改 spider 里的start_urls或start_requests即可。3.2 数据清洗CleanData.py 里的四类处理CleanData.py是数据进模型前的最后一道关常见处理有四类import re from opencc import OpenCC # 繁简转换 cc OpenCC(t2s) # 繁体转简体 def clean_text(text): text cc.convert(text) # 1. 繁简归一 text re.sub(rhttp\S, , text) # 2. 去 URL text re.sub(r[\w\u4e00-\u9fa5], , text) # 3. 去 提及 text text.replace([微笑], 开心) # 4. 表情转文字 return text.strip()逻辑说明OpenCC(t2s)是繁转简的标准配置港澳台语料多的场景必加。去 URL 的正则http\S匹配到空格为止够用。表情转文字这一步最容易被忽略——微博的[微笑]这类占位符如果直接删掉会丢失情绪信号映射成「开心」这类词反而给模型加了特征。参数上表情映射表建议自己维护一份覆盖高频表情即可不必求全。清洗完的数据一般落到 CSV 或数据库pipelines.py负责这个落库动作。跑完爬虫后先抽查几十条确认没有乱码和空文本再进训练环节。4. BERTLSTM 混合模型结构、训练与推理落地这是整个项目的技术核心。纯 BERT 做分类已经够强为什么还要接 LSTM因为微博文本短、口语化、上下文跳跃BERT 出的是每个 token 的向量接一层 LSTM 能把序列的时序依赖再抽一遍对反讽、转折这类表达更敏感。下面拆结构、训练和推理。4.1 MyModel.py 的网络结构模型定义在MyModel.py典型写法是 BERT 提特征、LSTM 做序列建模、全连接出分类import torch.nn as nn from transformers import BertModel class BertLstmClassifier(nn.Module): def __init__(self, num_labels3, hidden_size256): super().__init__() self.bert BertModel.from_pretrained(bert-base-chinese) self.lstm nn.LSTM( input_size768, # BERT base 输出维度 hidden_sizehidden_size, num_layers1, batch_firstTrue, bidirectionalTrue ) self.fc nn.Linear(hidden_size * 2, num_labels) # 双向要乘 2 def forward(self, input_ids, attention_mask): out self.bert(input_ids, attention_maskattention_mask) seq out.last_hidden_state # [batch, seq_len, 768] lstm_out, _ self.lstm(seq) pooled lstm_out[:, -1, :] # 取最后时刻 return self.fc(pooled)逻辑说明bert-base-chinese是中文场景的默认选择768 是它的隐藏维度别写错。LSTM 设bidirectionalTrue后输出维度翻倍所以全连接层输入是hidden_size * 2这是新手最容易算错的地方。num_labels3对应积极/中性/消极三分类如果你的标签是二分类就改成 2。取lstm_out[:, -1, :]是取序列最后一步也可以改成对时间维做平均池化效果因数据而异。4.2 Trainer.py 训练循环与关键参数Trainer.py管训练核心是优化器、学习率和 epoch 的配合from transformers import AdamW, get_linear_schedule_with_warmup optimizer AdamW(model.parameters(), lr2e-5, weight_decay0.01) scheduler get_linear_schedule_with_warmup( optimizer, num_warmup_stepsint(0.1 * total_steps), # 10% 步数做 warmup num_training_stepstotal_steps ) for epoch in range(5): model.train() for batch in train_loader: outputs model(batch[input_ids], batch[attention_mask]) loss criterion(outputs, batch[labels]) loss.backward() optimizer.step() scheduler.step() optimizer.zero_grad()逻辑说明BERT 微调的学习率要小2e-5是经验值设成 1e-3 会直接把预训练权重冲垮。weight_decay0.01抑制过拟合。warmup 占 10% 步数是常见做法能让训练初期更稳。epoch 一般 35 就够再多容易过拟合看验证集 loss 回升就停。MyDataSet.py负责把文本转成input_ids和attention_mask注意 padding 到统一长度max_length设 128 对微博够用。4.3 Predictor.py 推理与结果落库训练完的权重存下来推理走Predictor.pyfrom predictor.Predictor import Predictor predictor Predictor(model_pathmodels/best_model.pt) result predictor.predict(今天心情特别好阳光明媚) print(result) # {label: 积极, score: 0.97}逻辑说明Predictor内部会做和训练一致的清洗和 tokenize这一步必须和训练时对齐否则线上线下不一致预测结果会飘。score是 softmax 后的置信度低于 0.6 的建议人工复核。Flask 的app.py把predict包成 HTTP 接口前端App.vue调它拿结果并画柱状图。5. 避坑与排查模型加载、编码、前后端联调的血泪经验这一章是踩坑合集每条按「现象 → 原因 → 解决」写都是这类项目里高频翻车点。现象一OSError: Cant load weights for bert-base-chinese。原因本地没有预训练权重又连不上模型仓库或者缓存目录权限不对。 解决提前把bert-base-chinese下到本地改from_pretrained的路径为本地目录确认~/.cache/huggingface可写。现象二爬下来的中文全是乱码。原因响应编码没指定Scrapy 默认按响应头猜微博接口常返回 UTF-8 但头里没写。 解决在 spider 里显式response.encoding utf-8或在settings.py里配FEED_EXPORT_ENCODING utf-8。现象三前端页面能开但数据是空的。原因Flask 后端没启动或跨域被拦。 解决先确认app.py跑在 5000 端口再在 Flask 里加 CORS 支持flask-cors前端请求地址和端口要对上。现象四训练 loss 不降反升。原因学习率太大或标签没做数值映射还是字符串。 解决学习率降到2e-5检查MyDataSet.py里标签是否转成了 0/1/2 的整数。现象五pip install装 torch 卡死或报版本冲突。原因默认源慢或 Python 版本和 torch 轮子不匹配。 解决换国内镜像Python 用 3.7torch 选和 CUDA 匹配的版本没 GPU 就装 CPU 版。提示跑训练前先用几十条数据做一次「小样本过拟合」测试模型能在这几十条上把 loss 压到接近 0说明网络和数据处理没问题再上全量数据。6. 进阶技巧用混淆矩阵和置信度阈值把模型调到位模型能跑通只是及格线真正决定这套系统好不好用的是评估和调优。项目里给了模型在各标签下的表现.svg说明作者已经画了各标签的指标对比但光看准确率不够——三分类里如果「中性」样本占八成模型全猜中性也能有 80% 准确率这种虚高最坑人。我一般会补一张混淆矩阵看错分到底错在哪from sklearn.metrics import confusion_matrix, classification_report import seaborn as sns import matplotlib.pyplot as plt # y_true, y_pred 是真实标签和预测标签 cm confusion_matrix(y_true, y_pred) sns.heatmap(cm, annotTrue, fmtd, xticklabels[消极, 中性, 积极], yticklabels[消极, 中性, 积极]) plt.xlabel(预测) plt.ylabel(真实) plt.savefig(confusion_matrix.png, dpi150) print(classification_report(y_true, y_pred, digits3))逻辑说明confusion_matrix的行是真实、列是预测对角线是分对的。如果「积极」大量被错分成「中性」说明模型对正向情绪不敏感可以给积极类加权重或在清洗阶段保留更多情绪词。classification_report会给出每个类的 precision/recall/f1重点看 f1它兼顾了查准和查全。再进一步是调置信度阈值。Predictor输出的score不是摆设业务上可以设一条线低于阈值的样本不直接给结论转人工或标为「待定」。阈值怎么定拿验证集跑一遍画出不同阈值下的准确率-覆盖率曲线选一个业务能接受的平衡点。我一般从 0.6 起步舆情场景宁可漏判也别误判时就往上调到 0.75。还有一个容易被忽略的点模型版本管理。models/目录下别只留一个best_model.pt每次训练存成带时间戳的文件比如model_20240115.pt并在 README 里记一笔对应的数据版本和超参。不然过两周你根本想不起来哪个权重是哪个配置训出来的这种后悔药没处买。从那以后我每次训完模型都强制走一遍「混淆矩阵 分类报告 阈值扫描」这三件套确认没有类别塌陷才敢上线。希望这套拆解能帮到你把这份源码真正跑成自己的东西。本文还有配套的精品资源点击获取
返回列表