用Python+NRC词典分析微博评论情绪:从愤怒到惊喜的完整代码实战

用Python+NRC词典解码微博情绪:从数据清洗到多维可视化的实战指南

最近在分析一个社交媒体项目时,我遇到了一个挺有意思的挑战:如何从海量的微博评论中,不只是简单地判断正面或负面,而是精准地捕捉用户那些更细腻的情绪波动——比如愤怒、惊喜、期待,甚至是厌恶。传统的二分类情感分析在这里显得有些力不从心,直到我开始深入研究NRC情感词典,才发现原来情绪可以被如此精细地量化。

对于数据分析师和Python开发者来说,社交媒体上的文本分析早已不是新鲜事。但真正把分析做到“有温度”,能区分出用户是“愤怒地吐槽”还是“悲伤地诉说”,这中间的差别往往决定了商业洞察的深度。NRC词典提供的正是这样一套多维度的情绪坐标系,它把情感拆解成8种基本情绪和正负两极,让我们能够用数据语言描述人类的复杂情感。

在这篇文章里,我会分享一套完整的实战流程,从原始微博数据的抓取清洗开始,到NRC词典的本地化处理,再到避免中文分词陷阱的技巧,最后用多种可视化方式呈现情绪权重分布。整个过程都是我在实际项目中踩过坑、优化过的方案,特别适合需要处理中文社交媒体数据的朋友。

1. 环境准备与数据获取

1.1 Python环境配置

开始之前,确保你的Python环境已经安装了必要的库。我推荐使用Anaconda创建独立的环境,避免版本冲突。

# 创建新的conda环境
conda create -n weibo_emotion python=3.9
conda activate weibo_emotion

# 安装核心依赖
pip install pandas numpy jieba
pip install matplotlib seaborn plotly
pip install requests beautifulsoup4
pip install openpyxl  # 用于读取Excel格式的NRC词典

如果你习惯用pipenv或者virtualenv,原理也是一样的。关键是要有pandas做数据处理,jieba做中文分词,再加上matplotlib或seaborn做可视化。

注意:NRC词典的官方文件是Excel格式,所以openpyxl是必须的。如果你下载的是CSV版本,可以跳过这个安装。

1.2 NRC词典的获取与初步探索

NRC情感词典的官方名称是“NRC Emotion Lexicon”,由加拿大国家研究委员会开发。它覆盖了105种语言,包括简体中文。词典的独特之处在于,每个词语都被标注了是否属于8种基本情绪(愤怒、期待、厌恶、恐惧、喜悦、悲伤、惊喜、信任)以及正负情感倾向。

你可以从NRC的官方网站或学术数据平台获取最新版本。下载后,先用pandas看看它的结构:

import pandas as pd

# 加载词典文件
lexicon_path = 'NRC-Emotion-Lexicon-v0.92-In105Languages-Nov2017Translations.xlsx'
lexicon_df = pd.read_excel(lexicon_path)

# 查看列名和数据结构
print("词典总列数:", len(lexicon_df.columns))
print("前5列名称:", lexicon_df.columns[:5].tolist())

# 提取中文部分
chinese_columns = ['Chinese (Simplified) (zh-CN)', 'Positive', 'Negative', 
                   'Anger', 'Anticipation', 'Disgust', 'Fear', 
                   'Joy', 'Sadness', 'Surprise', 'Trust']

chinese_df = lexicon_df[chinese_columns].copy()
print(f"中文词典条目数: {len(chinese_df)}")
print("\n前几条数据示例:")
print(chinese_df.head())

运行这段代码,你会看到一个结构清晰的DataFrame。每一行代表一个中文词语,后面的列用1或0标记这个词语是否属于某种情感类别。比如“快乐”这个词,在“Joy”和“Positive”列会是1,其他列是0。

1.3 微博评论数据获取策略

对于微博数据,我通常采用两种方式获取:

方式一:微博官方API 如果你有企业资质或研究用途,可以申请微博开放平台的API权限。这种方式最稳定合规,但需要审核。

方式二:网页爬取(仅供学习研究) 对于小规模分析,可以通过requests和BeautifulSoup获取公开数据。这里强调一下,一定要遵守网站的robots.txt,控制请求频率,避免对服务器造成压力。

import requests
from bs4 import BeautifulSoup
import time
import random

def fetch_weibo_comments(weibo_id, max_comments=100):
    """模拟获取微博评论(示例函数,实际需要根据微博页面结构调整)"""
    base_url = f"https://weibo.com/ajax/statuses/buildComments"
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'Referer': f'https://weibo.com/{weibo_id}'
    }
    
    comments = []
    page = 1
    
    while len(comments) < max_comments:
        params = {
            'id': weibo_id,
            'page': page,
            'count': 20
        }
        
        try:
            response = requests.get(base_url, headers=headers, params=params, timeout=10)
            if response.status_code == 200:
                data = response.json()
                if 'data' in data and data['data']:
                    for item in data['data']:
                        comment_text = item.get('text', '').strip()
                        if comment_text:
                            comments.append({
                                'comment_id': item.get('id'),
                                'text': comment_text,
                                'user': item.get('user', {}).get('screen_name', ''),
                                'created_at': item.get('created_at', '')
                            })
                    page += 1
                    # 随机延迟,避免请求过快
                    time.sleep(random.uniform(1, 3))
                else:
                    break
            else:
                print(f"请求失败,状态码: {response.status_code}")
                break
        except Exception as e:
            print(f"获取数据时出错: {e}")
            break
    
    return pd.DataFrame(comments)

提示:在实际项目中,我建议将获取的数据立即保存到本地文件或数据库,避免重复请求。同时,一定要添加异常处理和日志记录,方便调试。

2. 数据清洗与预处理:处理中文社交媒体的特殊性

2.1 微博文本的典型噪声

微博评论和正式文本有很大不同,直接分析效果会很差。常见的噪声包括:

  • 表情符号和颜文字:😂、😭、T_T、QAQ
  • 话题标签和@用户:#今日心情#、@好友名字
  • URL链接和短链:http://t.cn/xxxxx
  • 重复字符和网络用语:“哈哈哈哈哈哈”、“yyds”、“绝绝子”
  • 中英文混合及拼音:“这个idea不错”、“xswl”(笑死我了)

处理这些噪声需要一套组合拳。我常用的清洗流程是这样的:

import re
import jieba
from zhon.hanzi import punctuation as chinese_punctuation

class WeiboTextCleaner:
    def __init__(self):
        # 加载停用词表
        self.stopwords = self._load_stopwords()
        
        # 编译常用正则表达式
        self.url_pattern = re.compile(r'https?://\S+|www\.\S+')
        self.mention_pattern = re.compile(r'@\w+')
        self.hashtag_pattern = re.compile(r'#\w+#')
        self.emoji_pattern = re.compile("["
            u"\U0001F600-\U0001F64F"  # 表情符号
            u"\U0001F300-\U0001F5FF"  # 符号和象形文字
            u"\U0001F680-\U0001F6FF"  # 交通和地图符号
            u"\U0001F1E0-\U0001F1FF"  # 国旗符号
            "]+", flags=re.UNICODE)
    
    def _load_stopwords(self):
        """加载中文停用词表"""
        stopwords = set()
        # 可以从文件加载,这里先定义一些基础停用词
        basic_stops = ['的', '了', '在', '是', '我', '有', '和', '就', 
                      '不', '人', '都', '一', '一个', '上', '也', '很', 
                      '到', '说', '要', '去', '你', '会', '着', '没有', 
                      '看', '好', '自己', '这']
        stopwords.update(basic_stops)
        return stopwords
    
    def clean_text(self, text):
        """完整的文本清洗流程"""
        if not isinstance(text, str):
            return ""
        
        # 1. 转换为小写(英文部分)
        text = text.lower()
        
        # 2. 移除URL
        text = self.url_pattern.sub('', text)
        
        # 3. 移除@提及和话题标签
        text = self.mention_pattern.sub('', text)
        text = self.hashtag_pattern.sub('', text)
        
        # 4. 移除表情符号
        text = self.emoji_pattern.sub('', text)
        
        # 5. 处理重复字符(如"哈哈哈哈" -> "哈")
        text = re.sub(r'(.)\1{2,}', r'\1', text)
        
        # 6. 移除多余空白字符
        text = re.sub(r'\s+', ' ', text).strip()
        
        return text
    
    def tokenize_chinese(self, text):
        """中文分词并去除停用词"""
        cleaned_text = self.clean_text(text)
        if not cleaned_text:
            return []
        
        # 使用jieba分词
        words = jieba.lcut(cleaned_text)
        
        # 过滤停用词和标点
        filtered_words = []
        for word in words:
            word = word.strip()
            if (word and 
                word not in self.stopwords and
                word not in chinese_punctuation and
                not word.isspace() and
                len(word) > 1):  # 过滤单字(除非是情感词)
                filtered_words.append(word)
        
        return filtered_words

2.2 处理网络新词与情感词扩展

中文网络用语更新极快,很多新词在标准词典里找不到。比如"破防了"、"emo了"、"蚌埠住了"这些词,都有强烈的情感色彩,但NRC词典可能没有收录。

我的做法是维护一个自定义的情感词扩展表:

# 自定义情感词扩展(示例)
custom_emotion_words = {
    '破防了': {'Anger': 0.7, 'Sadness': 0.8, 'Negative': 1},
    'emo了': {'Sadness': 0.9, 'Negative': 1},
    '蚌埠住了': {'Joy': 0.6, 'Surprise': 0.5, 'Positive': 0.7},
    'yyds': {'Joy': 0.8, 'Trust': 0.7, 'Positive': 1},
    '绝绝子': {'Joy': 0.7, 'Surprise': 0.6, 'Positive': 0.8},
    '躺平': {'Sadness': 0.6, 'Negative': 0.7, 'Disgust': 0.4},
    '内卷': {'Fear': 0.5, 'Negative': 0.8, 'Anger': 0.3},
}

# 可以定期从社交媒体热点中更新这个词表
def update_custom_lexicon(new_words_dict):
    """更新自定义词典"""
    global custom_emotion_words
    for word, emotions in new_words_dict.items():
        if word not in custom_emotion_words:
已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 ### TDS 2014示波器使用手册知识点总结 #### 一、TDS 1000B 和 TDS 2000B 系列数字存储示波器概述 - **产品系列**: TDS 1000B 和 TDS 2000B 是由 Tektronix 公司所研发并推出的数字存储示波器产品线。 - **功能定位**: 主要致力于为电子工程师以及研发人员提供具备高性能与高精度的信号测量设备。 - **应用领域**: 此类设备被普遍应用于教育机构、研发实验室以及工业生产过程中的测试环节。 #### 二、TDS 2014示波器基本操作与使用 - **开机与基本设置**: - 在启动设备时,必须确保仪器已经正确接地。 - 在使用之前,需要根据观察需求设定合适的屏幕亮度、对比度等显示参数。 - **通道选择与配置**: - 可以通过触摸显示屏或设备前面板上的按钮来选定需要进行的测量通道。 - 可依据实际需求来调整垂直灵敏度、水平时间基准等设置项。 - **触发设置**: - 触发模式包括自动、常态、单次等多种选择。 - 触发源与阈值设定涉及确定触发信号的具体来源及其电压阈值水平。 - **测量与分析功能**: - 提供多种自动测量功能选项,涵盖电压峰峰值、频率等参数的测量。 - 支持对波形进行数学运算,例如执行两个波形的相加或相减操作。 #### 三、TDS 2014示波器高级特性 - **波形捕获率**: - 波形捕获率越高,意味着在检测偶发事件方面的能力越强。 - **波形存储与回放**: - 支持将波形数据存储到内部存储单元或外部存储设备中。 - 用户能够随时调取先前保存的波形数据,以进行深入分析。 - *...
内容概要:本文聚焦2026年高教社杯全国大学生数学建模竞赛B题“无线电干扰源的快速自动定位与清除”,同时整合了多个数学建模与工程技术仿真研究资源,涵盖SEM广告投放策略优化、无人机协同路径规划、电力系统无功优化、微电网调度、负荷预测、电动汽车响应率建模等多个领域。其中重点详述了SEM广告投放策略的系统性建模,构建了从问题诊断、关键词分类、预算优化到不确定性环境下鲁棒决策的完整框架。提出基于成本—效益二维归一化的五类关键词划分方法(黄金词、重点词、潜力词、问题词、无效词),并建立了0-1整数规划与CVaR鲁棒优化模型,实现注册转化最大化与风险控制的平衡。文档还汇集了大量基于Matlab/Simulink的仿真资源,涉及智能优化算法、机器学习、信号处理、路径规划等方向,并配套提供代码与论文支持,形成跨学科的技术资源共享平台。; 适合人群:具备一定数据分析与建模基础,正在准备数学建模竞赛或从事科研工作的本科生、研究生及工程技术人员。; 使用场景及目标:①应用于数学建模竞赛备赛,学习多目标优化、分类模型、鲁棒决策等建模范式;②开展广告投放、电力调度、路径规划等领域的科研项目时借鉴模型构建与算法实现方法;③通过提供的Matlab/Python代码快速复现经典或前沿研究成果,提升科研效率与实践能力。; 阅读建议:此资源集合了多个独立研究主题,建议读者根据自身研究方向选择性阅读,重点关注模型构建逻辑与算法实现细节,并结合所提供的Matlab/Python代码进行实践验证,以加深理解与应用能力。
打开链接下载源码: https://pan.quark.cn/s/a89f7876a37d 将硅片上的电路管脚通过导线引至外部连接点,目的是为了与其他设备建立连接。封装类型指的是用于固定半导体集成电路芯片的外壳结构。这种外壳不仅承担着固定、密封、保护芯片以及改善电热特性等多重功能,同时通过芯片上的接触点利用导线连接至封装外壳的引脚,这些引脚再经由印刷电路板的线路与其他部件相连,从而完成芯片与外部电路的沟通。由于芯片必须与外界隔绝,以避免空气中杂质对电路造成腐蚀导致性能恶化,因此封装后的芯片也更为便于实施安装和运输。封装工艺的优劣直接关联到芯片自身特性和与之相接的PCB(衡量芯片封装技术水平的重要参照是芯片面积与封装面积的比例,这一比例越趋近于1则表示效果更佳。 【封装】在半导体产业中占据核心地位,其操作是将硅片上的电路端子借助导线连接至外部端口,以便与其他电子部件相接。封装的核心功能涵盖了固定、密封、保护芯片以及优化电热表现。封装外壳不仅作为芯片的物理防护层,更通过引脚将芯片与外部电路相连接,确保芯片功能的正常运作。封装的样式丰富多样,常见的有DIP(双列直插式封装)、SOP(小型封装)、SMD(表面贴装封装)、TO(晶体管封装)等。其中,TO-92是一种较为古老的晶体管封装方式,多用于小功率晶体管,其特征是在封装底部设有金属引脚,两侧各有两个引脚,外形类似字母“L”。 封装技术的革新直接影响芯片性能及其连接的PCB(印刷电路板)的工作效能。一个卓越的封装布局应尽可能减小芯片面积与封装面积的比率,从而提升封装的效率。除此之外,封装设计还需关注引脚的长度、间距、散热等要素,以减少信号传输的延迟,避免相互间的干扰,并确保良好的散热条件。封装技术的演进轨迹可从早期的TO封...
代码下载链接: https://pan.quark.cn/s/a4b39357ea24 依据所提供的文件资料,可以判断出这段代码与通过GPS数据计算电离层总电子含量(Total Electron Content, TEC)存在关联。尽管代码片段并不完整且包含了一些未完成的功能,但依然可以从现有资料中提取出一些关键性的知识点。 ### 1. 电离层总电子含量(TEC) **定义:** 电离层总电子含量(Total Electron Content, TEC)是指沿着信号传输路径单位面积上的电子总体数量,通常以TECU作为计量单位(1 TECU 等于 10^16 m^-2)。它作为研究电离层的重要指标之一,在卫星通信、导航系统以及遥感技术等领域具有关键性的应用意义。 **作用:** - **卫星通信与导航:** 掌握TEC数据有助于降低电离层对卫星信号的干扰,从而提升定位的精确度。 - **气象学与空间天气研究:** 通过监测TEC的动态变化,能够预测气象现象,特别是在太阳活动达到高峰的时期。 ### 2. GPS数据在TEC计算中的应用 **原理概述:** 电离层对GPS信号传播的主要影响表现为信号延迟现象。不同频率的GPS信号在穿过电离层时,由于受到不同电离层成分的作用会产生不同的延迟效果。因此,可以通过比较不同频率信号到达接收设备的时间差异来推算出电离层中的电子密度分布,进而得出TEC值。 **计算方法:** 一种常用的方法是通过双频观测数据来估算TEC。假设GPS接收设备接收到了两个不同频率的信号,比如L1和L2,它们分别位于1575.42 MHz和1227.6 MHz。通过分析这两个信号的相位差,可以消除大部分与接收设备相关的误差,从而精确地估算出电离层延...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值