探究
实验室
计算
公开
微博新闻情感分析
python
中文
新闻学
python中文新闻学
陈乐天 Letian Chen
爱学习的王一博
更新于 2025-03-08
推荐镜像 :wuda-weibo:20241010
推荐机型 :c2_m4_cpu
赞 2
1
2
微博新闻情感分析
背景介绍
数据格式说明
示例数据
对新闻学的意义
1. 导入数据库
2. 数据预处理
3. 加载数据
词频统计
词云图
词汇关系
4. 加载完整数据
特征提取
5. 模型训练
6. 模型预测与评估
7. 调用模型进行实时预测
正面案例
负面案例

微博新闻情感分析

©️ Copyright 2024 @ Authors
作者:陈乐天 📨
日期:2024-10-10
共享协议:本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
快速开始:你可以点击界面上方蓝色按钮 开始连接 ,选择提供的默认镜像 : `wuda-weibo:20241010 ` ` c2_m4_cpu`节点配置. 稍等片刻即可运行。

背景介绍

随着社交媒体的迅速发展,微博成为了全球范围内获取新闻、表达意见和讨论社会问题的重要平台。微博上的海量内容不仅仅是公众的表达,更是新闻学、社会学等学科的研究对象。通过对微博内容的情感分析,新闻学专业的学生可以深入了解公众对新闻事件、社会问题的看法,甚至能够预测热点话题的传播走向。

情感分析(Sentiment Analysis)是一种自然语言处理技术,旨在判断文本中的情感倾向——正面、负面或中性。在微博这种公开的社交平台上,不同用户会通过评论、转发、点赞等方式参与讨论,对新闻事件、社会问题发表自己的情感看法。通过对这些文本进行情感分析,新闻从业者可以实时掌握公众对事件的态度,从而在报道中调整策略,更好地传递信息。

对新闻学专业的学生而言,情感分析不仅仅是技术手段,更是理解社会情感脉动、提升新闻写作与传播效果的有效工具。

数据格式说明

为了开展微博情感分析,我们通常需要大量的微博数据。这些数据不仅包括文本内容,还需要带有明确的情感标签。以下是微博情感分析数据集的详细格式说明:

  • mid(微博唯一标识符): 每条微博的唯一标签,用于区分不同的微博。通过在网址 https://m.weibo.cn/status/ 后添加 mid,学生可以直接访问该条微博的原始网页内容。举个例子,mid4243222408317689 的微博可以通过访问 此链接 查看。

  • 情感标签(sentiment label): 数据集中的第二列为情感标签。 代表负面情感, 代表正面情感。通过这种标签,学生可以快速识别哪些微博内容反映了用户的负面情绪,哪些则表现出积极的态度。

  • 微博文本: 剩余部分是微博的实际文本内容。为了便于处理,文本中可能包含一些特殊符号。比如:

    • 微博表情:微博中的表情符号被转义为 [xx] 的格式,例如:[doge] 表示狗头表情,[允悲] 表示悲伤表情。这些表情在微博中扮演着丰富情感表达的角色,能够为情感分析提供更多的语境信息。
    • 话题/地理定位/超链接:为了简化文本处理,话题、地理位置和视频链接等内容被替换为 {%xxxx%} 的格式。例如,微博话题会被替换为 {%#话题名称#%},地理位置会被替换为 {%地理位置%}。这些内容通常并不会影响情感分析,学生可以通过简单的正则表达式清理它们。

示例数据

以下是一些数据的示例,帮助学生更直观地理解格式:

4243222408317689,1,{%#极限挑战#%} 温暖依旧,挑战还要继续,希望哥哥们在新的一年里能够用更好的表现迎接每一个惊喜,看哥哥们这次又有了新的“工程师”身份,每个人都是高科技领域的佼佼者,看来这场人工智能烧脑战会异常精彩哦,我们周日“未来”见吧~ ​
4243538441401200,1,{%#关注2018世界制造业大会#%}美菱开发的人工智能自贩柜,相比传统冰箱,延长食材保质期。独立研发的保鲜技术。水分子激活保鲜技术,一般玫瑰花保鲜7天,利用美菱独创的这项技术可让玫瑰花保鲜期长达33天。 ​
4243537615179369,1,说的很好,我觉得这是一个正在改变的时代,是一个局面转变的过渡期,孩子,家务,都不应该成为任何人的牵绊,在未来,也许人工智能可以解决这些问题。
  • 在第一个示例中,mid 为 4243222408317689,情感标签为 1(正面情感),文本内容包括话题 {%#极限挑战#%},以及与“工程师身份”和“人工智能”相关的正面评论。
  • 第二个示例展示了情感标签为 1 的微博,内容涉及“人工智能保鲜技术”。
  • 第三个示例则是针对人工智能对未来社会影响的讨论,标签为正面情感。

对新闻学的意义

通过这些情感标签与文本数据,新闻学学生可以探索公众对不同话题的态度。这些分析不仅可以揭示某个事件的舆论风向,还可以帮助新闻从业者更好地理解受众情绪,提升报道的社会共鸣。借助这些情感分析工具,学生能够探索如下问题:

  • 不同情感的表达如何影响新闻事件的传播?
  • 公众对特定新闻事件的情感变化趋势是什么?
  • 在突发新闻中,哪些情感表达对舆论走向产生了重要影响?

新闻学专业的学生可以通过参与微博情感分析的实践,培养数据分析技能,理解情感与新闻传播之间的复杂关系。这些技能将在未来的新闻报道和数据新闻中发挥重要作用。

下面让我们开始实操吧!

1. 导入数据库

代码
文本
[1]
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
from wordcloud import WordCloud
from sklearn.feature_extraction.text import TfidfVectorizer,CountVectorizer
from sklearn.svm import SVC
from sklearn.metrics import classification_report
import re
import jieba
import networkx as nx
import os
代码
文本

2. 数据预处理

代码
文本

下面,我们先读取一部分文本内容并进行一些词频统计。这里我首先定义了一个用来选择使用数据的函数。

代码
文本
[2]
import os
data.append((weibo_id, label, content))
except ValueError:
print(f"Skipping malformed line in file {selected_file}: {line}")

elif file_index == len(files):
# 用户选择合并所有文件
for file_name in files:
file_path = os.path.join(data_path, file_name)
# 读取每个文件内容
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line: # 确保跳过空行
try:
# 假设每行数据格式为 "微博ID, 标签, 文本内容"
weibo_id, label, content = line.split(',', 2)
# 将数据存储在列表中
data.append((weibo_id, label, content))
except ValueError:
print(f"Skipping malformed line in file {file_name}: {line}")
else:
print("无效的文件编号,请重新运行程序并选择正确的文件。")
return None

# 如果有数据,创建 DataFrame
if data:
# 创建DataFrame并命名列
df = pd.DataFrame(data, columns=['id', 'label', 'content'])
# 显示生成的数据
print(df.head())
# 将数据保存为CSV文件
df.to_csv(output_file, index=False, encoding='utf-8-sig')
print(f"数据已保存为 '{output_file}'")
# 返回生成的 DataFrame
return df
else:
print("没有数据可供处理。")
return None
代码
文本

下面,让我来调用上述函数,并选择想要使用的微博数据吧!

代码
文本
[6]
df = process_weibo_data()
请输入文件编号:
请选择一个文件进行处理,或者选择合并所有文件:
1. 特朗普.txt
2. 同济大学.txt
3. 人工智能.txt
4. 好莱坞.txt
5. 周杰伦.txt
6. 毕业.txt
7. 合并上述所有文件
                 id label                                            content
0  4243222408317689     1  {%#极限挑战#%} 温暖依旧,挑战还要继续,希望哥哥们在新的一年里能够用更好的表现迎接每一...
1  4243538441401200     1  {%#关注2018世界制造业大会#%}美菱开发的人工智能自贩柜,相比传统冰箱,延长食材保质期...
2  4243537615179369     1  说的很好,我觉得这是一个正在改变的时代,是一个局面转变的过渡期,孩子,家务,都不应该成为任何...
3  4243537509450844     1  写光照模型的时候模型头部上面完美着色,下面都糊了 难道本弱鸡的第一个基于头部识别的人工智能算...
4  4243537069987578     1  @上海移动 @中国移动10086 @中国移动 天天给我发升级套餐的推送,我抱怨几句怎么还就预...
数据已保存为 'weibo_dataset.csv'
代码
文本

3. 加载数据

代码
文本

我们知道,原始的文本内容存在很多标点符号、语气词和没有意义的副词等等,因此我们需要对原始的微博内容进行清洗和规范化,使其更适合后续的分析。下面我们将会做的是:

  1. 加载停用词表:停用词表是一组无实际含义的常见词,比如“的”、“在”等,处理时会把这些词忽略掉。

  2. 文本清洗:通过正则表达式,去除微博内容中不需要的部分,比如微博中的话题标签(如 {%xxx%})、用户标签(如 @xxx),以及标点符号等特殊字符,保留纯文本。

  3. 分词和停用词过滤:使用 jieba 分词工具将微博文本切割成单独的词,并去掉停用词,使文本更加简洁。

  4. 否定词处理:对否定词“”进行了特殊处理,将“”和后面的词连在一起,例如“不喜欢”变成一个整体,方便后续分析。

代码如下:

代码
文本
[7]
# 停用词表加载
stopwords = []
with open("./WeiboSentiment/data/stopwords.txt", "r", encoding="utf8") as f:
for w in f:
stopwords.append(w.strip())

# 定义文本处理函数,加入停用词过滤和否定词处理
def processing(text):
"""
数据预处理, 包括去除无效字符、停用词过滤和否定词拼接处理
"""
text = re.sub("\{%.+?%\}", " ", text) # 去除 {%xxx%} (地理定位, 微博话题等)
text = re.sub("@.+?( |$)", " ", text) # 去除 @xxx (用户名)
text = re.sub("【.+?】", " ", text) # 去除 【xx】 (通常不是用户原创内容)
text = re.sub("\u200b", " ", text) # 去除bad case
text = re.sub(r'[^\w\s]', '', text) # 去除标点符号
# 分词并过滤掉停用词
words = [w for w in jieba.lcut(text) if w.isalpha() and w not in stopwords]
# 对否定词 `不` 做特殊处理: 与其后面的词拼接
while "不" in words:
index = words.index("不")
if index == len(words) - 1:
break
words[index: index+2] = ["".join(words[index: index+2])]
result = " ".join(words)
return result
代码
文本

词频统计

词频统计是分析文本数据中各个词汇出现频率的过程。通过统计词汇的频次,我们可以识别出文本中哪些词出现得最多,哪些词的影响力更大。词频统计通常用于社交媒体分析、新闻文本分析等,帮助我们了解公众讨论的重点话题或常用表达。

接下来,我们将对处理过的数据集进行词频统计,并分别展示频率最高的前20前50以及所有词汇的分布图。通过这些图表,我们可以直观地看到高频词汇的分布,进而揭示出文本中的主要讨论内容和舆论走向。

以下是生成词频直方图的代码,它将分别展示不同数量的高频词汇,帮助我们更好地理解文本中的信息分布:

代码
文本
[18]
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import pandas as pd
from collections import Counter
import numpy as np

# 封装画词频直方图的函数
def plot_word_frequency(word_freq, top_n=20, show_all=False, font_path='./static/NotoSerifSC-Black.ttf'):
"""
画词频直方图
:param word_freq: 词频的Counter对象
:param top_n: 显示前 top_n 个高频词
:param show_all: 是否显示所有词汇的频率
:param font_path: 自定义字体路径,确保中文显示正确
"""
# 转换为DataFrame并按频率排序
word_freq_df = pd.DataFrame(word_freq.items(), columns=['word', 'count'])
word_freq_df = word_freq_df.sort_values(by='count', ascending=False)

# 如果显示全部词汇,忽略 top_n 参数,显示所有词汇
if not show_all:
word_freq_df = word_freq_df.head(top_n)

# 生成渐变颜色
colors = plt.cm.rainbow(np.linspace(0, 0.5, len(word_freq_df)))

# 自定义中文字体
my_font = fm.FontProperties(fname=font_path)

# 画词频直方图
plt.figure(figsize=(20, 8))
plt.bar(word_freq_df['word'], word_freq_df['count'], color=colors) # 应用渐变颜色

# 控制词汇显示:如果显示所有词汇且数量较多,隐藏x轴词汇,避免重叠
if show_all or top_n > 50:
plt.xticks([], fontproperties=my_font) # 隐藏x轴词汇标签
else:
plt.xticks(rotation=45, fontproperties=my_font) # 显示x轴词汇并旋转以便查看

# 设置标题和y轴标签
plt.title(f'{"All Words" if show_all else f"Top {top_n} Words"} Frequency', fontproperties=my_font)
plt.ylabel('Frequency', fontproperties=my_font)
plt.show()

# 应用文本处理函数
df['clean_content'] = df['content'].apply(processing)

# 统计词频
all_words = ' '.join(df['clean_content']) # 将所有处理后的微博内容拼接成一个大文本
word_list = all_words.split() # 分词结果已经是空格分隔的单词

# 统计词频
word_counts = Counter(word_list)

# 调用封装好的函数,设置显示前20个高频词
plot_word_frequency(word_counts, top_n=20) # 例如显示前20个词频
代码
文本
已隐藏单元格
已隐藏输出
代码
文本
已隐藏单元格
已隐藏输出
代码
文本

词云图

经过词频统计之后,我们可以利用这些高频词生成词云图。词云图是一种通过词汇的大小、颜色来可视化展示词频的方法。词频越高的词会以更大的字体呈现,频次低的词则会以较小的字体展示。通过词云图,能够直观地看到哪些词汇在文本中出现得最多,便于我们快速识别出讨论的热点话题或高频情感词汇。

在新闻学中,词云图常用于展示舆论分析的结果,帮助读者快速理解社交媒体中的高频词汇,以及某个主题的关键词分布。通过词云图的展示,可以更加直观地展示出微博用户在讨论某个话题时的常用词汇,进而对文本中的情感倾向、关注点等有更好的把握。

接下来,我们将使用之前处理过的微博文本数据生成词云图,并展示词汇的视觉效果。

代码
文本
[21]
# 生成词云图
wordcloud = WordCloud(font_path="./static/NotoSerifSC-Black.ttf", width=800, height=400, background_color='white').generate(all_words)
plt.figure(figsize=(10, 5))
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis('off')
plt.show()
代码
文本

词汇关系

代码
文本
[22]
# 忽略报警信息
import warnings
warnings.filterwarnings("ignore")

# 构建词语共现矩阵
def build_co_occurrence_matrix(texts, keywords, stopwords):
"""
构建词语共现矩阵
:param texts: 文本列表
:param keywords: 高频词关键词列表
:param stopwords: 停用词列表
:return: 共现矩阵
"""
vectorizer = CountVectorizer(tokenizer=jieba.lcut, vocabulary=keywords, stop_words=stopwords, token_pattern=None)
X = vectorizer.fit_transform(texts)
Xc = (X.T * X) # 词语共现矩阵
Xc.setdiag(0) # 去掉对角线(自己与自己共现)
return Xc.toarray()

# 绘制共现网络图
def plot_co_occurrence_network(matrix, keywords):
"""
绘制词汇共现网络图
:param matrix: 共现矩阵
:param keywords: 关键词列表
"""
G = nx.Graph()
# 添加节点和边
for i, word in enumerate(keywords):
for j in range(i + 1, len(keywords)):
if matrix[i, j] > 0: # 如果共现次数大于0,则添加边
G.add_edge(word, keywords[j], weight=matrix[i, j])

# 使用 spring_layout 进行节点布局
pos = nx.spring_layout(G, k=0.5) # 调整 k 值以控制节点之间的距离

# 绘制网络图
plt.figure(figsize=(12, 12))
edges = G.edges(data=True)
edge_weights = [edge[2]['weight'] for edge in edges] # 根据共现次数调整边的粗细

# 绘制节点和标签
nx.draw_networkx_nodes(G, pos, node_size=3000, node_color="lightblue")
nx.draw_networkx_labels(G, pos, font_size=10, font_family="SimHei")
nx.draw_networkx_edges(G, pos, width=[weight/5 for weight in edge_weights], edge_color='gray')

plt.title("Word Co-occurrence Network")
plt.axis("off")
plt.show()

# 提取处理后的文本数据
texts = df['clean_content']

# 获取前 20 个高频词作为关键词
top_keywords = [word for word, _ in word_counts.most_common(20)]

# 构建共现矩阵
co_occurrence_matrix = build_co_occurrence_matrix(texts, top_keywords, stopwords)

# 绘制词汇共现网络
plot_co_occurrence_network(co_occurrence_matrix, top_keywords)

代码
文本

4. 加载完整数据

数据结构以及关系之后,我们现在来加载完整的数据集为后续模型训练做准备。

完整数据中,训练集包含 条数据,测试集包含 条数据

代码
文本
[23]
# 定义加载完整数据集的函数
def load_corpus(path):
"""
加载语料库
"""
data = []
with open(path, "r", encoding="utf8") as f:
for line in f:
[_, sentiment, content] = line.split(",", 2)
content = processing(content)
data.append((content, int(sentiment)))
return data
代码
文本

下面加载完整的训练数据与测试数据,并转换成pandas的DataFrame格式,以便后续模型训练与预测。

代码
文本
[24]
# 加载和预处理数据
data_path = "./WeiboSentiment/data/weibo2018/"
train_data = load_corpus(f"{data_path}train.txt")
test_data = load_corpus(f"{data_path}test.txt")

# 转换成DataFrame
df_train = pd.DataFrame(train_data, columns=['text', 'label'])
df_test = pd.DataFrame(test_data, columns=['text', 'label'])
代码
文本

特征提取

特征提取是机器学习中的一个关键步骤,目的是将原始文本数据转化为模型可以理解的数值形式。在本例中,我们使用了TF-IDF(词频-逆文档频率)方法,将微博中的文本转化为特征向量。

TF-IDF 可以衡量一个词在某一条微博中出现的频率,同时考虑该词在整个数据集中的普遍性,进而降低常见词汇的影响,提升重要词汇的权重。

代码
文本
[25]
# 特征提取
vectorizer = TfidfVectorizer(max_features=10000)
X_train = vectorizer.fit_transform(df_train['text'])
y_train = df_train['label']

X_test = vectorizer.transform(df_test['text'])
y_test = df_test['label']
代码
文本

通过特征提取步骤,模型可以从数值化的文本数据中学到微博的内容结构和情感信息,这为后续的机器学习算法提供了基础输入。

5. 模型训练

在这一部分,我们使用支持向量机SVM)作为分类模型,对微博情感数据进行训练和预测。

SVM 是一种常见的分类算法,它通过寻找最佳的分隔超平面,将数据分成不同的类别。在这里,我们使用了线性核函数,因为它适合处理高维数据并且在文本分类任务中表现良好。

代码
文本
[26]
# 模型训练
svm_model = SVC(kernel='linear')
svm_model.fit(X_train, y_train)
SVC(kernel='linear')
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
代码
文本

6. 模型预测与评估

下面,我们对模型进行了预测与评估,通过测试数据来验证模型的效果。

代码
文本
[27]
# 预测与评估
y_pred = svm_model.predict(X_test)
print(classification_report(y_test, y_pred))
              precision    recall  f1-score   support

           0       0.78      0.68      0.72       155
           1       0.86      0.91      0.89       345

    accuracy                           0.84       500
   macro avg       0.82      0.80      0.81       500
weighted avg       0.84      0.84      0.84       500

代码
文本

7. 调用模型进行实时预测

下面,让我们调用这个模型,自己输入一段话进行情感分类预测吧!

代码
文本
[28]
# 实时预测
def predict_sentiment(input_text):
cleaned_input = processing(input_text)
input_vector = vectorizer.transform([cleaned_input])
prediction = svm_model.predict(input_vector)
return '正面' if prediction[0] == 1 else '负面'
代码
文本

正面案例

这里我们使用武汉大学官方微博中的一条微博内容进行识别,微博原文链接: https://m.weibo.cn/detail/5087703424832598

代码
文本
[15]
# 输入一段文本进行情感分析
input_text = input("请输入一段文本进行情感判断:")
result = predict_sentiment(input_text)
print(f"该段文本的情感分析结果为:{result}")
请输入一段文本进行情感判断:
该段文本的情感分析结果为:正面
代码
文本

负面案例

下面我们看一个负面新闻的例子,微博链接:https://m.weibo.cn/detail/5084744435368968

代码
文本
[16]
# 输入一段文本进行情感分析
input_text = input("请输入一段文本进行情感判断:")
result = predict_sentiment(input_text)
print(f"该段文本的情感分析结果为:{result}")
请输入一段文本进行情感判断:
该段文本的情感分析结果为:负面
代码
文本
python
中文
新闻学
python中文新闻学
已赞2
本文被以下合集收录
文本
微信用户fHLY
更新于 2024-10-24
1 篇0 人关注
情感分析
bohr41da44
更新于 2024-10-18
1 篇0 人关注