首页/新闻资讯/正文详情

京东评论爬取与情感分析实战:从数据采集到可视化大屏

发布时间:2026/9/24 18:35:15 来源:云帆数科 栏目:资讯中心
京东评论爬取与情感分析实战:从数据采集到可视化大屏
简介针对Python爬虫与文本情感分析入门者的京东评论研究实战包以京东平台商品评价为对象覆盖从页面数据采集、去重清洗、正负向情感分类到图表可视化的完整分析链路适合课程设计、毕业设计或个人练手。压缩包共20个文件包括爬虫脚本、情感分类训练代码、CSV格式的原始及处理后数据、TXT词表与说明文档、JPG/PNG形式的情感分布图与词云图并附有项目备份整体约5.87MB便于下载与本地复现。目前已有76人学习浏览内容中既能找到核心的Python实现文件也能直接查看处理好的评论数据表和结果表配合README说明可快速理清代码逻辑与数据流向。通过这套资料可以掌握电商评论采集、文本预处理、朴素贝叶斯/机器学习情感分类的基本方法并学会用图表呈现分析结论是一份结构清晰、实用性较强的完整参考。1. 从一条京东评论到一张可视化大屏中间隔着什么想研究某款手机的京东评价几百页评论翻到凌晨也看不完于是把问题交给Python先把评论全部抓下来再对每一条算情感分最后画成图表。这个标题讲的就是这么一条流水线——京东商品评论爬取、情感分析、可视化三个环节串起来做一次完整的数据洞察。它不是单纯的爬虫脚本也不是单纯的画图而是一条从数据源到结论的通道。适合刚入门Python爬虫的开发者、要做电商反馈分析的产品或运营以及想拿真实数据集做课设的学生。真动手后会发现难的不是爬虫本身而是接口反爬和情感分析的领域偏差这两块占掉整个项目八成调试时间。2. 京东评论爬取接口定位、参数构造与增量去重设计2.1 评论是动态加载的先找到数据接口再谈爬取直接下载商品详情页的HTML翻遍源码也找不到评论内容。京东评论全部由JavaScript脚本异步请求接口加载服务端渲染的页面里只有商品主图、价格和标题。所以第一步不是写爬虫而是打开浏览器开发者工具切到Network面板勾选Fetch/XHR往下滚动评论区等到评论出现后在请求列表里找一条名称类似于client.action或shou.jd.com的记录点开它的响应体才能看到真正的评论JSON。找到接口之后要做的第一件事是观察URL参数。京东评论流接口的关键参数通常是这几个functionId标识接口名称常见的是commentsSearchproductId是商品ID也就是商品详情页URL里sku后面的数字score表示评论类型0是全部、1是好评、2是中评、3是差评、5是晒图sortType控制排序方式5代表按时间排序page是页码pageSize是每页条数。把这些参数整理成函数爬虫部分就完成了一半。import requests def build_comment_url(product_id: str, page: int 0, score: int 0) - str: 构造京东评论列表接口URL :param product_id: 商品ID取自商品详情页URL中的sku参数 :param page: 页码从0开始 :param score: 0全部 1好评 2中评 3差评 5晒图 params { functionId: commentsSearch, productId: product_id, page: page, score: score, sortType: 5, pageSize: 30, } base https://api.m.jd.com/client.action return base ? .join(f{k}{v} for k, v in params.items()) print(build_comment_url(1625010852, page0))按这个方式构造出来的URL可以直接在浏览器里打开测试能返回JSON就说明参数没写错。常见做法是先手动打开一次把响应结构里的字段名记下来再去写解析代码。参数说明page从0开始有的分页接口从1开始我这里统一从0翻页才能拿到第一页漏了这一点很容易把第一页重复爬三遍。sortType用5按时间排序的评论分布比“推荐排序”更接近真实口碑后续做趋势分析也更有价值。pageSize不要调太大30条一页足够调成100虽然能少翻几页但单次请求体变大更容易触发风控。2.2 翻页与重试让爬虫在“能跑”和“被封”之间走钢丝接口定位好后第二个坑是请求头的完整性。直接拿requests.get去访问这个URL大概率返回一堆乱码或者登录跳转因为京东会校验User-Agent和Referer。用requests.Session把headers固定下来将登录后的Cookie写进配置这样每次翻页都带上同一份身份信息。import time import random import requests session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://item.jd.com/1625010852.html, Accept: application/json, text/plain, */*, }) def fetch_comments(product_id: str, max_pages: int 10, score: int 0): all_comments [] for page in range(max_pages): url build_comment_url(product_id, pagepage, scorescore) for attempt in range(3): try: resp session.get(url, timeout5) data resp.json() if data.get(code) 0 and data.get(commentInfo): comment_list data[commentInfo][commentList] if not comment_list: return all_comments all_comments.extend(comment_list) break elif data.get(code) 108: print(登录态失效需要重新扫码获取Cookie) return all_comments else: print(fpage{page} 返回异常等待后重试: {data.get(code)}) except requests.RequestException: time.sleep(random.uniform(3, 6)) time.sleep(random.uniform(2, 5)) return all_comments逻辑说明使用Session而不是每次重新构造requests请求是因为登录Cookie只需要设置一次后续翻页请求自动带上省去每次拼header的麻烦。内层for attempt in range(3)控制单页重试次数重试前先等待3到6秒避免连续请求同一页被识别成异常。如果接口返回code为108说明登录态失效继续重试也没有意义直接终止并提示人工处理。参数说明timeout设成5秒网络条件差的网络可以放宽到10秒但不要不设超时否则某个请求卡住会让整个爬虫停在那里。随机延时2到5秒的作用是让请求节奏接近真人浏览固定延时反而容易被时间序列上的规律性识别出来。max_pages建议先跑10页验证字段解析正确再根据评论总数调整页码范围。Cookie的有效期取决于登录方式和账号状态短则一天长则一周。实践做法是把Cookie存到配置文件里失效时手动扫码更新一次不要让爬虫请求过程中弹出验证码后自动退出。2.3 增量去重与落库Redis Set判重配合SQLite存储评论数据是持续的今天抓了1000条下周再跑一次又会多出几百条。增量逻辑要做对不然每次全量重爬不仅浪费时间情感分析那一步还要对重复评论重复打分。这里用Redis的Set结构做去重评论ID作为成员写入前先判断是否存在。有一个容易翻车的地方评论ID在不同商品下不保证全局唯一如果只拿评论ID做去重键抓商品A时入过库抓商品B时相同ID会被误判成已存在。所以去重键一定要用productId加评论ID拼接。抓取过程中可以打开redis可视化客户端比如Redis Desktop Manager或者Another Redis Desktop Manager直接看jd_comment_id_set这个集合的成员数量变化确认去重是否真的在生效。import redis import sqlite3 r redis.Redis(hostlocalhost, port6379, db1, decode_responsesTrue) def save_comments(product_id: str, comment_list: list): conn sqlite3.connect(jd_comments.db) cursor conn.cursor() cursor.execute(CREATE TABLE IF NOT EXISTS comments ( id TEXT PRIMARY KEY, product_id TEXT, content TEXT, score INT, creation_time TEXT, sentiment REAL )) saved 0 for c in comment_list: # 用商品ID评论ID拼接全局唯一标识避免不同商品评论ID冲突 unique_id f{product_id}_{c.get(id, )} if r.sismember(jd_comment_id_set, unique_id): continue content c.get(content, ).strip() if not content: continue cursor.execute(INSERT OR IGNORE INTO comments VALUES (?,?,?,?,?,NULL), (unique_id, product_id, content, c.get(score), c.get(creationTime))) r.sadd(jd_comment_id_set, unique_id) saved 1 conn.commit() conn.close() print(f本次新增 {saved} 条评论)逻辑说明先查Redis再写SQLite重复评论直接跳过。SQLite的INSERT OR IGNORE是第二道保险防止同一个会话内因为并发或异常导致重复写入。sentiment字段先留成NULL等情感分析跑完后统一回填这样爬虫和分析两个环节可以分开执行任意一步失败都不影响另一部分数据。参数说明decode_responsesTrue让sadd和sismember操作返回字符串而不是bytes调试时少一层解码。db设成1避开默认db0里可能存在的其他项目Key防止Key撞车。id字段设成TEXT主键因为拼接后的ID是字符串如果设成INTEGER某些长ID会超范围写入失败。3. 情感分析先用SnowNLP跑通基线再用领域语料修正偏差3.1 文本情感分析为什么先上SnowNLP十分钟拿到第一版结果爬完评论不是终点判断“这句是好评还是差评”才是关键。文本情感分析这个方向现在已经有从单句判断扩展到多模态的趋势但针对京东评论这种短文本第一批尝试的价值在于先把流水线跑通再考虑精度。SnowNLP是中文情感分析里起步最快的一个库pip install snownlp就能用内置模型直接对一句话输出0到1之间的情感分数接近1偏向正向接近0偏向负向。from snownlp import SnowNLP comments [ 这次买的降噪耳机效果超出预期降噪一开整个世界都安静了, 续航一般般用两个小时就没电了, 第二次买了做工扎实性价比很高, ] for text in comments: score SnowNLP(text).sentiments label 好评 if score 0.6 else (差评 if score 0.4 else 中评) print(f{score:.2f} {label} {text})逻辑说明sentiments属性返回情感分数0.99这种值说明模型对正向判断非常确定0.02说明负向倾向明显。和京东星级不同情感分数是连续的0.51和0.49之间没有本质差异所以阈值不要定成0.5一刀切0.6和0.4之间留一个灰色的中评区间更接近人工标注的习惯。参数说明0.6和0.4这两个阈值是快速切分三档的常见取值。不同商品品类可以微调比如美妆类评论里负面表达往往更柔和“还行吧”可能实际是差评这时候把差评阈值抬高到0.45更合理。先别急着上大模型。第一版用SnowNLP跑完把情感分和京东星级做交叉比对能马上知道基线哪里有问题再决定要不要换模型。3.2 通用模型在电商评论上的翻车自建训练语料的标注与训练用一段时间会发现一个典型现象好评里写到“物流快得离谱第二天就到了”SnowNLP给出的分数偏低。原因在于内置语料里“物流”“包装”这类词经常出现在投诉语境中词袋模型只看到词频看不清上下文。这是通用情感模型的领域偏差业内常说是黑匣子只能靠领域数据矫正。解决办法是自己构造训练语料重新训练SnowNLP的分类器。数据不需要人工从头标注可以从已经爬下来的评论里按星级抽样5星评论归正向1星和2星归负向。中评不要混进去因为中评表达经常模棱两可会拉低边界准确率。from snownlp import sentiment import sqlite3 # 1. 从库里抽取已标注样本5星归正向1和2星归负向 conn sqlite3.connect(jd_comments.db) rows conn.execute( SELECT content, score FROM comments WHERE score IN (1, 2, 5) ).fetchall() with open(pos_comment.txt, w, encodingutf-8) as f1, \ open(neg_comment.txt, w, encodingutf-8) as f2: for content, score in rows: if score 5: f1.write(content \n) elif score 2: f2.write(content \n) # 2. 训练并保存新模型注意第一个参数是负向语料 sentiment.train(neg_comment.txt, pos_comment.txt) sentiment.save(jd_sentiment_model.marshal)逻辑说明train函数两个参数的位置很容易写反第一个是负向语料文件第二个是正向语料文件。写反之后整个模型的情感方向颠倒好评全部被判成低分落库后整列情感数据全错而且要等跑完一轮训练加预测才能发现浪费一两个小时。参数说明每个类别的语料至少500行我一般凑到1500到2000行太少会让贝叶斯概率估计偏得厉害。语料里的重复评论要去掉训练前用set或者去重脚本过滤一遍。训练完成后生成的marshal文件需要复制到snownlp安装目录下的sentiment文件夹里替换默认的sentiment.marshal之后所有SnowNLP(text).sentiments调用都会走新模型。替换前先备份原文件这个后悔药一定要留。训练完一定要做验证拿100条没参与训练的评论人工标注好正负跑一遍新模型算准确率。如果正向召回率低于0.75补正样本负向召回率低补负样本。补完重训两三轮就稳定了。3.3 什么时候值得换BERT精确率和句式复杂度基线模型跑完如果准确率还在0.7以下或者评论里大量出现“整体还行但售后实在拉胯”这类转折句式SnowNLP的词袋结构确实处理不了。这时候再考虑用BERT做文本分类微调。判断标准很简单模型输出的情感分和京东星级对不上而且错例集中在带转折、带反讽的句子上。这类句子词袋模型看不到否定词和转折词的关系需要带上下文建模能力的中文预训练模型。from transformers import AutoTokenizer, AutoModelForSequenceClassification from transformers import Trainer, TrainingArguments # 假设 train_texts 是评论文本列表train_labels 是0/1标签 tokenizer AutoTokenizer.from_pretrained(hfl/chinese-roberta-wwm-ext) model AutoModelForSequenceClassification.from_pretrained( hfl/chinese-roberta-wwm-ext, num_labels2 ) train_encod tokenizer(train_texts, truncationTrue, paddingTrue, max_length128) training_args TrainingArguments( output_dir./bert_comment_model, num_train_epochs3, per_device_train_batch_size16, learning_rate2e-5, save_strategyepoch, ) trainer Trainer(modelmodel, argstraining_args, train_datasettrain_encod) trainer.train()逻辑说明这段只给了骨架因为真正上手时更花时间的是数据清洗和标签构造。训练数据量要求从SnowNLP的1500行提升到5000条左右训练时间从秒变成小时级别显存至少6G。如果没有这个预算先别换。参数说明max_length设128京东评论绝大多数不到这个长度超过部分直接截断不影响判断。batch_size16在8G显存上比较稳中途OOM就降到8。learning_rate2e-5是中文文本分类微调的安全默认值改太大容易把预训练权重冲坏。三个方案的选择可以看这张表方案准备成本训练耗时典型准确率适用阶段SnowNLP无秒级0.65-0.75基线、快速跑通流水线自训练SnowNLP1-2小时标注分钟级0.75-0.85单品类商品评论BERT微调半天标注与清洗小时级GPU0.85-0.92多品类、上线给业务用4. 可视化呈现把情感分数变成能汇报的图表与大屏4.1 先想清楚给谁看报表型图表与可视化大屏的选型差异数据可视化不是画得越花哨越好而是让看的人一眼读出结论。自己做研究用pyecharts生成静态HTML就够要给团队或答辩展示就需要按可视化大屏的思路来布局。这两者代码差别不大差异主要在容器组织和刷新频率上。echarts数据可视化生态下的pyecharts库把前端图表的配置项封装成了Python链式调用后端算好数据前端渲染图表改造起来很顺手。情感分析有几个固定要看的图情感分布饼图、情感分数日趋势折线图、关键词词云。饼图回答“这批评论整体正负比例多少”折线图回答“差评是不是集中在某个时间点爆发的”。from pyecharts.charts import Pie, Line from pyecharts import options as opts def sentiment_pie(df) - Pie: counts df[label].value_counts() pie ( Pie() .add(, [list(z) for z in zip(counts.index, counts.values)]) .set_global_opts(title_optsopts.TitleOpts(title评论情感分布)) .set_series_opts(label_optsopts.LabelOpts(formatter{b}: {c} ({d}%))) ) return pie def sentiment_trend(df) - Line: daily df.groupby(df[date].dt.date)[sentiment].mean().reset_index() line ( Line() .add_xaxis(daily[date].astype(str).tolist()) .add_yaxis(平均情感分, daily[sentiment].round(3).tolist()) .set_global_opts( title_optsopts.TitleOpts(title情感分数日趋势), yaxis_optsopts.AxisOpts(min_0, max_1), ) ) return line逻辑说明饼图传入的数据是成对的[名称, 值]列表先做value_counts聚合再传给add能避免把整个DataFrame塞进去导致图表内部处理NaN。折线图把groupby结果里的date列转成字符串因为pyecharts的x轴不接受datetime对象不转的话图表会直接报类型错误。参数说明情感趋势图的y轴范围固定成0到1是根据情感分的定义域设置的。不手动设的话pyecharts会从0.2起步本来平稳的0.65到0.7之间波动会被放大成“剧烈变化”让看图的人误读趋势。4.2 词云的正确打开方式jieba中文分词与停用词过滤词云是情感分析报告里最直观也最容易翻车的图。不处理停用词的话图里最大的几个字永远是“京东”“这个”“东西”“感觉”完全看不出产品特征。生成词云前必须做两件事装载自定义词典把品牌名和型号词固定住避免“AirPods”被切碎过滤场景停用词把平台通用词和口头禅从分词结果里删掉。import jieba from wordcloud import WordCloud stopwords set() with open(jd_stopwords.txt, encodingutf-8) as f: for line in f: stopwords.add(line.strip()) # 把品牌/型号加入自定义词典避免被误切 jieba.load_userdict(jd_userdict.txt) def build_wordcloud(comments: list, image_path: str comment_cloud.png): words [] for text in comments: segs jieba.lcut(text) words.extend([w for w in segs if w not in stopwords and len(w) 1]) wc WordCloud( font_pathC:/Windows/Fonts/simhei.ttf, width1200, height800, background_colorwhite, max_words200, ).generate( .join(words)) wc.to_file(image_path)逻辑说明jieba.lcut返回一个分词列表过滤停用词和单字词后用空格连接成一个长字符串。WordCloud内部按空格分词所以拼接时不能用逗号或者直接传列表否则中文词云会糊成一坨。参数说明font_path是词云最容易出错的地方。Windows本地开发用simhei.ttf能正常显示部署到Linux服务器上必须改成系统里中文字体的路径常见位置是/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc不确定就先执行fc-list :langzh看输出。max_words设200足够再小的词频太低视觉上就是噪点。提示jd_stopwords.txt是纯文本文件每行一个词。网上有很多通用中文停用词表但京东场景还要额外加“京东、快递、东西、感觉、真的、商品”这类场景高频词。4.3 把脚本串成可交互面板Streamlit的极简可视化界面静态HTML图表适合放进报告但如果想自己点一点、筛一筛就得把前面所有环节包进一个交互界面。用Streamlit可以把几十行爬虫结果读取和分析代码直接变成web页面这已经是一个完整的python爬虫可视化界面不用单独写前端。import streamlit as st import pandas as pd st.set_page_config(page_title京东评论情感分析, layoutwide) df pd.read_sql(SELECT * FROM comments, sqlite:///jd_comments.db) product_id st.sidebar.selectbox(选择商品, df[product_id].unique()) score_filter st.sidebar.selectbox(评论类型, [全部, 好评, 中评, 差评]) sub df[df[product_id] product_id] if score_filter ! 全部: label_map {好评: 5, 中评: 3, 差评: 1} sub sub[sub[score] label_map[score_filter]] st.plotly_chart(sentiment_pie(sub)) st.plotly_chart(build_wordcloud(sub[content].tolist())) st.dataframe(sub[[content, score, sentiment]].head(100))逻辑说明Streamlit的特点是脚本每次交互都会从上到下重新执行一遍所以图表函数内部不要做耗时太长的全量计算。数据量上来以后给读取SQLite和聚合计算加st.cache_data装饰器否则每点一次下拉框都要重新读库页面卡顿很明显。参数说明sidebar.selectbox会在左侧渲染下拉框选择结果直接驱动后续DataFrame筛选。layoutwide让图表占满整个浏览器宽度适合大屏展示。dataframe组件自带搜索和排序比直接贴表格更适合放汇报页面。到这里“爬虫、情感分析、可视化”的闭环已经通了。剩下的问题在于这套东西怎么在没人盯着的情况下自己每天跑。5. 避坑京东评论爬取与情感分析最常踩的五个坑5.1 接口返回code108但浏览器还能打开Cookie失效与风控节奏现象爬虫跑了十几分钟后接口开始返回code108日志里全是登录态失效但用浏览器手动打开同一个接口地址却能正常返回数据。原因高频请求触发了风控服务端要求本轮请求重新校验登录态Cookie本身还没有过期但已经被标记为可疑。这个返回码是京东接口安全策略的通用信号并不等价于账号被处罚。解决把单次请求间隔下坠到3到5秒不要每页只停2秒。用Session保存Cookie并在启动前做一次验证请求失效再提示人工处理。如果换了一组Cookie还是十几分钟就失效就换一个出口IP继续跑别在同一IP下硬刚。5.2 评论星级是5分情感分却只有0.2领域偏差在作祟现象明显的好评内容“到货很快包装严实没有磕碰”SnowNLP算出来情感分低于0.3与京东星级严重矛盾。原因通用模型的训练语料里“包装”“到货”经常出现在投诉语境中词袋模型只统计词频和共现关系看不到“没有磕碰”这个否定结构。这是通用情感分析模型在电商评论上的经典偏差。解决不要直接用通用模型结果入库。按照3.2节自建京东评论正负语料并重新训练训练后抽100条真实评论做交叉验证。正向召回率和负向召回率都达到0.75以上再批量回填sentiment字段。5.3 词云里全是“京东”“东西”停用词表不贴合场景现象词云生成后几乎无法阅读最醒目的词全是“京东”“东西”“感觉”“真的”这类场景高频词产品本身的特征词全被淹没了。原因通用停用词表覆盖了“的”“了”“是”这类虚词但漏掉了电商场景里的泛指词和语气词。这些词在评论里出现频率极高如果不过滤词频排序后一定排在最前。解决维护一份场景停用词表把商品详情库里出现的品牌词、型号词也加进去。每次生成词云后人工扫一眼连续两次出现的无义词直接加入停用词表。这个迭代动作比调wordcloud参数有用得多。5.4 Redis里的评论ID在涨SQLite不涨去重键设计有误现象redis可视化客户端里集合的成员数量一直在增加但SQLite里的记录数始终不变每次跑完日志都显示新增0条。原因去重键只用了评论ID不同商品下的评论ID可能相同。抓商品A时这个ID入过库抓商品B时相同ID被误判成已存在于是全部跳过。解决去重键改成product_id加评论ID拼接的字符串SQLite表主键也同步用这个拼接串。如果数据已经错乱把Redis里的旧集合删掉重新全量跑一遍代价是几分钟重爬时间但能保证数据完整。5.5 服务器上词云全是豆腐块中文字体路径缺失现象本机生成的词云一切正常部署到Linux服务器后图片里的中文全部显示成方块。原因wordcloud和matplotlib在Linux上默认字体不包含中文字形渲染时每个字都落空画出来的就是方框。解决在服务器上执行fc-list :langzh查看可用的中文字体路径把路径填到font_path参数里。如果是容器把Windows里的simhei.ttf复制进/usr/share/fonts目录执行fc-cache -f刷新字体缓存后重新生成。5.6 大屏页面空白但数据有值图表序列化失败现象pyecharts render出来的HTML打开是白屏浏览器控制台报序列化错误但DataFrame里的数据是完整的。原因add_yaxis接收到numpy类型或NaN值pyecharts在把数据转JSON时无法处理这些类型。常见于情感分列存在NULL或者聚合结果里混入了numpy.float64。解决传给图表之前先df.fillna(0)再对numpy类型做.tolist()转换。把图表函数写成纯输入输出的工具函数固定一份样例数据做回归测试之后挂到面板上出问题能第一时间定位到是数据问题还是渲染问题。6. 让流水线自动跑起来定时任务、校验与习惯6.1 用APScheduler让爬虫每天自动跑一遍评论是每天增长的情感分析结果也是动态变化的。一个可落地的项目不能每次都手动执行脚本而是要用定时任务把它串起来。APScheduler是Python里常用的定时调度库阻塞式调度器配合cron触发器就能满足这个场景。from apscheduler.schedulers.blocking import BlockingScheduler def daily_task(): # 以下函数分别复用第2章到第4章的实现 comments fetch_new_comments(1625010852, max_pages5) save_comments_to_db(comments) update_sentiment_for_uncored() render_dashboard() if __name__ __main__: scheduler BlockingScheduler(timezoneAsia/Shanghai) scheduler.add_job(daily_task, cron, hour8, minute30) scheduler.start()逻辑说明hour8, minute30代表每天早上8点30分执行一次完整链路。评论日增量通常不大一天一次足够低频请求也能让Cookie生命周期更长。render_dashboard在每次任务最后执行生成新的HTML覆盖旧文件打开就是最新结果。6.2 给准确率做一个校验不只看图还要看数字定时任务跑起来以后还要有一个验证环节盯住模型状态。我一般会在每天的任务里加一个对比当天平均情感分与昨天相差超过15%就输出一条提醒。这个变化可能来自真实舆论波动也可能来自模型退化但不管哪种都要人工看一眼才能确认。除了每日对比每周还要做一次小样本复核从库里随机抽50条评论人工标注后和模型结果比对准确率低于0.75就重新触发训练脚本。这个动作能防止新出现的表达方式把模型带偏。我自己的习惯是每周看一眼新增评论里有没有高频新词有就往停用词表或自定义词典里补。跑得越久这套小系统就越贴合目标品类的真实表达。数据积累和价值沉淀在这类项目里是复利第一周效果平平跑上一个月再回头看趋势图和词云已经完全变样了。希望帮到你。本文还有配套的精品资源点击获取

相关推荐

LLM之Agent(九十八)|DeepSeek-Harness(八)测试策略与 CI 门禁
LLM之Agent(九十八)|DeepSeek-Harness(八)测试策略与 CI 门禁

"测试通过"和"功能真的能用"之间隔着好几层容易被忽略的陷阱——mock 太多会验证不到真实链路,覆盖率只证明代码跑过、不证明行为正确,而 CI 矩阵如果全靠 YAML 手写会迅速失控成没人敢改的黑箱。DeepSeek Harness 用一套分层的 Vitest 测试体系 一套用 T… · 2026/9/24 18:35:15

Python京东评论爬取与情感分析可视化:从数据采集到词云报告
Python京东评论爬取与情感分析可视化:从数据采集到词云报告

简介:这是一套面向Python学习者与数据分析初学者的电商评论挖掘实战资源,以京东商品评价为对象,完整覆盖爬虫采集、数据清洗、情感分类与可视化展示全流程。压缩包共20个文件,大小约5.87MB,包含Python脚本、CSV数据集、… · 2026/9/24 18:35:15

个人微信API二次开发:微信群消息自动化怎么实现?
个人微信API二次开发:微信群消息自动化怎么实现?

群自动化往往不止「往群里发一句」。通知、自动回、 某人、建群拉人,都会碰到。个人微信没有官方群机器人可挂进客户群;个人微信API二次开发里,能在群里说话的,只能是已经在群里的那个个人微信号。 群会话的 toWxid 是 xxxchatro… · 2026/9/24 18:35:08

PostgreSQL存储过程与函数实战:告别数据搬运工,实现性能飞跃
PostgreSQL存储过程与函数实战:告别数据搬运工,实现性能飞跃

先说个我自己的经历。前几年做一个营销数据中台,每天凌晨要从订单库同步几百万行明细到分析库,然后按用户、按商品、按渠道做汇总。最初的方案很典型:写一个 Java 定时任务,把明细全查出来,在内存里分组求和&#xff0… · 2026/9/24 19:39:15

警惕GhostClaw仿冒OpenClaw:恶意安装脚本窃取API密钥全解析
警惕GhostClaw仿冒OpenClaw:恶意安装脚本窃取API密钥全解析

周末凌晨两点,一个开发者朋友突然给我发来一串截图:他照着某篇“OpenClaw 安装教程”配置好的环境,第二天发现 GitHub 上出现了不属于自己的 commit,而且云厂商的账单里多了一台从没开过的境外服务器。排查到最后,问题… · 2026/9/24 19:39:15

埋点选型避坑指南:神策、PostHog、ClkLog 数据模型与治理深度对比
埋点选型避坑指南:神策、PostHog、ClkLog 数据模型与治理深度对比

埋点选型这件事,我前前后后参与过四次,从早期自研打点 SDK,到后来采购商业平台,再到用开源方案自己搭一套,每次踩的坑都不太一样。最让我印象深刻的是一次"功能表选型"翻车:当时团队拉了一张几十… · 2026/9/24 19:39:15

一人公司出海指南:从自由职业到微型SaaS的实战路径
一人公司出海指南:从自由职业到微型SaaS的实战路径

最近总有朋友问我同一个问题:一个人真的能开公司吗?我的回答是,现在这个问题已经过时了,真正值得问的是——一个人能不能开一家面向海外市场的公司。上周一个前同事告诉我,他白天上班,晚上花三个月搭了个小… · 2026/9/24 19:39:15

让业务同事用说话查数据:一个取数 Agent 的四层架构与核心代码
让业务同事用说话查数据:一个取数 Agent 的四层架构与核心代码

把 Text2SQL 接到聊天框里,第一版通常跑不顺。原因不是 SQL 生成不准,而是真实对话里的问题从来不是单轮的: 「那华东呢?」——上一轮的指标和时间段要继承下来 「按这个口径再算一遍去年」——口径指的是哪一条得记住 「这两个… · 2026/9/24 19:39:15

百度网盘直链解析与下载加速:网页扩展与工具选型实战
百度网盘直链解析与下载加速:网页扩展与工具选型实战

1. 百度网盘直链解析的核心逻辑与场景拆解1.1 为什么直链解析一直是刚需百度网盘作为国内用户基数最大的个人云存储服务之一,长期承担着文件备份、资料分享、软件分发等角色。但免费账户的下载速度限制,让很多人在下载大体积文件时体验很差。一个几GB的安… · 2026/9/24 19:39:02

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程
基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为… · 2026/9/24 0:00:13

1D-CNN时间序列建模实战:从Conv1d原理到工业落地
1D-CNN时间序列建模实战:从Conv1d原理到工业落地

简介:面向时间序列数据建模的一维卷积神经网络完整实现,适合深度学习入门者及需要快速验证时序模型的研究者,能够从音频、文本、传感器或股价等序列中挖掘局部特征与时间依赖。压缩包体积很小,只有3KB,内含3个Python脚… · 2026/9/24 0:00:26

柔软的L:汉语语流中被忽视的舌肌张力控制
柔软的L:汉语语流中被忽视的舌肌张力控制

1. 这个“L”不是字母表里的L,而是舌尖上的L最近在几个方言群和语音教学社群里,反复看到有人发一句:“也说字母L:柔软的长舌”。初看以为是英语发音课笔记,点开才发现全是方言爱好者、播音系学生、语言康复师甚至戏曲演… · 2026/9/24 0:00:44

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码