自学内容网 自学内容网

IPhone16评论自然语言处理

最近看到了一个自然语言处理的项目,发现自己也没怎么写过这方面的文章,所以上周写了一篇,上周忘记发了,这周才发。

 这是两个数据集的概况

最近看到了一个IPhone评论数据的自然语言处理的项目,就想到了在GitHub上的一个开源的处理中文文本的模型HanLP,这是他的地址https://github.com/hankcs/HanLP
大家可以去学习一下,Jieba是基于传统的词典匹配和HMM,而HanLP2.x版本是基于深度学习,对于分词的处理可能更加精确

一.准备工作

!pip install snownlp -i https://pypi.tuna.tsinghua.edu.cn/simple/
!pip install wordcloud -i https://pypi.tuna.tsinghua.edu.cn/simple/
!pip install hanlp[full] -i https://pypi.tuna.tsinghua.edu.cn/simple/

先下载需要用到的分词,情感分析,词云图的第三方库

import hanlp
import pandas as pd
import numpy as np
from snownlp import SnowNLP
from wordcloud import WordCloud

 导入包

df1 = pd.read_excel("D:/每周挑战/B站视频-何同学_241020_1729431535.xlsx")
df2 = pd.read_excel("D:/每周挑战/B站视频-影视飓风_241020_1729431473.xlsx")

pd.set_option("display.max_columns",1000)
pd.set_option("display.max_rows",1000)

读取数据,并解除行和列的限制

df1.info()
///
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6310 entries, 0 to 6309
Data columns (total 14 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   oid     6310 non-null   int64  
 1   rpid    6310 non-null   int64  
 2   rrpid   1290 non-null   float64
 3   评论层级    6310 non-null   object 
 4   用户昵称    6310 non-null   object 
 5   评论内容    6310 non-null   object 
 6   评论时间    6310 non-null   object 
 7   被回复用户   1290 non-null   object 
 8   性别      6310 non-null   object 
 9   用户当前等级  6310 non-null   int64  
 10  点赞数     6310 non-null   int64  
 11  回复数     6310 non-null   int64  
 12  视频标题    6310 non-null   object 
 13  视频链接    6310 non-null   object 
dtypes: float64(1), int64(5), object(8)
memory usage: 690.3+ KB
///
df2.info()
///
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 9128 entries, 0 to 9127
Data columns (total 14 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   oid     9128 non-null   int64  
 1   rpid    9128 non-null   int64  
 2   rrpid   4321 non-null   float64
 3   评论层级    9128 non-null   object 
 4   用户昵称    9128 non-null   object 
 5   评论内容    9128 non-null   object 
 6   评论时间    9128 non-null   object 
 7   被回复用户   4321 non-null   object 
 8   性别      9128 non-null   object 
 9   用户当前等级  9128 non-null   int64  
 10  点赞数     9128 non-null   int64  
 11  回复数     9128 non-null   int64  
 12  视频标题    9128 non-null   object 
 13  视频链接    9128 non-null   object 
dtypes: float64(1), int64(5), object(8)
memory usage: 998.5+ KB
///

 从这里看出,数据集里缺失数据还是有的,rrpid是被回复用户的唯一标识,因为我们主要是做文本分析的,id对我们来说没用,因此,我们就不管了

data1 = df1[['用户昵称', '评论内容', '评论时间', '性别', '用户当前等级', '点赞数', '回复数']]
data2 = df2[['用户昵称', '评论内容', '评论时间', '性别', '用户当前等级', '点赞数', '回复数']]

 提取出我们用到的数据

二.数据可视化

import matplotlib.pyplot as plt

plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['SimHei']

plt.figure(figsize=(12,10))

# 点赞数箱线图
plt.subplot(2, 1, 1)
plt.boxplot(data1['点赞数'])
plt.title('何同学 - 点赞数箱线图')
plt.ylabel('点赞数')
plt.grid(True)
# 回复数箱线图
plt.subplot(2, 1, 2)
plt.boxplot(data1['回复数'])
plt.title('何同学 - 回复数箱线图')
plt.ylabel('回复数')
plt.grid(True)

plt.tight_layout()
plt.show()

 

plt.figure(figsize=(12,10))

# 点赞数箱线图
plt.subplot(2, 1, 1)
plt.boxplot(data2['点赞数'])
plt.title('影视飓风 - 点赞数箱线图')
plt.ylabel('点赞数')
plt.grid(True)
# 回复数箱线图
plt.subplot(2, 1, 2)
plt.boxplot(data2['回复数'])
plt.title('影视飓风 - 回复数箱线图')
plt.ylabel('回复数')
plt.grid(True)

plt.tight_layout()
ply.show()

print("何同学视频点赞数最高的10条评论:")
data1.nlargest(10, '点赞数')[['用户昵称','用户当前等级', '评论内容', '点赞数', '回复数']]

print("影视飓风视频点赞数最高的10条评论:")
data2.nlargest(10, '点赞数')[['用户昵称','用户当前等级', '评论内容', '点赞数', '回复数']]

 

plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.scatter(data1['用户当前等级'], data1['点赞数'], color='blue', alpha=0.5)
plt.title('何同学 - 用户等级与点赞数的关系')
plt.xlabel('用户当前等级')
plt.ylabel('点赞数')

plt.subplot(1, 2, 2)
plt.scatter(data1['用户当前等级'], data1['回复数'], color='green', alpha=0.5)
plt.title('何同学 - 用户等级与回复数的关系')
plt.xlabel('用户当前等级')
plt.ylabel('回复数')

plt.tight_layout()
plt.show()

plt.figure(figsize=(12, 6))

plt.subplot(1, 2, 1)
plt.scatter(data2['用户当前等级'], data2['点赞数'], color='blue', alpha=0.5)
plt.title('影视飓风 - 用户等级与点赞数的关系')
plt.xlabel('用户当前等级')
plt.ylabel('点赞数')

plt.subplot(1, 2, 2)
plt.scatter(data2['用户当前等级'], data2['回复数'], color='green', alpha=0.5)
plt.title('影视飓风 - 用户等级与回复数的关系')
plt.xlabel('用户当前等级')
plt.ylabel('回复数')

plt.tight_layout()
plt.show()

 

import re
def clean_text(text):
    """
    文本预处理:只删除表情符号和emoji,保留所有文字内容
    """
    if not isinstance(text, str):
        return ''
    
    # 1. 去除[xxx]格式的表情
    cleaned_text = re.sub(r'\[.*?\]', '', text)
    
    # 2. 去除emoji表情
    cleaned_text = re.sub(r'[\U00010000-\U0010ffff]', '', cleaned_text)
    
    # 3. 去除多余空格
    cleaned_text = ' '.join(cleaned_text.split())
    
    return cleaned_text.strip()



data1['清洗评论'] = data1['评论内容'].apply(clean_text)
data2['清洗评论'] = data2['评论内容'].apply(clean_text)


# 加载分词模型
tokenizer = hanlp.load(hanlp.pretrained.tok.COARSE_ELECTRA_SMALL_ZH)


# 加载停用词表
with open('E:/ChromeDownloads/baidu_stopwords.txt', 'r', encoding='utf-8') as f:
    stopwords = set(line.strip() for line in f)

# def participle(texts):
#     # 批量分词并过滤停用词
#     word_lists = tokenizer(texts)
#     result = [[word for word in words if word not in stopwords] for words in word_lists]
#     return result
product_words = {'苹果', '手机', 'iphone', '华为', '三星', '何同学', '影视飓风', '回复'}
all_stopwords = stopwords.union(product_words)


def participle(text):
    # 对每条评论分词并过滤停用词
    words = tokenizer(text)
    filtered_words = [word for word in words if word not in all_stopwords]
    return ''.join(filtered_words)


data1['分词结果'] = data1['清洗评论'].apply(participle)
data2['分词结果'] = data2['清洗评论'].apply(participle)

 对评论内容进行处理后在进行分词

def get_sentiment(text):
    """
    情感分析函数,包含错误处理
    """
    try:
        # 如果文本为空或者只包含空格
        if not text or text.isspace():
            return 0.5  # 返回中性分数
        return SnowNLP(text).sentiments
    except:
        return 0.5  # 出错时返回中性分数



data1['情感分数'] = data1['清洗评论'].apply(get_sentiment)
data2['情感分数'] = data2['清洗评论'].apply(get_sentiment)

对评论内容进行情感分析

plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.hist(data1['情感分数'], bins=50, color='blue', alpha=0.6)
plt.title('何同学 - 评论情感分布')
plt.xlabel('情感分数(0=消极,1=积极)')
plt.ylabel('评论数量')
plt.grid(True, alpha=0.3)

# 影视飓风评论情感分布
plt.subplot(1, 2, 2)
plt.hist(data2['情感分数'], bins=50, color='green', alpha=0.6)
plt.title('影视飓风 - 评论情感分布')
plt.xlabel('情感分数(0=消极,1=积极)')
plt.ylabel('评论数量')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

 

def generate_wordcloud(data, title, word_cloud_type):
    # 根据情感分数过滤数据并将分词结果拼接成字符串
    if word_cloud_type == '积极':
        text = ' '.join([' '.join(words) for words in data[data['情感分数'] > 0.8]['分词结果']])
    else:
        text = ' '.join([' '.join(words) for words in data[data['情感分数'] < 0.2]['分词结果']])

    plt.figure(figsize=(15, 10))
    wordcloud = WordCloud(
        font_path='E:/ChromeDownloads/SIMHEI.ttf',
        width=800,
        height=400,
        background_color='white',
        max_words=100,
    ).generate(text)

    plt.imshow(wordcloud, interpolation='bilinear')
    plt.title(title)
    plt.axis('off')

 绘制词云图

generate_wordcloud(data1, '何同学 - 积极评论词云', '积极')
generate_wordcloud(data1, '何同学 - 消极评论词云', '消极')
generate_wordcloud(data2, '影视飓风 - 积极评论词云', '积极')
generate_wordcloud(data2, '影视飓风 - 消极评论词云', '消极')

 


原文地址:https://blog.csdn.net/qq_60688380/article/details/143485028

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!