基于情感分析与主题分析的微博“双减”政策话题在线评论研究


前言

双减是指有效减轻义务教育阶段学生过重作业负担和校外培训负担。
2021年10月,全国人大表示:双减拟明确入法,避免加重义务教育阶段学生负担。 2021年11月3日,市场监管总局等八部门发布《关于做好校外培训广告管控的通知》。坚决杜绝地铁、公交站台等所属广告牌、广告位刊发校外培训广告。


一、数据来源

选择微博中关于“双减”政策的热门话题,如下图所示在这里插入图片描述

二、数据爬取

代码如下(示例):

# encoding=utf8

import requests
import pandas as pd
import json
import time
import re

# 设置头部和cookie,反爬,伪装
header = {'Content-Type': 'application/json; charset=utf-8',
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36'}
Cookie = {
    'Cookie': ''    #此处放置自己的Cookie
    }


# 评论翻页的关键字段
max_id = ""
# 设置循环
while True:
    # 评论第一页max_id为空值
    if max_id == "":
        url = "https://m.weibo.cn/comments/hotflow?id=4662583791456072&mid=4662583791456072&max_id_type=0"
    else:
        # 显示max_id
        print(max_id)
        # 评论后一页url中的max_id为前一页传递来的参数
        url = "https://m.weibo.cn/comments/hotflow?id=4662583791456072&mid=4662583791456072&max_id=" + str(
            max_id) + "&max_id_type=" + str(max_id_type)
    print("请求的url是:" + url)
    # request对象获取
    response = requests.get(url, headers=header, cookies=Cookie)
    # json格式解析
    comment = response.json()
    print("requestion请求状态:" + str(comment["ok"]))
    # 如果Ok值为1,表示解析成功
    if comment["ok"] == 0:
        break
    # 获取max_id值
    max_id = comment["data"]["max_id"]
    max_id_type = comment["data"]["max_id_type"]
    print("max_id is:" + str(max_id))
    print("max_id_type is:" + str(comment["data"]["max_id_type"]))
    # 获取评论文本,并过滤符号和英文字符
    for comment_data in comment["data"]["data"]:
        data = comment_data["text"]
        p = re.compile(r'(<span.*>.*</span>)*(<a.*>.*</ a>)?')
        data = re.sub('[^\u4e00-\u9fa5]', '', data)
        data = p.sub(r'', data)
        data1 = [(comment_data['created_at'], comment_data['user']['id'], comment_data['user']['screen_name'], data)]
        data2 = pd.DataFrame(data1)
        data2.to_csv('weibo_comment.csv', header=False, index=False, mode='a+')

    # 休眠3秒,防止被系统认为是爬虫
    time.sleep(3)

三、数据清洗

1.清除缺失数据
2.去除重复数据
3.机械压缩去词
4.短句过滤
代码如下(示例):

# coding:utf-8

import pandas as pd
from collections import Counter


data_path = './all.csv'
df = pd.read_csv(data_path, encoding='utf-8')

print('原始数据信息:')
print(len(df))  # 长度
print(type(df))    # 数据类型
# 清除缺少数据
df = df.dropna()  # 消除缺失数据 NaN为缺失数据
print('清除缺失数据后:')
print(len(df))
print(type(df))
print('------------------')
# 清除重复值
df = pd.DataFrame(df.iloc[:, 0].unique())  # 去掉第一列的重复数据;iloc[:, 0]表示索引每一行的第一列;
print('去重数据后:')
print(len(df))
print('------------------')

# 定义机械压缩去词函数
def str_unique(raw_str, reverse=False):
    """
    比如:我喜欢喜欢喜欢喜欢喜欢喜欢该商品;去掉重复的“喜欢”
    :param raw_str:
    :param reverse: 是否转置
    :return:
    """
    if reverse:
        raw_str = raw_str[::-1]
    res_str = ''
    for i in raw_str:
        if i not in res_str:
            res_str += i
    if reverse:
        res_str = res_str[::-1]
    return res_str

ser1 = df.iloc[:, 0].apply(str_unique)	    # 这时,因为索引了第一列,所以结果成了Series;
print('df2', type(ser1))  # <class 'pandas.core.series.Series'>
df2 = pd.DataFrame(ser1.apply(str_unique, reverse=True))	 # 再次生成DataFrame;

print('机械压缩去词后:')
print(len(df2))
print(type(df2))
print('------------------')

# 短句过滤
df3 = df2[df2.iloc[:, 0].apply(len) >= 4]
data1 = pd.DataFrame(df3)
data1.to_csv("sentence.csv", header=False, index=False, mode="a+")
print('短句过滤后:')
print(len(df3))
print('------------------')

输出结果:在这里插入图片描述


四、基于BosonNLP词典的情感分析

运用BosonNLP词典对评论内容进行情感分析,计算出的情感表示语义积极或消极的概率,计算出的情感score表示语义积极或消极的概率。
如果总分值>0,表示情感倾向为积极
如果总分值<=0,表示情感倾向为消极
情感分析流程:
在这里插入图片描述

代码如下(示例):

# -*- coding:utf-8 -*-
import pandas as pd
import jieba

# 基于波森情感词典计算情感值
def getscore(text):
    df = pd.read_table(r"./BosonNLP_sentiment_score.txt", sep=" ", names=['key', 'score'])
    key = df['key'].values.tolist()
    score = df['score'].values.tolist()
    # jieba分词
    segs = jieba.lcut(text, cut_all = False)  # 返回list
    # 计算得分
    score_list = [score[key.index(x)] for x in segs if(x in key)]
    return sum(score_list)

#读取文件z
def read_txt(filename):
    with open(filename,'r',encoding='utf-8')as f:
        txt = f.read()
    return txt
#写入文件
def write_data(filename,data):
    with open(filename,'a',encoding='utf-8')as f:
        f.write(data)


if __name__=='__main__':
    text = read_txt('./清洗后评论.txt')
    lists  = text.split('\n')

    # al_senti = ['无','积极','消极','消极','中性','消极','积极','消极','积极','积极','积极',
    #             '无','积极','积极','中性','积极','消极','积极','消极','积极','消极','积极',
    #             '无','中性','消极','中性','消极','积极','消极','消极','消极','消极','积极'
    #             ]

    i = 0
    for list in lists:
        if list  != '':
            # print(list)
            sentiments = round(getscore(list),2)
            #情感值为正数,表示积极;为负数表示消极
            print(list)
            print("情感值:",sentiments)

            if sentiments > 0:
                print("机器标注情感倾向:积极\n")
                s = "积极"
            else:
                print('机器标注情感倾向:消极\n')
                s = "消极"
            sentiment = '情感值:'+str(sentiments)+'\n'

            #文件写入
            filename = './BosonNLP情感分析结果.txt'

            write_data(filename,s+'\n') 
            i = i+1


输出结果:在这里插入图片描述

4.1 整体倾向

代码如下(示例):
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

data_path = './comment.csv'
df = pd.read_csv(data_path, encoding='utf-8')

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置加载的字体名

plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

plt.figure(figsize=(12, 6))  # 设置画布大小

rate = df['score']

ax = sns.distplot(rate,

            hist_kws={'color': 'green', 'label': '直方图'},

            kde_kws={'color': 'red', 'label': '密度曲线'},

            bins=20)  # 参数color样式为salmon,bins参数设定数据片段的数量

ax.set_title("'双减'整体情感倾向")

plt.show()


输出结果:在这里插入图片描述

4.2 积极/消极情绪词云图

代码如下(示例):
import jieba
import collections
import re
from wordcloud import WordCloud
import matplotlib.pyplot as plt



with open(r'C:\Users\admin\pythonProject\微博评论\c.txt', encoding="utf-8") as f:
    data = f.read()

# 文本预处理  去除一些无用的字符   只提取出中文出来
new_data = re.findall('[\u4e00-\u9fa5]+', data, re.S)
new_data = " ".join(new_data)

# 文本分词
seg_list_exact = jieba.cut(new_data, cut_all=True)

result_list = []
with open(r'C:\Users\admin\pythonProject\停用词.txt', encoding='utf-8') as f:
    con = f.readlines()
    stop_words = set()
    for i in con:
        i = i.replace("\n", "")   # 去掉读取每一行数据的\n
        stop_words.add(i)

for word in seg_list_exact:
    # 设置停用词并去除单个词
    if word not in stop_words and len(word) > 1:
        result_list.append(word)
print(result_list)

# 筛选后统计
word_counts = collections.Counter(result_list)
# 获取前100最高频的词
word_counts_top100 = word_counts.most_common(100)
print(word_counts_top100)

# 绘制词云
my_cloud = WordCloud(
    background_color='white',  # 设置背景颜色  默认是black
    width=900, height=600,
    max_words=100,            # 词云显示的最大词语数量
    font_path='simhei.ttf',   # 设置字体  显示中文
    max_font_size=99,         # 设置字体最大值
    min_font_size=16,         # 设置子图最小值
    random_state=50           # 设置随机生成状态,即多少种配色方案
).generate_from_frequencies(word_counts)

# 显示生成的词云图片
plt.imshow(my_cloud, interpolation='bilinear')
# 显示设置词云图中无坐标轴
plt.axis('off')
plt.show()


输出结果:
在这里插入图片描述

4.3 情感语义网络图

利用ROST CM软件进行情感语义网络分析,进一步挖掘。
软件界面(示例):
在这里插入图片描述

该软件的使用可参考:https://blog.csdn.net/qq_42374697/article/details/113091809
输出结果:在这里插入图片描述

五、主题分析

主题模型是假设每个文档由多个主题混合而成,而每个主题都是词上的概率分布(即每个词对主题的贡献度),这样文档、词都可以映射到同一个潜在语义空间——主题。代码如下(示例):

# encoding=utf-8
import pyLDAvis.gensim_models
import jieba.posseg as jp,jieba
from gensim.models.coherencemodel import CoherenceModel
from gensim.models.ldamodel import LdaModel
from gensim.corpora.dictionary import Dictionary

# 读取需要处理的文本
doc1=open(r'C:\Users\admin\pythonProject\微博评论\清洗后评论.txt','rb').read()


# 构建文本集
texts = [doc1]
# 词性标注条件
flags = ('n', 'nr', 'ns', 'nt', 'eng', 'v', 'd','vn','vd')
# 停用词表
stopwords = open(r'C:\Users\admin\pythonProject\微博评论\停用词.txt',"r",encoding='utf-8').read()

# 分词
words_ls = []
for text in texts:
    # 采用jieba进行分词
    words = [word.word for word in jp.cut(text) if word.flag in flags and word.word not in stopwords]
    words_ls.append(words)

# 构造词典
dictionary = Dictionary(words_ls)
corpus = [dictionary.doc2bow(words) for words in words_ls]
# lda模型,num_topics设置主题的个数
lda = LdaModel(corpus=corpus, id2word=dictionary, num_topics=3, random_state=100, iterations=50)
# U_Mass Coherence
ldaCM = CoherenceModel(model=lda, corpus=corpus, dictionary=dictionary, coherence='u_mass')

# 打印所有主题,每个主题显示10个词
for topic in lda.print_topics(num_words=10):
    print(topic)

# 用pyLDAvis将LDA模式可视化
plot =pyLDAvis.gensim_models.prepare(lda, corpus, dictionary)
# 保存到本地html
pyLDAvis.save_html(plot, './pyLDAvis.html')


输出结果:
在这里插入图片描述
在这里插入图片描述

总结

本文使用python爬虫对微博双减话题进行爬取,利用BonsonNLP情感词典对采集到的文本进行情感分析,并用词云图和情感语义图进行进一步分析,最后使用主题分析进行进一步挖掘。

  • 13
    点赞
  • 136
    收藏
    觉得还不错? 一键收藏
  • 37
    评论
# emotionAnalysis 疫情背景下,基于情感词典和机器学习对新闻和微博评论情感分析 # Data Science Basics in SWI, NJU, 2020-Fall > ## 计算社会学:基于NLP技术的新冠疫情下的社会心态研究 Cong Jin , YDJSIR, Sugar Xu‘s project of 2020 Data Science Basic Course in SWI, NJU. 此为发布开源的版本而不是开发环境使用的版本。 ## 文件结构 ```bash │ LICENSE │ README.md ├─Analyze # 分析数据的过程所使用的所有代码 ├─Data # 原始数据以及处理过后的所有数据 ├─Report # 报告相关源文件以及最终报告的成品 └─Spyder # 爬虫代码 ``` 文件结构经过事后整理,并不是工作时目录的状态,因而代码所涉及的路径需要稍加修改后运行。 原始报告数据在评分后抹掉相关关键词后后放出。 > ### `Data`目录下文件结构 > > 该目录下共有6个文件夹,分别对应`stage0` - `stage6` > > ##### stage内文件目录结构 > > ```bash > │ COVkeywords-Stage-.json # 人工筛选后的疫情相关关键词 > │ COVkeywords-Stage.json # 未经筛选的疫情关键词 > │ keywords-Stage.json # 从荔枝新闻获取的原始结果 > │ ratioByDate.png # 该阶段内每日疫情相关重点微博占比 > │ SaveTest.png # 疫情相关度分布拟合结果1 > │ SaveTest_Fit.png # 疫情相关度分布拟合结果2 > │ stageCOVWeibo.json # 该阶段内疫情相关重点微博(按时间先后排序) > │ stageCOVWeiboByImportance.json # 该阶段内疫情相关重点微博(按疫情相关度排序) > | SaveTest-热度.png # 各项热度指标占比 > │ stageInfo.json # 该阶段基础信息 > │ weiboPolar.png # 疫情相关重点微博情感极性 > | weiboEmotion.png # 当前阶段的疫情相关微博情感倾向 > ├─YYYY-MM-DD- > ├─YYYY-MM-DD- > ├─YYYY-MM-DD- > ├─YYYY-MM-DD- > ... > └─YYYY-MM-DD- > ``` > > ##### 每个日期内文件目录结构 > > ```bash > YYYY-MM-DD > | jstvRAW.csv # 疫情相关关键词检索得到的荔枝新闻原始数据 > | keywords.json # 荔枝新闻正文提取出来的关键词及其乘以100以后的TextRank权值 > | wordcloud.html # 由荔枝新闻生成的词云 > | blog-Scored.json # 每篇微博都有一个疫情相关度 > | blog-COV.json # 筛选后的新冠疫情相关微博 > | blogInfo.json # 当日博客相关基础信息 > | weiboEmotion.png # 基于心态词典的当日疫情相关微博重点评论情感分析生成的雷达 > └─weiboEmotion.csv # 基于心态词典的当日疫情相关微博重点评论情感分析原始数据 > ``` ======= # emotionAnalysis 疫情背景下,基于情感词典和机器学习对新闻和微博评论情感分析
以下是基于情感词典与机器学习对微博新闻评论情感分析Python 代码示例: 首先,需要下载情感词典并加载到程序,比如使用文情感词典“知网情感词语极值表”。 ```python import jieba # 加载情感词典 posdict = [] negdict = [] with open("posdict.txt", "r", encoding="utf-8") as f: for line in f: posdict.append(line.strip()) with open("negdict.txt", "r", encoding="utf-8") as f: for line in f: negdict.append(line.strip()) # 对文本进行分词 def seg_text(text): seg_list = jieba.cut(text) return " ".join(seg_list) # 计算文本情感分数 def get_sentiment_score(text): seg_list = seg_text(text).split() pos_count = len(set(seg_list) & set(posdict)) neg_count = len(set(seg_list) & set(negdict)) score = (pos_count - neg_count) / len(seg_list) return score ``` 接下来,可以使用机器学习算法对微博新闻评论进行情感分析。这里以朴素贝叶斯算法为例: ```python import pandas as pd from sklearn.feature_extraction.text import CountVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.metrics import accuracy_score # 加载数据集 data = pd.read_csv("weibo_comments.csv") # 分割训练集和测试集 train_data = data.sample(frac=0.8, random_state=1) test_data = data.drop(train_data.index) # 对文本进行分词和向量化 vectorizer = CountVectorizer(token_pattern=r'\b\w+\b') X_train = vectorizer.fit_transform(train_data["评论"].apply(seg_text)) y_train = train_data["情感"] # 训练朴素贝叶斯模型 clf = MultinomialNB() clf.fit(X_train, y_train) # 对测试集进行情感分析并评估模型性能 X_test = vectorizer.transform(test_data["评论"].apply(seg_text)) y_test = test_data["情感"] y_pred = clf.predict(X_test) accuracy = accuracy_score(y_test, y_pred) print("Accuracy:", accuracy) ``` 需要注意的是,以上代码仅仅是一个示例,实际应用时需要根据具体情况进行适当调整,比如增加特征选择、模型调参等步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值