ARTICLE DETAIL

资讯详情

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

基于Python的大众点评数据可视化与情感分析系统实战解析

基于Python的大众点评数据可视化与情感分析系统实战解析 简介基于Python的大众点评数据可视化与情感分析系统设计与实现资源适用于毕业设计、期末大作业与课程设计项目参考适合需要完整系统代码与答辩材料的学习者也适合希望从注释清晰的代码中快速理解项目开发的Python新手。资源压缩包约26.35MB内容以Python源码和配套PPT为主代码内包含详细注释整体部署简便下载后调整配置即可运行。系统围绕大众点评评论数据展开涵盖数据清洗、情感倾向分析与可视化展示等环节可输出直观图表呈现分析结论代码模块划分清楚便于二次修改和功能扩展。配套PPT给出了项目设计思路与实现框架可直接用于答辩汇报或成果展示。目前已有207人学习下载项目完成度较高对于同类系统研究和课程实践都很有参考价值。资源结构完整能帮助使用者节省从零搭建系统的时间更快聚焦关键实现与最终展示。1. 大众点评数据可视化与情感分析系统看起来是三个功能其实是两条数据链路「基于 Python 的大众点评数据可视化和情感分析系统」这类题目在毕业设计里一直很热门但真正动手的人很快会发现情感分析和可视化加起来只占三成工作量剩下七成全在数据获取和清洗上。这个题目的本质是两条数据链路——一条从网页到干净表格另一条从表格到情感指标和图表——哪条断了系统都转不起来。它适合正在做毕设的学生也适合想用 Python 把爬虫、pandas、自然语言处理和 Web 展示串一遍的从业者。下面按我习惯的落地路径拆先把数据结构和清洗规则定死再写采集脚本然后做情感打分最后用 Flask 加 ECharts 把结果摆到页面上并把最常翻车的位置单独拎出来说。2. 系统架构与数据设计先定字段再写爬虫最后才做分析很多人拿到这个题目第一件事就是写爬虫这是最容易被返工的开局。页面结构一变、反爬一触发前面写的抽取逻辑全部要推倒。更稳的顺序是先把数据模型定下来再反推采集脚本要抓哪些字段。2.1 分层架构采集层、存储层、分析层、展示层各管什么这套系统我一般拆成四层。采集层用 requests 拉取页面负责把网页变成结构化记录存储层用 CSV 或 SQLite 落盘分析层用 pandas 做清洗和聚合用 SnowNLP 做情感打分展示层用 Flask 提供数据接口前端用 ECharts 渲染图表。数据流向是「网页 → 原始记录 → 干净表格 → 统计指标 → 图表」每一层只依赖上一层的结果不混在一起。为什么不用 Scrapy 或者 Spark课程设计和中小型分析场景用不上。Scrapy 的学习成本高框架本身的爬虫调度逻辑在答辩时讲不清楚Spark 更是杀鸡用牛刀。requests 加 pandas 的组合代码量小、每一步都能打断点观察老师问到底层也能答得上来。情感分析层我选 SnowNLP 而不是大模型 API理由后面单说核心是离线可复现、答辩演示不依赖网络。2.2 字段设计店铺、评分、评论、时间怎么存先看要回答什么问题哪个区域的店评分高、哪个品类的差评多、口碑随时间怎么变化。围绕这些我把数据拆成两张表。店铺表shop字段类型说明shop_id文本主键来自店铺页 URLshop_name文本店铺名称region文本行政区或商圈category文本品类如火锅、日料avg_score浮点平台展示的平均评分avg_cost浮点人均消费review_count整型评论总数用于计算爬取覆盖率评论表review字段类型说明review_id文本主键来自评论节点的唯一标识shop_id文本外键关联店铺表rating浮点用户打分1 到 5content文本评论文本comment_time时间评论发布时间like_count整型点赞数可做加权参考这里有一个设计选择评论表里不冗余店铺名和品类只留 shop_id。冗余字段会让洗数据时出现信息不一致例如同一家店在两个来源里写成了不同名字。宁可分析时用 join 关联也不要让同一份数据出现两个版本。另外 review_id 不要用自增数字因为增量爬取需要稳定唯一键否则第二次跑脚本会全量重复。存储介质上数据量小于五万条时 CSV 完全够用而且答辩时可以直接用 Excel 打开给老师看。想显得工程化一点就上 SQLite连 pandas 的 read_sql 都省了转换。MongoDB 适合字段经常变的场景但对这个题目属于过度设计我不建议。2.3 数据清洗与去重时间、评分、文本的规范化无论爬虫写得多么小心原始数据里一定有重复评论、空值、营销广告和格式不统一的时间。这份清洗代码是整套系统的地基跑完之后的数据才交给情感分析。import pandas as pd raw pd.read_csv(data/reviews_raw.csv, dtype{shop_id: str}) print(原始记录数:, len(raw)) # 1) 去重以评论 ID 为准保留第一条 raw raw.drop_duplicates(subset[review_id], keepfirst) # 2) 时间解析页面返回的时间格式不统一统一成 datetime无法解析的置为空 raw[comment_time] pd.to_datetime(raw[comment_time], errorscoerce) # 3) 评分分级页面可能是 1~5 分也可能是文本描述统一转成浮点 def parse_rating(x): try: v float(x) return v if 1 v 5 else None except (TypeError, ValueError): return None raw[rating] raw[rating].apply(parse_rating) # 4) 过滤短评和广告文本长度小于 5 或命中营销词删掉 ad_keywords [加微信, 免费领, 代购, 扫码] def is_useless(t): if not isinstance(t, str) or len(t) 5: return True return any(k in t for k in ad_keywords) raw raw[~raw[content].apply(is_useless)] # 5) 只保留核心字段按采集时间顺序落盘 clean raw.dropna(subset[rating, comment_time]) clean clean[[review_id, shop_id, rating, content, comment_time]] clean.to_csv(data/reviews_clean.csv, indexFalse, encodingutf-8-sig) print(清洗后记录数:, len(clean))几个参数值得说明。drop_duplicates 的 subset 是主键如果爬虫没抓到 review_id就退化成用 shop_id 加 content 加 comment_time 三列联合去重。pd.to_datetime 的 errorscoerce 会把解析失败的时间变成 NaT后续 dropna 直接剔除宁可少一条数据也不要让脏时间进入趋势图。parse_rating 里用 try except 而不是判断类型是因为 Pandas 的单元格可能是字符串、浮点、空值三种状态直接 isinstance 判断容易漏。清洗完要做一个验收动作按 shop_id 分组看每家的评论数量正常分布应该是长尾——热门店几百条小店面几条。如果所有店铺评论数都一模一样八成是解析逻辑写错了把同一个评论重复抓了多遍。这一步能在进入情感分析之前就拦住大多数问题比做完分析再返工省时间。清洗前后的记录数对比、字段去重数、时间跨度这三项也是论文里最值得放的数据。3. 大众点评数据采集的工程化写法请求、解析、调度与断点续爬数据采集是这套系统里最容易翻车的环节不是因为代码难写而是因为页面结构不在你手里。网上那些免费 Python 源码大全里的大众点评爬虫脚本十个有八个直接跑不通原因基本是页面里某个 class 名换了。所以这一章不只给代码更重要的是给一套「变了也能快速修」的写法。3.1 从店铺列表页到评论详情页URL 结构与请求构造大众点评的店铺页 URL 通常形如https://www.dianping.com/shop/{shop_id}评论列表页会在后面拼上 review 相关的路径和页码参数。问题是这些路径在不同城市、不同类目下可能不一样所以第一步不是写代码而是手动在浏览器里打开一个目标店铺把 URL 和页面结构抄下来。我的习惯是先在浏览器开发者工具里搜索评论内容找到评论所在的 HTML 节点记下它的 class 名称和层级关系再回到代码里写选择器。页面结构是动态变化的CSS 类名往往带随机后缀今天能用的选择器下周可能就失效了。因此选择器要集中放在脚本顶部的变量里别散落在循环内部。这样页面改版时只需要改一处不用通读整个脚本。请求层还有一个容易被忽略的点大众点评对 PC 页面和移动端页面的渲染方式不同评论内容有时藏在接口返回的 JSON 里而不是 HTML 里。如果解析 HTML 拿不到数据就到开发者工具的 Network 面板里找 XHR 请求看有没有/reviewlist、/shopreviews这类接口直接请求接口拿 JSON 反而更干净。判断标准很简单HTML 里能看到完整评论就用 HTML 解析看不到就去翻 XHR。3.2 用 requests lxml 写最小爬虫选择器与字段抽取下面这段是评论页采集的最小可用版本重点在 Session 复用和选择器抽取。import requests import time import random from lxml import html session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept-Language: zh-CN,zh;q0.9, }) def fetch_review_page(session, shop_id, page_no): url fhttps://www.dianping.com/shop/{shop_id}/reviewall/p{page_no} resp session.get(url, timeout10) if resp.status_code ! 200: print(f[skip] shop{shop_id} page{page_no} status{resp.status_code}) return [] doc html.fromstring(resp.text) items [] # 选择器的 class 名称以实际页面为准这里示范结构 for node in doc.cssselect(div.review-list div.review-item): items.append({ review_id: node.get(data-review-id), shop_id: shop_id, rating: node.cssselect(span.starval)[0].get(class, ), content: node.cssselect(div.review-text)[0].text_content().strip(), comment_time: node.cssselect(span.time)[0].text_content().strip(), }) return items # 串行抓取每页间隔 2~4 秒避免请求频率过高 for page in range(1, 11): rows fetch_review_page(session, 123456, page) if not rows: break # 追加写入部分见 3.4 的断点续爬 time.sleep(random.uniform(2, 4))三个设计点。第一用requests.Session()而不是每次requests.get()Session 会帮你保存服务端下发的 Cookie连续翻页时更接近真实浏览器行为。第二星级我拿的是 span 的 class 属性而不是文本大众点评常用star50、star40这类类名表示打分直接读文本容易拿到「口味很好」这种描述还得再做一层映射。第三每页间隔用random.uniform(2, 4)而不是固定 sleep 3 秒目的是让请求间隔看起来像人在操作这是爬虫工程里的基本习惯。解析库我选 lxml 的 cssselect 而不是 BeautifulSoup 加正则。cssselect 的书写和前端 CSS 选择器一致熟悉网页的人零学习成本BeautifulSoup 的 find 写法在多层嵌套时要写好几个 find 调用维护起来远不如一行选择器直观。需要先确认环境里装了 cssselect 包lxml 默认不带这个解析器。3.3 反爬与稳定性Cookie、UA、限速与人工验证兜底这一节直接决定你的脚本能跑十分钟还是一整天。大众点评的风控主要看几个信号请求频率、Cookie 完整性、UA 是否为常见浏览器、是否在短时间内翻了很多页。触发的典型现象有三种返回 403、返回一个验证码页面、页面正常但评论列表是空的。我的应对是三层。第一层是请求侧UA 用真实的 Chrome 版本字符串Session 保持 Cookie每页间隔不低于三秒。第二层是入口侧先在浏览器里手动打开店铺页让它生成合法的 Cookie再把这个 Cookie 字符串塞进代码的请求头里模拟一个已经访问过的会话。这属于学术研究场景下的常规做法数据量控制在几百条以内不要对单店全量评论做地毯式抓取。第三层是熔断代码里检测到响应里出现验证码特征就立刻停止让程序发一条提醒人工处理完再继续绝不自动重试硬闯。有一个必须划线的边界这套系统只处理公开页面上能看到的内容不碰用户头像、昵称、私信等隐私字段也不做绕过登录态的操作。课程设计的数据量级两百家店、几千条评论足够支撑所有图表贪多只会增加被封的风险和清洗成本。论文里写清「数据获取限于公开页面、低频采集、仅用于学习」这一段反而比遮遮掩掩更经得起推敲。3.4 断点续爬与日志让爬虫变成可重跑的批处理任务爬虫写到能跑只是第一步写成能断点续跑才算完。大众点评的反爬经常在你睡到一半时触发脚本停了前面抓的数据不能丢重跑时也不能把已抓的再抓一遍。做法是维护一个已抓取评论 ID 的集合每条写入前先查这个集合。import json import os import pandas as pd SEEN_FILE data/seen_review_ids.json def load_seen(): if os.path.exists(SEEN_FILE): with open(SEEN_FILE, r, encodingutf-8) as f: return set(json.load(f)) return set() def save_seen(seen): with open(SEEN_FILE, w, encodingutf-8) as f: json.dump(list(seen), f, ensure_asciiFalse) seen load_seen() new_rows [] for page in range(1, 11): rows fetch_review_page(session, shop_id, page) page_new [r for r in rows if r[review_id] not in seen] if not page_new: print(fpage {page} 无新增停止) break new_rows.extend(page_new) for r in page_new: seen.add(r[review_id]) save_seen(seen) time.sleep(random.uniform(2, 4)) # 统一追加写入 CSV if new_rows: df pd.DataFrame(new_rows) df.to_csv(data/reviews_raw.csv, modea, headernot os.path.exists(data/reviews_raw.csv), indexFalse, encodingutf-8-sig)这里用 JSON 文件存集合而不是数据库是因为课程设计里没必要引入额外依赖文件读写足够快。save_seen 每翻完一页就调用一次而不是全部跑完再存这样脚本随时被杀掉重跑时最多重复最后一页的数据。追加写入时用headernot os.path.exists(...)判断文件是否存在避免每追加一次都写入表头。断点的判断逻辑是「这一页没有一条新评论就停」这个条件比「翻到最后一页」更可靠因为很多店铺的评论列表根本没有明确的尾页标识。4. 评论文本情感分析SnowNLP 打分、自定义词典与口碑聚合数据洗干净之后进入标题里的核心词「情感分析」。这一步输出的是一个 0 到 1 之间的小数但要让这个数对店铺口碑有解释力还需要做领域词典和聚合加工。4.1 为什么选 SnowNLP离线、快、答辩好讲中文情感分析的方案很多最省事的是调用大模型 API把评论丢给 GPT 让它返回 positive 或 negative。但课程设计不推荐这条路每次调用都要联网答辩现场网络一旦波动就黑屏接口返回结果有随机性同一句话两次调用可能不同更麻烦的是你没法向老师解释分是怎么算出来的。SnowNLP 是另一个方向本地跑、速度快、打分逻辑是训练好的贝叶斯模型输入文本输出 0 到 1 的情感倾向0.5 是中性分。它的训练语料偏电商购物评论直接用在餐饮点评上准确率一般但可以通过词表和规则修正。这个「基座模型加业务规则」的组合在美团情感分析、影视情感分析、农产品价格数据可视化-flask 这些同类型题目里都能复用换掉领域词表就行。答辩时你能讲清楚哪些词是自定义的、为什么这样加权这比一句「AI 分析的」有说服力得多。4.2 情感得分计算先用 SnowNLP 跑一遍基线先不急着加规则把原始打分跑出来看整体分布是否合理。from snownlp import SnowNLP import pandas as pd clean pd.read_csv(data/reviews_clean.csv) def base_score(text): try: return SnowNLP(str(text)).sentiments except Exception: return 0.5 clean[base_sentiment] clean[content].apply(base_score) print(clean[base_sentiment].describe()) print(情感分 0.6 占比:, (clean[base_sentiment] 0.6).mean())sentiments属性返回 0 到 1 的浮点数越接近 1 越正向。包一层 try except 是因为部分评论包含表情符号或特殊字符时SnowNLP 内部分词可能抛异常兜底给 0.5 不影响整体统计。describe 输出的均值如果明显偏离 0.5说明这批评论本身就有倾向性或者采集的店铺偏好评这是正常现象不要强行修正。基线跑完要做一次肉眼抽检打印 20 条情感分小于 0.2 和大于 0.8 的评论看看是不是符合直觉。常见问题是「绝绝子」「天花板」这类网络流行语被 SnowNLP 判成中性以及「不太好吃」这种否定句式被打成低分。这些就是下一节要用规则修的地方。4.3 自定义词典与否定词把「绝绝子」识别成好评领域修正我把它做成一个打分调整函数优先级从高到低强正负词、否定反转、程度加强。不重写模型只在这个函数里叠加规则。strong_neg {不好吃, 踩雷, 难吃, 差评, 服务差, 再也不来} strong_pos {绝绝子, 天花板, 强烈推荐, 还会再来, 份量足, 很用心} negators {不, 没, 别, 不太, 不够} boosters {非常, 特别, 太} def adjust_score(text, base): if any(w in text for w in strong_neg): return 0.1 if any(w in text for w in strong_pos): return 0.9 if any(w in text for w in negators): return 0.5 - (base - 0.5) if any(w in text for w in boosters) and base 0.5: return min(0.95, base 0.15) return base clean[sentiment] clean.apply( lambda r: adjust_score(r[content], r[base_sentiment]), axis1)强词表的优先级最高命中就直接改分不再走后面的否定判断。原因是「踩雷」这类词本身已经表达了明确态度再做否定反转会把意思搞反。否定反转的公式0.5 - (base - 0.5)的含义是如果模型把「好吃」打成 0.8那么「不好吃」的分值对称翻到 0.2如果模型把「差」打成 0.3「不差」会翻到 0.7。这个对称变换假设了否定并不改变情感强度只改变方向虽然粗糙但对中文短文本的容错率很高。词表要根据实际跑出来的误判案例持续扩充。我一般准备两个文本文件pos_words.txt和neg_words.txt由爬虫阶段统计的高频词人工筛选而来。扩充词表属于一种叫「词典覆盖」的通用做法任何迁移到这个方案的项目都会经历这一步换领域就换词表规则逻辑不用动。4.4 情感结果与口碑聚合好评率、情感指数、时间趋势情感分只有一个数字放进系统里必须聚合成指标才有意义。按店铺聚合看口碑优劣按月份聚合看口碑变化这两张聚合表就是后面可视化章节的数据源。# 按店铺聚合口碑指标 shop_stats clean.groupby(shop_id).agg( review_n(review_id, count), avg_rating(rating, mean), avg_sentiment(sentiment, mean), pos_rate(sentiment, lambda s: (s 0.6).mean()), ) # 按月份聚合情感趋势 clean[ym] clean[comment_time].dt.to_period(M) trend clean.groupby(ym).agg( avg_sentiment(sentiment, mean), review_n(review_id, count), )pos_rate的阈值取 0.6含义是「明确正面评论的占比」。这个阈值不是固定的可以看基线分布的 75 分位来定如果整体打分偏高就上调到 0.65。dt.to_period(M)把时间归到月份画折线图时 x 轴就是「2024-01」「2024-02」这样的刻度比原始日期好看。聚合之后建议做一次一致性检查计算 avg_sentiment 和 avg_rating 的相关系数。如果出现一家店评分很高但情感分很低大概率是评论内容与评分对不上说明爬虫阶段把不同店的评论混在一起了需要回到清洗环节检查 shop_id 映射。这一条检查能拦住大部分隐蔽的数据错位问题。5. 数据可视化与系统展示从 ECharts 图表到 Flask 仪表盘数据算完了最后一步是把结果摆到页面上。这个章节直接对应标题里的「数据可视化」也是 PPT 里最出效果的部分。展示层我用 Flask 写接口、ECharts 画图前后端分开接口返回 JSON前端负责渲染。5.1 看哪些图才够答辩图表与指标的对应关系不是图越多越好而是每张图都要对应一个可回答的问题。我给这套系统配了五类图对应五种指标图表类型展示指标答辩话术地图或柱状图各区域店铺数量与平均评分哪个商圈餐饮供给最密集横向柱状图各品类平均评分与人均消费哪个品类性价比最突出饼图评分分布1 星到 5 星占比用户打分是否有长尾偏差折线图情感得分月度趋势口碑随时间如何变化词云评论高频词用户最关心口味、服务还是环境ECharts 是这类系统的事实标准免费、中文文档全、几乎每个毕业设计都在用网上能找到大量可改的示例。它的一个优势是单 HTML 文件就能跑不需要构建工具把 echarts.min.js 引入后直接写配置项就行。农产品价格数据可视化-flask、旅游网站之数据可视化这类题目展示层都是同一套架构改数据接口和图表类型就能复用。5.2 Flask 提供数据接口把统计结果输出成 JSON展示层和数据处理层通过一个 JSON 接口分开。Flask 只负责读聚合结果、转 JSON不做计算。from flask import Flask, jsonify import pandas as pd app Flask(__name__) app.route(/api/overview) def overview(): clean pd.read_csv(data/reviews_clean.csv) shop_stats clean.groupby(shop_id).agg( review_n(review_id, count), avg_sentiment(sentiment, mean), ).reset_index() return jsonify({ shop_count: int(clean[shop_id].nunique()), review_count: int(len(clean)), avg_sentiment: round(float(clean[sentiment].mean()), 3), shop_stats: shop_stats.to_dict(orientrecords), }) app.route(/api/trend) def trend(): clean pd.read_csv(data/reviews_clean.csv) clean[ym] clean[comment_time].dt.to_period(M).astype(str) trend clean.groupby(ym).agg( avg_sentiment(sentiment, mean), review_n(review_id, count), ).reset_index() return jsonify(trend.to_dict(orientrecords)) if __name__ __main__: app.run(host127.0.0.1, port5000, debugFalse)接口设计有个原则计算在接口外完成接口内只做读取和格式化。最省事的写法是每次请求都重新读 CSV 重新 groupby数据量小的时候看不出来但答辩时连续点多个图表会明显变卡。改进方法是把聚合结果在启动时算一次存成全局变量接口直接引用。to_dict(orientrecords)输出的格式是[{字段: 值}, ...]前端 map 起来最顺手。中文内容交给 jsonify 后会自动做 UTF-8 编码前端不会出现乱码。5.3 ECharts 前端渲染一个页面集成四类图表前端用一个 HTML 页面承载多个图表。每个图表一个 div 容器一个echarts.init一份option配置。下面以情感趋势折线图为例。fetch(/api/trend) .then(res res.json()) .then(data { const chart echarts.init(document.getElementById(trendChart)); chart.setOption({ title: { text: 情感得分月度趋势 }, tooltip: { trigger: axis }, xAxis: { type: category, data: data.map(d d.ym) }, yAxis: { type: value, min: 0, max: 1, name: 情感分 }, series: [{ type: line, data: data.map(d d.avg_sentiment), smooth: true, areaStyle: { opacity: 0.15 } }] }); });这段代码有两个经常翻车的细节。第一容器 div 必须有高度echarts.init之后图表会取容器宽高如果 div 没设高度画布是 0 像素页面上什么都看不见。第二x 轴数据是字符串月份y 轴数据是情感分前端字段要和后端 JSON 字段严格对应哪怕后端把ym改成month前端也要同步改否则图表空白。我的习惯是先定接口返回样例把前端写死的数据跑通再换成真实请求这能避免两头同时调试。页面布局上图表用 CSS Grid 排列左侧放区域评分柱状图右侧放情感趋势折线图下方放评分分布饼图。不要试图在一个图表里塞进所有信息ECharts 的 legend 太多反而答辩看不清。5.4 PPT 与论文里的图表导出清晰度与配色标题里带着「PPT」所以展示层的最后一步是导出和排版。ECharts 自带的 toolbox 可以保存图片但默认导出像素比不高打印或投影时会发虚。保存前在 option 里加一段配置把dataZoom关掉、把像素比设为 2导出 PNG 后再放进 PPT清晰度基本够用。配色不要用 ECharts 默认的蓝色系选一套三到四色的主题色统一用在所有图表上。论文里的架构图不要贴代码截图用画图工具画成分层框图标好「采集层 / 存储层 / 分析层 / 展示层」和每层的数据流向。每一张图表下面配一句「从图中可以看出……」这句话就是答辩时你要说的核心结论。PPT 控制在十二页以内背景与问题、系统架构、爬虫模块、清洗前后对比、情感分析规则、五张图表展示、创新点与总结这样的节奏正好覆盖一次十分钟的汇报。6. 避坑与验证跑通这套系统最容易翻车的五个位置这套系统我自己重写过不止一遍下面五件事都真实踩过每条按现象、原因、解决来写希望能帮你少走一步弯路。6.1 评论和店铺对不上。现象翻页抓取后某条评论显示在错误店铺下。原因评论列表页是异步加载的部分节点在翻页时复用了之前的 DOM 结构选择器命中了残留内容。解决每条评论记录里同时保存 source_url用 URL 里的 shop_id 作为最终归属清洗阶段再做一次校验。6.2 请求突然返回验证码。现象前十分钟正常突然所有请求都返回一个验证页面。原因请求频率超过阈值或者 Session 里的 Cookie 失效。解决把每页间隔提到四秒以上用 Session 保活 Cookie出现验证码就停止人工处理完再跑。课程设计的数据量不需要硬闯停一下换时间段重跑即可。6.3 SnowNLP 把网络用语判成中性。现象「绝绝子」「YYDS」这类词的情感分在 0.5 附近。原因模型训练语料生成时这些词还没有流行。解决把网络热词加进 strong_pos 词表规则命中优先于模型打分不要指望换模型解决。6.4 浏览器里图表中文显示成方块。现象标题和坐标轴上的中文全部变成方框。原因HTML 页面没有声明字符集或者引入的字体不支持中文渲染。解决在每个 HTML 的head里加meta charsetutf-8接口返回的 JSON 在 Flask 侧默认 UTF-8 编码不要额外转码。6.5 清洗后的 CSV 用 Excel 打开乱码。现象pandas 写出的文件在记事本正常Excel 里中文全乱。原因CSV 保存时用的是无 BOM 的 UTF-8 编码Excel 默认按本地编码读取。解决所有 CSV 落盘统一加encodingutf-8-sig这一行代码能省掉答辩前最后五分钟的尴尬。我自己的习惯是先把字段表和接口样例定死再写爬虫和图表这样返工率最低。收藏夹里可以放着各种看着想要的代码但真正把自己的数据从网页到图表完整跑通一遍之后才会明白整个系统的瓶颈通常在数据质量上而不是哪个算法不够新颖。希望这些经验能帮到你把这套系统做成一个自己能讲清楚每一步的作品。本文还有配套的精品资源点击获取
返回列表