最近在做用户反馈,需要分析B站某视频下的评论。由于用户评论数量庞大,因此使用Python爬取评论,并进行简单的分析处理。本文介绍此过程中使用的方法,基本思路为:
- 爬取评论数据保存到CSV文件
- 对爬取的评论进行情感分析
- 对评论数据进行可视化分析
一、获取评论
根据视频链接解析oid参数,将爬取的数据保存到CSV文件中。
爬取信息包括:用户姓名、性别、IP属地、评论内容、点赞数量、评论数量。
# 参考来源:https://www.bilibili.com/video/BV1K9Hse8EwM/?share_source=copy_web&vd_source=d4744805a3e716c7d611be8c989392d9
import csv
import hashlib
import time
from datetime import datetime
import requests
from urllib.parse import quote
import json
import re
# 构造函数,解析w_rid加密参数
def GetSign(data_time, next_page, oid):
pagination_str = '{"offset":%s}' % next_page
print(pagination_str)
l = [
"mode=3",
f"oid={oid}",
f"pagination_str={quote(pagination_str)}",
"plat=1",
"type=1",
"web_location=1315875",
f"wts={data_time}"
]
y = '&'.join(l)
string = y + 'ea1db124af3c7062474693fa704f4ff8'
MD5 = hashlib.md5()
MD5.update(string.encode('utf-8'))
w_rid = MD5.hexdigest()
print(w_rid)
return w_rid
# 构造获取B站评论内容函数
def GetInfo(next_page, oid, csv_writer):
# url构造
url = "https://api.bilibili.com/x/v2/reply/wbi/main"
data_time = int(time.time())
w_rid = GetSign(data_time, next_page, oid)
data = {
'oid': oid,
'type': '1',
'mode': '3',
'pagination_str': '{"offset":%s}' % next_page,
'plat': '1',
'web_location': '1315875',
'w_rid': w_rid,
'wts': data_time
}
response = requests.get(url=url, params=data, headers=headers)
json_data = response.json()
replies = json_data['data']['replies']
for index in replies:
comment_time = datetime.fromtimestamp(index['ctime']).strftime('%Y-%m-%d %H:%M:%S')
dit = {
'昵称': index['member']['uname'],
'性别': index['member']['sex'],
'地区': index['reply_control'].get('location', '').replace('IP属地:', ''), #一些较早视频没有地区信息,如果没有地区信息返回空值
'评论': index['content']['message'],
'点赞数': index['like'],
'评论数': index['reply_control'].get('sub_reply_title_text', '0').replace('相关回复共', ''),
'评论时间': comment_time
}
csv_writer.writerow(dit)
print(dit)
# 检查是否有二级评论
if 'replies' in index and index['replies'] is not None:
for sub_reply in index['replies']:
sub_comment_time = datetime.fromtimestamp(sub_reply['ctime']).strftime('%Y-%m-%d %H:%M:%S')
sub_dit = {
'昵称': sub_reply['member']['uname'],
'性别': sub_reply['member']['sex'],
'地区': sub_reply['reply_control'].get('location', '').replace('IP属地:', ''),
'评论': sub_reply['content']['message'],
'点赞数': sub_reply['like'],
'评论数': '0', # 二级评论下无其他评论,则值设为0
'评论时间': sub_comment_time
}
csv_writer.writerow(sub_dit)
print(sub_dit)
next_page = json_data['data']['cursor']['pagination_reply']['next_offset']
next_offset = json.dumps(next_page)
print(next_offset)
return next_offset
# 构造函数,通过视频链接获取oid
def get_oid(author_url):
rsp = requests.get(author_url, headers=headers)
oid = re.findall(r'"aid":(\d+),', rsp.text)[0]
print('成功获取oid:',oid)
return oid
if __name__ == '__main__':
headers = {
"cookie": "", #输入cookie,否则无法获取完整评论
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
}
# 输入视频链接和文件名
author_url = input("请输入视频链接: ")
oid = get_oid(author_url)
filename = input("请输入要保存的文件名: ") + '.csv'
# 创建文件对象
with open(file=filename, mode='w', encoding='utf-8-sig', newline='') as f:
csv_writer = csv.DictWriter(f, fieldnames=['昵称', '性别', '地区', '评论','点赞数','评论数','评论时间'])
csv_writer.writeheader()
next_page = '""'
for page in range(1, 100):# 可以根据需要修改爬取范围
next_page = GetInfo(next_page, oid, csv_writer)
此爬虫代码仅能爬取一级评论和展开的二级评论,无法爬取到分页的二级评论,因此爬取数量会比实际数量少。
二、情感分析
为了快速筛选出CSV文件中含有负面情感的示例,考虑使用NLP或大语言模型进行情感分析。
使用SnowNLP分析评论情感:
SnowNLP是一个基于 Python 的自然语言处理工具包,它提供了文本情感分析、关键词提取、文本分类等功能。该工具包具有简单易用的接口,可帮助用户快速实现文本处理和情感分析任务。
# 参考来源:https://mp.weixin.qq.com/s/NqSmswl8Cad1MCWWwQj3gQ
from snownlp import SnowNLP
import pandas as pd
def sentiment_analysis(text):
"""
使用SnowNLP进行中文文本情感分析。
:param text: 中文文本字符串。
:return: 情感分析结果,包括情感倾向(正面情感、负面情感)和情感值。
"""
# 创建SnowNLP对象
snlp = SnowNLP(text)
# 获取情感倾向和情感值
sentiment = snlp.sentiments
# 根据情感值判断情感倾向
if sentiment > 0.5:
sentiment_polarity = '正面情感'
else:
sentiment_polarity = '负面情感'
return sentiment_polarity, sentiment
# 读取CSV文件
df = pd.read_csv(r'./xuangu.csv') # 修改此处
# 获取评论列的值
comments = df['评论'].values
# 初始化情感倾向列表和情感值列表
inclinations = [] # 情感倾向列表
values = [] # 情感值列表
# 遍历评论进行情感分析
for comment in comments:
sentiment_polarity, sentiment_score = sentiment_analysis(comment)
inclinations.append(sentiment_polarity)
values.append(sentiment_score)
print(f"情感倾向: {sentiment_polarity}, 情感值: {sentiment_score}")
# 打印情感倾向列表查看结果
print(inclinations)
# 将分析结果添加到DataFrame
df['情感倾向'] = inclinations
df['情感值'] = values
# 将更新后的DataFrame保存到新的CSV文件
df.to_csv('./xuangu_snetiments_analysis.csv', index=False, encoding='utf-8-sig')
使用Zhipu分析评论情感:
智普AI大模型开放平台提供免费API供用户调用,可前往申请:https://open.bigmodel.cn/
import pandas as pd
import time # 导入time模块用于调用sleep函数
from zhipuai import ZhipuAI
def analyze_comment_sentiment(comment):
"""
分析用户评论的情感倾向。
参数:
- comment: str, 用户的评论内容
返回:
- str, 评论的情感倾向(正向、中性、负向)
"""
# 初始化ZhipuAI客户端
client = ZhipuAI(api_key="") # 请填写您自己的APIKey
# 发送请求进行情感分析
response = client.chat.completions.create(
model="GLM-4-Flash", # 模型名称,可根据实际情况选择,模型列表见https://bigmodel.cn/dev/howuse/model
messages=[
{"role": "system",
"content": "#Role:用户评论情感分析专家"
"## Goals:理解用户评论的情感态度,判断情感态度"
"## Output_format:正向、中性、负向"
"## Constrains:不要解释原因,直输出结论"
},
{"role": "user",
"content": comment}, # 使用函数参数
],
)
# 返回分析结果
return response.choices[0].message.content
# 读取CSV文件
df = pd.read_csv(r'./xuangu.csv') # 读取保存评论的文档
# 获取评论列的值
comments = df['评论'].values
# 初始化情感倾向列表
inclinations = []
# 遍历评论进行情感分析
for comment in comments:
sentiment = analyze_comment_sentiment(comment)
inclinations.append(sentiment)
print(f"评论: {comment}, 情感倾向: {sentiment}")
time.sleep(3) # 每次调用后等待3秒,可根据实际情况更改数值
# 将分析结果添加到DataFrame
df['情感倾向'] = inclinations
# 将更新后的DataFrame保存到新的CSV文件
df.to_csv('./xuangu_zhipu_sentiments_analysis.csv', index=False, encoding='utf-8-sig')
三、数据可视化
飞书多维表格
飞书多维表格提供丰富的数据图标模板,将生成的CSV文件上传至飞书云文档多维表格,然后利用仪表盘生成数据表。
Pyecharts
此外,还可以使用PyeCharts进行数据可视化。
PyeCharts是一个开源可视化工具,提供丰富的图标组件
示例代码:https://gallery.pyecharts.org/#/Map/china_gdp_from_1993_to_2018
import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Map
# 读取CSV文件
df = pd.read_csv('wuxia.csv') # 确保文件路径正确
# 创建一个映射,将常见的省份和直辖市名称映射到pyecharts能识别的名称
name_mapping = {
'北京': '北京市', '天津': '天津市', '上海': '上海市', '重庆': '重庆市',
'河北': '河北省', '山西': '山西省', '辽宁': '辽宁省', '吉林': '吉林省',
'黑龙江': '黑龙江省', '江苏': '江苏省', '浙江': '浙江省', '安徽': '安徽省',
'福建': '福建省', '江西': '江西省', '山东': '山东省', '河南': '河南省',
'湖北': '湖北省', '湖南': '湖南省', '广东': '广东省', '海南': '海南省',
'四川': '四川省', '贵州': '贵州省', '云南': '云南省', '陕西': '陕西省',
'甘肃': '甘肃省', '青海': '青海省', '台湾': '台湾省',
'内蒙古': '内蒙古自治区', '广西': '广西壮族自治区', '西藏': '西藏自治区',
'宁夏': '宁夏回族自治区', '新疆': '新疆维吾尔自治区',
'香港': '香港特别行政区', '澳门': '澳门特别行政区'
}
# 使用映射更新地区名称
df['地区'] = df['地区'].map(name_mapping)
# 计算每个地区的数量
region_counts = df['地区'].value_counts().reset_index()
region_counts.columns = ['地区', '数量']
print(region_counts)
# 准备数据
data = [list(z) for z in zip(region_counts['地区'], region_counts['数量'])]
# 创建地图
c = (
Map()
.add("", data, "china")
.set_global_opts(
title_opts=opts.TitleOpts(title="用户来源"),
visualmap_opts=opts.VisualMapOpts(max_=100),# 根据图表数据修改取值范围
)
.render("map_visualmap_piecewise.html")
)
Wordcloud库
使用python的jieba和wordcloud库可以生成词云图,代码如下:
# 导入必要的库
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import jieba
import pandas as pd
# 读取停用词
with open("stopwords_cn.txt", "r", encoding="utf-8") as f:
stopwords = set([line.strip() for line in f.readlines()])
# 读取csv文件
df = pd.read_csv("wuxia.csv", encoding="utf-8")
comments = df["评论"].tolist()
# 将评论列的内容合并为一个字符串
s = " ".join(comments)
# 中文分词
text = ' '.join(jieba.cut(s))
# 生成词云对象
wc = WordCloud(font_path="msyh.ttc", # 字体路径,确保路径正确
background_color='white',
max_words=200,
width=1920,
height=1080,
stopwords=stopwords).generate(text)
# 使用Matplotlib显示词云
plt.imshow(wc, interpolation='bilinear')
plt.axis("off")
plt.show()
# 保存到文件
wc.to_file("wuxia_comments_wordcloud.png")
附词云停用词表:
主要参考来源:
- 【Python爬虫可视化:采集分析各大平台用户评论数据(B站、抖音、京东、天猫、网易云、微博、知乎)】 https://www.bilibili.com/video/BV1K9Hse8EwM/?share_source=copy_web&vd_source=d4744805a3e716c7d611be8c989392d9
- python例子:对评论内容进行情感分析,https://mp.weixin.qq.com/s/NqSmswl8Cad1MCWWwQj3gQ
评论 (0)