ARTICLE DETAIL

资讯详情

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

用Python搭建网易新闻舆情热点分析平台的完整教程

用Python搭建网易新闻舆情热点分析平台的完整教程 简介一套基于网易新闻与评论的舆情热点分析平台完整Python项目源码面向Python初学者、课程设计及毕业设计学生。项目覆盖网络爬虫、数据清洗、中文分词、情感分析、关键词提取、时间序列分析与可视化展示等完整技术链路前后端功能齐全代码注释清晰便于理解与二次开发。资源共1403个文件压缩包大小23.83MB主要包含前端JS/CSS样式、Python业务脚本、HTML页面、数据库SQL文件以及设计文档docx、pptx、pdf等目录结构清晰。目前已有166人学习下载。通过该项目可掌握requests、BeautifulSoup、jieba、SnowNLP、Flask等常用库的实际组合应用了解舆情数据从采集到展示的工程化实现思路也能直接作为毕业设计演示与答辩参考素材是高性价比的实战学习资料。1. 网易新闻评论的舆情热点分析平台到底在分析什么如果在网上搜“舆情分析”出来最多的往往是某省委宣传部的大屏系统或者高校实验室的论文离普通开发者的实际诉求很远。而python083这个标题对应的是一个能用最常规的Python工具链把网易新闻正文和网友评论抓下来、算出哪些新闻正在被热议、大家的情绪偏向正还是负、热度随时间怎么变化并最终在浏览器里以图表方式呈现的完整分析平台。它解决的不是“爬一条新闻”这种一次性需求而是让你有一个可复用的底座换关键词、换时间范围就能持续追踪某一类事件在网易新闻生态里的讨论热度。适合谁用三类人。第一类是产品经理和技术负责人想低成本验证“舆情监测”这个功能在自己的业务里值不值得投入用这个方案三天内能出demo。第二类是Python学习者爬虫、数据处理、可视化三块基本功在这个项目里全部串起来了。第三类是拿它做毕业设计或项目申报的学生这个技术方向既不过时又不需要申请商业API权限。先把预期摆正这个方案抓的是网易新闻页面上能公开访问的内容不做任何反向破解也不依赖任何需要付费的第三方舆情数据接口。整个链路从requests请求开始到Flask网页结束中间夹着jieba分词、情感分析和pyecharts出图全是公开库。2. 跑通这个平台的环境准备Python版本、依赖和第一条抓取命令2.1 为什么推荐Python 3.8到3.10之间而不是最新版很多第一次接触这个项目的朋友一上来就装最新的Python 3.13然后在pip install环节卡半天。这里有个实际原因pyecharts、snownlp这些库的某些历史版本在过新的Python上容易出现依赖冲突尤其是lxml、pandas这类带二进制编译的包。我更建议你装Python 3.9或3.10这是目前兼容性最稳妥的区间。Linux和Windows都能跑但如果你在Windows上记得在安装Python时勾选“Add Python to PATH”这一步能省掉后面配置环境变量的时间。装好Python之后建议直接用conda或者venv建一个独立的虚拟环境别和系统Python混在一起。舆情平台要装的库有十几个混在全局环境里哪天卸载重装容易把系统工具整挂。下面是创建虚拟环境并安装依赖的做法# 创建名为 yq_env 的虚拟环境指定 Python 3.10 conda create -n yq_env python3.10 -y conda activate yq_env # 安装核心依赖按行拆分方便看清每个包的作用 pip install requests beautifulsoup4 lxml pandas jieba snownlp flask pyecharts wordcloud # 验证安装结果出现 3.10.x 说明当前环境正常 python -V这段命令里requests负责向网易新闻发HTTP请求beautifulsoup4配合lxml解析返回的HTML页面pandas做时间序列聚合jieba给文本分词snownlp做情感倾向打分flask起本地Web服务pyecharts在网页上绘制图表wordcloud生成词云图。如果你是第一次搭环境建议一条一条装别一次性全装完。某一条装失败时失败信息会直接被后面成功的输出冲掉排查起来反而费劲。2.2 拿到压缩包之后先按这个目录结构摆放文件解压后你会看到一堆 .py 文件和可能带有的静态资源目录。不管压缩包里原本怎么命名我一般建议手动归拢成下面这个结构后面所有命令都基于这个布局解释你按自己的情况微调即可analysis_platform/ ├── app.py # 入口启动Flask服务把数据渲染成网页 ├── spider/ │ ├── news_crawler.py # 抓取网易新闻列表页和正文页 │ └── comment_crawler.py # 抓取指定新闻下的评论列表 ├── analysis/ │ ├── hot_words.py # 对新闻标题和评论做分词、统计热点词 │ └── sentiment.py # 对评论逐条做情感打分并汇总 ├── data/ │ ├── news_raw.csv # 采集到的新闻原始记录 │ └── comments_raw.csv # 采集到的评论原始记录 └── templates/ └── index.html # Flask 前端页面用来展示图表摆放好目录后先不要立刻运行入口文件。先跑一条最简单的抓取命令验证网络请求链路通不通这一步能屏蔽掉大量后面才暴露的问题。在项目根目录打开终端进入Python交互模式或写个小脚本尝试请求网易新闻首页import requests headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 } resp requests.get(https://news.163.com/, headersheaders, timeout10) print(resp.status_code)如果输出200说明你的网络环境可以正常访问网易新闻Requests库也正常工作。如果出现超时或者403大概率不是代码问题而是访问频率受限或网络代理设置导致。这一条命令的价值在于把“环境问题”和“逻辑问题”切分开后面写爬虫时如果报错你就知道锅不在requests这一层。3. 抓网易新闻和评论两条链路两个接口别只盯着页面3.1 新闻列表页和正文页的抓取解析逻辑与字段设计网易新闻的内容分布是有规律的。首页的栏目区块会给出新闻链接每条新闻的URL形如“https://www.163.com/news/article/XXXXXX.html”链接末尾那段字符串就是这篇文章的唯一ID通常叫docid。后续抓评论时这个docid是核心入参。常见的抓取做法是先从网易首页或者特定频道页比如“国内”“国际”“社会”板块拿新闻链接列表再逐个请求详情页从详情页里提取标题、发布时间、来源、正文摘要。页面解析用BeautifulSoup就够了不需要上Scrapy这种重型框架毕竟不是大规模采集。写一个最小可运行的新闻抓取脚本focus在单页解析上import requests from bs4 import BeautifulSoup import pandas as pd def parse_news_list(channel_url): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 } resp requests.get(channel_url, headersheaders, timeout10) resp.encoding utf-8 soup BeautifulSoup(resp.text, lxml) news_items [] # 网易首页的新闻链接通常包裹在 class 含>import requests import time import pandas as pd def fetch_comments(docid, limit50): headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36, Referer: fhttps://www.163.com/news/article/{docid}.html, } # 以网易跟帖常见接口结构为例具体域名以实际抓包为准 comment_url ( fhttps://comment.news.163.com/api/v1/products/a2869674571/posts/{docid} f?limit{limit}offset0 ) resp requests.get(comment_url, headersheaders, timeout10) if resp.status_code ! 200: return [] data resp.json() comment_list data.get(comments, []) return [ { docid: docid, user: c.get(user, {}).get(nickname, 匿名用户), content: c.get(content, ).strip(), create_time: c.get(createTime), vote: c.get(vote, 0), } for c in comment_list ] if __name__ __main__: sample_docid 你的测试文章在URL末尾的那段ID comments fetch_comments(sample_docid, limit50) df pd.DataFrame(comments) df.to_csv(data/comments_raw.csv, indexFalse, encodingutf-8-sig) print(f抓到 {len(df)} 条评论)这里有个非常关键的头信息Referer必须设置为当前新闻详情页很多评论接口会校验来源域名不设Referer直接返回403或空数据。limit参数控制每次拉取条数网易接口一般有上限如果你发现单次请求最多只能拿50条或100条就按这个上限做循环翻页offset每次增加一个limit的长度直到返回的列表为空。这里的接口结构我只写了一个常见的、可靠的参考框架——具体域名、产品ID都以你抓包得到的为准不同时期网易后台接口会有调整。3.3 采集策略控制频率、随机延时和本地存储格式爬虫写得再好频率控制不当就会被封IP。经验做法是每请求完一个频道页sleep 1到2秒每抓完一篇新闻的评论sleep 2到3秒。睡眠时间可以用random.uniform(1, 2)做随机化避免出现规律的请求间隔被识别。存储格式直接统一用CSV字段提前规划好。新闻表至少包含title标题、url链接、publish_time发布时间、source来源。评论表至少包含docid所属新闻ID、nickname昵称、content正文、vote点赞数、create_time评论时间。编码统一写utf-8-sig这样用Excel打开CSV时中文不会乱码。每抓完一批就增量写入一次不要攒到最后才写防止程序中途崩溃丢掉全部成果。4. 从评论到热点分词、情感打分和热度排序的落地参数4.1 热点词提取用jieba分词加自定义词典过滤噪声拿到新闻标题和评论内容之后第一个核心任务是“哪些词正在被热议”。直接用jieba的默认词典跑一遍会发现一堆“了”“的”“吗”之类的停用词占着高频位置还有“网易”“新闻”这类来源词也会刷屏。这就需要两步处理加自定义词典把这些业务关键词比如“华为”“暴雨”“地震预警”“下调”等强制识别成完整词再配一个停用词表把无意义虚词过滤掉。写一个热点词提取的脚本把新闻标题和评论内容合并后统一处理import jieba import jieba.analyse import pandas as pd def extract_hot_words(news_df, comments_df, top_n30): # 合并语料新闻标题权重按2次计入评论正文按1次计入 news_text .join(news_df[title].astype(str).tolist()) comment_text .join(comments_df[content].astype(str).tolist()) corpus (news_text ) * 2 comment_text # 加载自定义词典每行一个词格式词语 词频 词性 jieba.load_userdict(dict/user_dict.txt) # 使用TF-IDF算法提取关键词allowPOS限定只取名词、动词和形容词 keywords jieba.analyse.extract_tags( corpus, topKtop_n, withWeightTrue, allowPOS(n, v, an, ns, nt), ) result [{word: w, weight: round(wt, 4)} for w, wt in keywords] return result if __name__ __main__: news pd.read_csv(data/news_raw.csv) comments pd.read_csv(data/comments_raw.csv) hot_words extract_hot_words(news, comments) for item in hot_words: print(item)这段代码里最有取舍空间的是allowPOS参数我限定在名词、动词、形容词和地名、机构名这样输出的是有实际语义的候选词。“网易”这种品牌词如果想排除就去停用词表里加一行。TF-IDF的topK控制在30以内太多会稀释词云的视觉效果太少又看不出热点层次。还要注意词频权重在舆情场景下不等于热度真正要关注的是“和昨天比突然升高”的词这需要后面通过对比计算实现。4.2 情感倾向分析snownlp的基础用法和它的局限舆情分析里最常被问到的就是“这波评论是正面还是负面”。Python生态里snownlp是上手成本最低的情感分析库不需要训练模型、不需要申请API一句from snownlp import SnowNLP就能用。但它的准确率在新闻评论这种短文本、口语化、反讽频出的场景下并不算高这是事实不能假装不存在。一个更稳的做法是用snownlp打分同时把分数落在0.4到0.6之间的评论全部标记为“中性情绪”只把两个极端区间当作有效正负面样本。因为snownlp的分值天然往0.5附近集中新闻评论里很多“无语”“什么鬼”这类反讽会被它误判成中性偏正面。如果你的样本量允许更进一步的优化是手动打标几百条用snownlp提取特征后训练一个朴素贝叶斯分类器但这不是必须的先按阈值标记能应对大部分场景。from snownlp import SnowNLP import pandas as pd def analyze_sentiment(comments_df): sentiments [] for _, row in comments_df.iterrows(): content row[content] if not content or len(content) 2: sentiments.append(neutral) continue score SnowNLP(content).sentiments # 分值范围 [0, 1]越接近1越正面 if score 0.4: sentiments.append(negative) elif score 0.6: sentiments.append(positive) else: sentiments.append(neutral) comments_df[sentiment] sentiments return comments_df if __name__ __main__: comments pd.read_csv(data/comments_raw.csv) result analyze_sentiment(comments) print(result[sentiment].value_counts()) result.to_csv(data/comments_sentiment.csv, indexFalse, encodingutf-8-sig)这里把中性区间拉大到0.4到0.6严格过滤掉无关情感。正负面比例计算时分母排除中性样本这样得到的正负面占比更有讨论价值。跑完之后打印分布如果负面比例低到离谱先别怀疑代码随便拿几条评论出来人工读一读多半会发现是反讽和夸张表达让snownlp误判了。4.3 热度排序把评论量、时间衰减和情感烈度合成一个指标“热度”不是单纯的评论数一篇两小时前评论猛增的新闻和一篇昨天火过今天降温的新闻热度含义完全不一样。常见做法是加权计算热度 评论量 * 时间衰减系数 * 情感烈度系数。时间衰减系数用指数形式表达越新的评论权重越大情感烈度用情感偏差量衡量即分类结果离0.5的距离越大说明情绪越强烈。合并成一个可排序的score然后按新闻分组做Top N排名这是舆情热点的核心输出。到这一步你就拥有了一个小型舆情平台的核心逻辑热点发现、情感判断、时间线变化全部可由注入的数据驱动。5. 舆情平台避坑指南四类常见问题与排查办法5.1 评论接口没有返回数据docid提取与鉴权参数缺一不可现象请求评论JSON接口返回200但数据列表为空或者直接返回错误信息“参数错误”。原因有两点一是docid从新闻URL里提取错了网易新闻有两种URL格式www.163.com/news/article/和www.163.com/dy/article/docid在两种格式里位置不同漏截或多截都可能导致查不到评论二是请求头里少了Referer网易评论接口会校验请求来源是否是该新闻页面。解决先从浏览器复制真实发出的评论请求对比你的docid提取正则和Header把Referer严格设置为新闻页URL再把注释信息里提到的产品ID核对一遍基本能修复。5.2 CSV读取后中文乱码或Excel打开异样现象用pandas读取CSV后打印正常但用Excel打开文件中文全变成乱码。原因写入CSV时用了默认的utf-8编码Excel默认按gbk或ANSI识别。解决所有to_csv和open操作里编码统一写encodingutf-8-sig这个带BOM的UTF-8格式能被Excel正确识别。如果是Python脚本直接读取CSV出现中文乱码把read_csv里的encoding改为“utf-8-sig”或“gbk”都试一遍用手指哪边乱码判断到底存的是什么编码。5.3 词云图上的关键词全是“我们”“什么”“一个”这类词现象jieba提取的关键词列表里混满无意义虚词顶部20个词完全不能描述舆情主题。原因没有加载合适的停用词表jieba自带的停用词表覆盖不全新闻口语里大量出现的“真的真的”“我觉得”“大家说”不处理就会排进前列。解决准备一个domain_stopwords.txt结合场景手工维护第一轮先加入“网易”“新闻”“现在”“自己”“我们”“什么”“一个”“这种”“那个”“就是”等高频虚词迭代两三轮后剩余结果就是有业务含义的热词。词频和TF-IDF权重是两个概念这里建议以TF-IDF排序为准。5.4 长时间运行时被限流请求状态码从200变成403现象脚本刚开始正常跑了十到二十分钟后所有请求全部403。原因每分钟请求数量超过了网易的限流阈值服务器识别出非人类访问行为。解决必须引入随机sleep和重试机制。每次请求前随机睡0.5到1.5秒遇到403时退避5到10秒再重试一次但连续重试两次还是403就停下别硬刚。更稳的做法是控制抓取总量单次运行不要抓超过2000条评论跑完一批间隔半小时再继续。把速度放慢这个方案就不需要代理池。6. 把平台做成每天自动跑的监测任务定时调度与结果验证6.1 用APScheduler或系统cron定时触发让数据自动更新开发环境里手动运行脚本没问题但舆情监测的核心是持续性。你需要把它挂成定时任务。两种方式如果平台只在你自己电脑上演示就写一个无限循环加sleep的调度脚本放那儿跑如果是部署在服务器上长期运行Linux下用cron最简单。先写好一个main.py把“抓新闻——抓评论——算热点——算情感——导出结果”全部串起来然后配cron。以Linux为例每天凌晨0点跑一次全量采集白天每4小时增量采集一次评论# 每天 0:10 执行全量采集 10 0 * * * cd /opt/analysis_platform /opt/conda/envs/yq_env/bin/python /opt/analysis_platform/main.py --mode daily logs/daily.log 21 # 每4小时执行一次评论增量更新 0 */4 * * * cd /opt/analysis_platform /opt/conda/envs/yq_env/bin/python /opt/analysis_platform/main.py --mode comments logs/comments.log 21cron里的精髓是两个一个是cd到项目根目录再执行确保相对路径不出错第二个是python解释器路径写绝对路径避免cron环境下PATH不包含conda环境。日志重定向到文件出错了翻日志比看终端输出方便一百倍。如果你在Windows上调度可以用“任务计划程序”配一个每日触发命令指向pythonw.exe运行入口脚本。6.2 用“昨天的热词今天出现没”检验平台的有效性需求方最常问的一句话是“准不准”。我的验证习惯是每天跑完任务后留一份热词快照次日对比增量。具体做法是hot_words.py的输出额外存一份带日期的文件比如hot_words_20241204.json。对比时看两件事一是头部热词的重合度如果连续三天Top10几乎一模一样说明没有新热点进入采集范围可能太窄需要扩展频道源二是新增词的权重排名比如“地震”这个关键词昨天没进Top20今天突然排到第3那这个信号就是真正值得关注的舆情热点。这种验证方式不需要外部标注每天肉眼扫一眼列表就能判断平台工作是否正常。6.3 一个让演示效果明显更好的附加技巧叠加评论时间线静态图表容易让领导或评委觉得没有“洞见”。我会额外输出一张“情感趋势折线图”横轴是小时纵轴是正面评论占比再叠一条评论总量柱状图。操作上很简单对comments_sentiment.csv里的create_time做datetime类型转换按小时聚合正负面评论数然后交给pyecharts画双Y轴图。这一张图能直接回答“事件是升温还是降温、情绪是好转还是恶化”是舆情平台汇报时的杀手锏。我自己的习惯是每次项目交接时在readme里写清楚运行命令、cron配置位置、停用词表维护入口。这样一旦踩到某个坑翻文档定位问题比重新读代码快得多。做舆情分析这类涉及数据采集和处理的项目稳定运行不翻车比功能花哨更值钱。希望帮到你。本文还有配套的精品资源点击获取
返回列表