学号 2025-2026-2 《Python程序设计》实验四报告
课程:《Python程序设计》
班级: 2524
姓名: 李俊江
学号:20252403
实验教师:王志强
实验日期:2026年6月6日
必修/选修: 公选课
一、系统设计
1.1 总体架构
系统采用模块化分层架构,共 6 个 Python 模块 + 1 个配置文件:
┌─────────────────┐│ Streamlit UI ││ (app.py) │└────────┬────────┘│┌────────────┬────────────┼────────────┬────────────┐│ │ │ │ │┌────▼────┐ ┌─────▼─────┐ ┌───▼────┐ ┌─────▼────┐ ┌────▼────┐│ crawler │ │ analyzer │ │visualiz│ │ database │ │ config ││ .py │ │ .py │ │er.py │ │ .py │ │ .py │└────┬────┘ └─────┬─────┘ └───┬────┘ └─────┬────┘ └────┬────┘│ │ │ │ │┌────▼────┐ ┌─────▼─────┐ ┌───▼────┐ ┌─────▼────┐ ││Playwright│ │ DeepSeek │ │Plotly +│ │ SQLite3 │ ││Browser │ │ API │ │WordCloud│ │ .db │ │└─────────┘ └──────────┘ └────────┘ └──────────┘ │┌───────▼──────┐│ .env / env ││ API Key 配置 │└──────────────┘
1.2 模块职责
| 模块 | 文件 | 职责 |
|---|---|---|
| 界面层 | app.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
Streamlit 页面渲染、用户交互、流程编排 |
| 爬虫层 | crawler.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
Playwright 浏览器控制、API 拦截、DOM 提取 |
| 分析层 | analyzer.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
DeepSeek API 调用、情感分析、文本摘要 |
| 可视化层 | visualizer.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
Plotly 图表生成、jieba 分词、WordCloud 词云 |
| 数据层 | database.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
SQLite CRUD、趋势统计、历史查询 |
| 配置层 | config.pyhttps://gitee.com/hantou1/web-sentiment-watch/commit/27474c7f1dcf36512197e157cd589e49c8c03c4d |
环境变量读取、User-Agent 池、爬虫参数 |
1.3 数据库设计
使用 SQLite 数据库
1.4 爬虫策略设计
快手是 SPA(单页应用),内容由 JavaScript 动态渲染。爬虫采用双通道策略:
┌──────────────────────────────────────────────────────┐
│ 爬虫主流程 │
│ │
│ ① 访问搜索页 → 等待渲染 + 滚动加载 │
│ │ │
│ ├── 通道A: 拦截 XHR/fetch 响应 │
│ │ ├─ 匹配搜索API → 解析JSON视频列表 │
│ │ ├─ 匹配详情API → 解析标题/作者/播放量 │
│ │ └─ 匹配评论API → 解析评论列表 │
│ │ │
│ └── 通道B: DOM 降级提取(通道A失败时) │
│ ├─ querySelectorAll 提取视频链接 │
│ ├─ innerText 正则提取播放量/点赞数 │
│ └─ 滚动 + DOM 提取评论文本 │
│ │
│ ② 逐一访问详情页 → 提取完整信息 + 评论 │
│ │ │
│ ③ 过滤空数据 → 返回结构化结果 │
└──────────────────────────────────────────────────────┘
反反爬措施:
- 6 个真实移动端 User-Agent 轮换
- 随机延迟 2-5 秒模拟人类浏览
- 隐藏
navigator.webdriver特征 - 禁用 AutomationControlled 标志
- 失败重试 3 次,每次等待递增
由于快手反爬协议 https://www.kuaishou.com/robots.txt ,最终放弃了对信息爬取的实现。
1.5 DeepSeek 情感分析部分设计
程序内接入了deepseek api,能够对爬虫获取信息进行分析处理,并以JSON格式输出分析结果。
以下是
你是一个专业的中文文本情感分析助手。
请分析用户输入的文本所表达的情感倾向,并以严格的 JSON 格式输出结果。
情感判断标准:
- positive: 正面、积极、支持、赞扬、满意、高兴
- negative: 负面、消极、反对、批评、愤怒、失望、焦虑
- neutral: 中立、客观、疑问、无明显情感倾向、信息性
二、实现过程
2.1 开发环境
- 操作系统:Windows 11
- 编辑器:VIM 9.0 (在 Git Bash 终端中使用)
- Python 版本:3.11
- 版本控制:Git托管至fitee平台
2.2 核心代码实现
2.2.1 爬虫模块 (crawler.py)
信息爬取模块
class APICapture:"""捕获页面发出的 API 响应,抽取结构化 JSON 数据"""SEARCH_PATHS = ["/rest/n/search/", "/rest/search/", "search/photo", ...]DETAIL_PATHS = ["/rest/n/photo/info", "/rest/n/feed/single", ...]COMMENT_PATHS = ["/rest/n/photo/comment", "/rest/comment/list", ...]async def handle_response(self, response):"""Playwright response 回调"""url = response.urlif "kuaishou.com" not in url:returnbody = await response.text()data = json.loads(body)# 匹配搜索 API → 解析视频列表if self._matches_any(url, self.SEARCH_PATHS):self.search_results = self._parse_search_response(data)# 匹配详情 API → 解析标题/作者/播放量elif self._matches_any(url, self.DETAIL_PATHS):self.video_detail = self._parse_detail_response(data)# 匹配评论 API → 解析评论列表elif self._matches_any(url, self.COMMENT_PATHS):self.comment_list = self._parse_comment_response(data)
搜索响应解析:
def _parse_search_response(self, data: dict) -> list[dict]:feed_keys = ["feeds", "result", "items", "list", "photos", "records"]for key in feed_keys:array = _deep_get(data, "data", key) if array:breakarray = _deep_get(data, key)
2.2.2 情感分析模块 (analyzer.py)
def analyze_sentiment(text: str) -> dict:"""对单条文本进行情感分析"""if not text or len(text.strip()) < 5:return {"sentiment": "neutral", "confidence": 0.3}messages = [{"role": "system", "content": SENTIMENT_SYSTEM_PROMPT},{"role": "user", "content": text[:500]},]content = _call_deepseek(messages, temperature=0.1, max_tokens=256)result = _extract_json(content) if result and "sentiment" in result:return {"sentiment": result["sentiment"],"confidence": min(max(float(result["confidence"]), 0.0), 1.0),}return {"sentiment": "neutral", "confidence": 0.0}
2.2.3 可视化模块 (visualizer.py)
def plot_sentiment_pie(sentiment_stats: dict) -> go.Figure:"""绘制情感分布饼图"""labels_map = {"positive": "正面", "negative": "负面", "neutral": "中立"}colors_map = {"positive": "#2ecc71", "negative": "#e74c3c", "neutral": "#95a5a6"}fig = go.Figure(data=[go.Pie(labels=[labels_map[k] for k in ...],values=[...],marker=dict(colors=[colors_map[k] for k in ...]),hole=0.4, )])fig.update_layout(title="📊 情感分布", height=400)return figdef generate_wordcloud(texts: list[str]) -> Optional[Path]:"""使用 jieba 分词 + WordCloud 生成词云"""all_words = []for text in texts:words = jieba.lcut(text) for w in words:if w not in _STOP_WORDS and len(w) >= 2: all_words.append(w)word_freq = Counter(all_words)wc = WordCloud(font_path=font_path, width=800, height=600, ...)wc.generate_from_frequencies(word_freq)wc.to_file(output_path)return Path(output_path)
2.2.4 数据库模块 (database.py)
def init_db():"""创建 5 张表 + 索引"""cursor.execute("""CREATE TABLE IF NOT EXISTS search_history (id INTEGER PRIMARY KEY AUTOINCREMENT,keywords TEXT NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,total_videos INTEGER DEFAULT 0,total_comments INTEGER DEFAULT 0,status TEXT DEFAULT 'pending')""")def get_sentiment_stats(search_id: int) -> dict:"""获取情感分布统计"""cursor.execute("""SELECT sentiment, COUNT(*) as count, AVG(confidence) as avg_confidenceFROM sentiment_results WHERE search_id=? GROUP BY sentiment""", (search_id,))return {"positive": {...}, "negative": {...}, "neutral": {...}}
2.2.5 主界面 (app.py)
st.set_page_config(page_title="快手舆情监控系统", layout="centered", ...)with st.sidebar:keywords = st.text_input("🔍 输入关键词(逗号分隔)")start_btn = st.button("▶️ 开始监控", type="primary")tab1, tab2, tab3, tab4 = st.tabs(["📋 总览", "🎬 视频列表", "📊 详细分析", "📈 趋势"])with tab1:st.markdown(summary['key_topics']) st.plotly_chart(plot_sentiment_pie()) st.image(generate_wordcloud()) with tab2:for v in videos:sent_badge = {"positive": "👍 正面", ...}[vid_sent]with st.expander(f"{title} {sent_badge}"):
3.3 关键问题与解决方案
关键问题一: 快手平台有反爬措施,爬虫无法实现对信息的爬取,导致后续操作无法实现。
解决方案一:增加反反爬措施,了解快手平台robots协议,对代码进行优化。
关键问题二:华为云服务器openeuler系统中无python 3.1.1库,windows上编程后,无法在云服务器上运行。
解决方案二:修改代码,适应linux环境,从阿里云镜像网站下载python3.1.1库。
关键问题三:本地vim编程时,对操作不熟悉,出现缩进错误,导致代码无法正常运行。
解决方案三:重新学习vim使用方法,对:wq等命令进行学习与掌握。
四、部署与运行
4.1 Windows 本地开发
使用 VIM 在 Windows Git Bash 终端中编写代码:

本地启动命令
streamlit run app.py
### 4.2 华为云 EulerOS 部署服务器配置:2vCPUs / 4GiB / EulerOS 2.0**部署步骤:**```bash
通过ssh命令链接至服务器,通过scp代码将本地代码上传并配置python环境和chorm浏览器。
配置安全组,开放8501端口,关闭防火墙。
启动服务器,等待链接。
4.3 手机访问
手机与服务器在同一网络下,浏览器访问 http://123.249.71.184:8501,Streamlit 自动适配移动端布局。
五、实验结果
5.1 功能实现情况
| 功能 | 状态 | 说明 |
|---|---|---|
| 关键词输入与搜索 | 完成 | 支持逗号分隔多关键词 |
| 快手数据爬取 | 失败 | 遭受快手反爬,研究相关规定后放弃强行爬取 |
| DeepSeek 情感分析 | 完成 | 视频标题+描述+评论全面分析,含置信度 |
| 可视化展示 | 完成 | 饼图、柱状图、趋势折线图、词云 |
| AI 文本摘要及分析 | 完成 | 重点讨论内容 + 群众思想动态 |
| 数据持久化 | 完成 | SQLite数据库,历史记录查询,趋势统计 |
| 移动端适配 | 完成 | 响应式CSS,自动适配手机 |
5.2 系统界面
(1)主界面 - 4个标签页


(2)手机端效果


(3)运行视频
https://files.cnblogs.com/files/blogs/864651/舆情监控.zip?t=1780726446&download=true
5.3 技术指标
| 指标 | 数值 |
|---|---|
| 代码行数 | 约 1800 行 Python |
| 模块数量 | 6 个核心模块 |
| 数据库表 | 5 张表 + 3 个索引 |
| 爬虫重试次数 | 3 次 |
| User-Agent 池 | 6 个移动端 UA |
| 情感分类 | 3 类(正面/负面/中立) |
| Chart 类型 | 4 种(饼图/柱状图/折线图/词云) |
六、课程总结与感想
6.1 对本门课程的总结
通过本学期 Python 程序设计课程的学习,我系统地掌握了以下知识与技能:
-
Python 基础语法:变量、数据类型、控制流、函数、面向对象编程、异常处理等,能够编写结构清晰、可维护的 Python 代码。
-
序列;包括列表、元组、字典、集合等的特征和区别,以及如何应用。
-
网络编程与爬虫:学习了 HTTP 协议基础、Playwright 自动化浏览器控制、反爬策略应对,理解了 SPA 页面的数据获取方式。
-
socket套接字:学习了通过socket套接字实现不同主机间的双向通信和链接,能够传递加密信息并解密。
-
web应用与第三方库:学习了进行web编程,了解了web网站的构成与设计,学到了对第三方库如requests等的应用。
6.2 课程感想与体会
python是一种跨平台,解释型,面向对象,动态数据类型的高级程序设计语言。相比于c语言,python更为简化,泛用性更好,能够实现的效果也更多。在程序设计中,python没有像c语言一样的严格的格式要求,新版python甚至可以支持中文字符串,对于我们这样的初学者而言更加友好。
强哥讲课很有意思,能够把知识点以简单易懂,易于理解的方式讲给我们,让我们能够深入掌握。实验课安排与学到的知识紧密相关,是对知识掌握的有效检验和应用,能够强化学习效果。
6.3 课程建议
老师在下次开设python课时,可以先将实验报告优秀模板或实例展示或分享,实验后也可将完整实验代码或实例给出。
同时,老师在实验安排时,可以考虑在后续实验中加入对之前学习知识的应用。如在实验二中,可以加入对之前学到的序列的应用,避免学了后面忘了前面。
参考文献
[1] Streamlit Documentation. https://docs.streamlit.io/
[2] Playwright for Python. https://playwright.dev/python/
[3] DeepSeek API Documentation. https://platform.deepseek.com/api-docs/
[4] Plotly Python Graphing Library. https://plotly.com/python/
[5] jieba 中文分词. https://github.com/fxsjy/jieba
[6] WordCloud for Python. https://amueller.github.io/word_cloud/
[7] 华为云弹性云服务器用户指南. https://support.huaweicloud.com/ecs/
[8] Python SQLite3 Documentation. https://docs.python.org/3/library/sqlite3.html
