通过python爬虫,对京东蜂花洗发水的用户品论进行分析。
1、数据采集
1.1数据来源
数据来源主要来自线上购物平台京东关于蜂花洗发水的评论数据,其中选取了购买率最高和评论数据较为全面的蜂花最早推出的洗发水共2971条数据,主要采集了评论内容、发布时间、用户名、用户地区和用户评分。
2.数据爬取
利用Python爬虫代码进行数据的爬取,因为可以较快获取大量的评论数据并且能在一定程度上保证数据的真实性和完整性,有助于后面的数据分析。
2.1 流程图
2.2 数据爬虫具体步骤
首先,通过导导入所需要的数据库、requests和pandas,然后在循环中爬取200页数据。
#导入第三方库,requests是一个常用的HTTP库,用于发送HTTP请求和处理响应。
import requests
import pandas as pd
#定义空列表
items=[]
#for循环
for i in range(1,200):
获取header及url的步骤如下(headers表示模拟浏览器发送请求,Url表示这个接口的请求地址):首先进入京东平台的页面,点击搜索框输入蜂花洗发水,点击进入,选择购买率最高评论数据较为全面的蜂花洗发水,点击进入商品详情页面,进入商品详情页面的同时点击鼠标右键选择检查。
选择网络,刷新整个网页,刷新出数据包。此时再点击京东商品页面的详情页看更新的数据包,一般即为携带评论数据的数据包。
选择标头,获取获取header及url
header = {'User-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36 SLBrowser/8.0.1.4031 SLBChan/105'}
#定义爬虫地址
url=f'https://api.m.jd.com/?appid=item-v3&functionId=pc_club_productPageComments&client=pc&clientVersion=1.0.0&t=1696341744412&loginType=3&uuid=122270672.16943527276851761465306.1694352728.1696338524.1696341706.7&productId=2248069&score=0&sortType=5&page={i}&pageSize=10&isShadowSku=0&fold=1&bbtf=&shield='
模拟浏览器发送请求,获取服务器返回的数据并转换为json格式。response表示请求得到的响应,把它转为Json,然后利用数据结构解析出里面的内容、评论、时间、用户名。
#模拟浏览器发送请求,获取服务器返回的数据
response= requests.get(url=url,headers=header)
#将数据转换为jason格式
json=response.json()
#解析数据,提取其中的comments
data=json['comments']
#循环拿取数据
for t in data:
# print(t)
content =t['content']
time =t['creationTime']
name = t['nickname']
#python基础异常检测,尝试拿去'location',否则就输出空值
try:
area = t['location']
except:
area =''
score = t['score']
item=[content,time,name,area,score]
items.append(item)
差评和中评的提取方法是一样的,只不过URL发生了变化,此处不做赘述。
3.数据整理
数据整理主要是围绕数据清洗、检验和转换这几项工作。在数据清洗中主要包括数据去重、缺失值处理;数据检验主要包括数据一致性处理、数据规范化处理;数据转换主要包括多数据源合并、不一致数据转换、数据粒度转换等。
3.1数据合并
数据分为三部分评论的爬取,分别是好评、中评和差评,这样数据合并就利用定义一个列表,图中item表示的就是该列表。分别按顺序往列表里面添加评论极其它字段,最后将列表转为DataFrame的格式,并设置列名为columns列表里面的内容,输出查看数据维度后,保存到本地的excel文件。
df = pd.DataFrame(items, columns=['评论内容', '发布时间', '用户名', '用户地区', '用户评分'])
print(df.shape)
df.to_excel('t.xlsx')
3.2数据整理
对合并后的数据文件进行数据清洗,包括类型转换和数据去重与缺失值处理。对数据的整体进行去重,也就是如果有两行一模一样的数据,那么我们只保留一行,并重新设置索引。使用print(data.info())
输出数据框的基本信息,包括每列的数据类型和每列的缺失值数量。然后,使用fillna()
函数填充缺失值。这里使用的填充方法是前向填充('ffill'),意味着用前一个非缺失值填充缺失值。
import pandas as pd
data = pd.read_excel("t.xlsx")
# 删除重复值
print(data.shape)
data = data.drop_duplicates()
print(data.shape)
# 处理缺失值
print(data.info)
data = data.fillna(method='ffill')
print(data.info)
3.3整理结果
对数据进行合并整理后的数据文件中的属性包括评论内容、发布时间、用户名、用户地区、用户评分保存在一个excel表格当中。
OK,爬取完成啦!
4.爬取结果可视化
4.1导入爬取数据
数据结果可视化通过将数据以图形、图表等形式呈现出来,可以更直观地展示数据的趋势、关系和异常值等帮助人们更好地理解和分析数据,提高决策效率和准确性。
将之前爬取结果导入:
import pandas as pd
data = pd.read_excel("评论结果.xlsx").drop(columns =['Unnamed: 0'])#pd将数据读取到data里面
data.sample(5)#随机调用数据
读取结果如下:
4.2数据处理
(1)提取发布时间:从"发布时间"列中提取年、月和日的部分,并将它们分别存储在新创建的"year"、"month"和"day"列中。
#根据for循环(列表生成式)从“发布时间”列提取年月日
data['year'] = list( [i[:4] for i in data['发布时间']] )#提取前四个字符
data['month'] = list([i[5:7] for i in data['发布时间']])#提取前第五-七个字符
data['day'] = list([i[8:10] for i in data['发布时间']])#提取前第八-十个字符
data.sample(5)
结果如下:
(2)规范用户地区名称:根据给定的规则,规范数据框中“用户地区”列的名称,确保它们都是标准或准确的形式。
#规范用户地区名称
list_temp = []#创建空列表
for i in data['用户地区']:
if str(i)=='北京' or str(i)=='上海' or str(i)=='天津' or str(i)=='重庆':
list_temp.append(str(i)+'市')#如果是以上4个直辖市,则添加“市”并加入到空列表中
elif str(i)=='新疆':#自治区如下
list_temp.append('新疆维吾尔自治区')
elif str(i)=='西藏':
list_temp.append('西藏自治区')
elif str(i)=='内蒙古':
list_temp.append('内蒙古自治区')
elif str(i)=='宁夏':
list_temp.append('宁夏回族自治区')
elif str(i)=='广西':
list_temp.append('广西壮族自治区')
else:#如果以上都不是则加“省'
list_temp.append(str(i)+'省')
data['用户地区']=list_temp#将列表赋值到“用户地区”-更新
处理结果如下:
(3)统计上述数据:用pandas的value_counts()
方法来统计“用户地区”列中每个不同值的出现次数,然后从data_2
字典中提取所有值,并将它们转化为一个列表,存储在values_1
变量中并将values_1
列表中的每个元素转换为整数。
#统计'用户地区'列的不同值的出现次数,并将这些统计数据以字典和列表的形式存储在变量中
data_2 = dict(data['用户地区'].value_counts())
print(data_2)
values_1 = list(data_2.values())#从data_2字典中提取所有值转化为列表,存储在values_1变量中
leibie = list(data_2.keys())#从data_2字典中提取所有键,存储在leibie变量中
print(leibie,values_1)
values_1 = [int(value) for value in values_1]#列表推导式
统计结果如下:
4.3数据可视化
(1)生成“各地评论数量”的中国地图:pyecharts
库中导入options
模块、Map
类,用于创建地图,定义函数map_1
,向地图添加数据,并设置地图系列及全局,最终返回一个显示了各省份评论数量的中国地图。
from pyecharts import options as opts
from pyecharts.charts import Map
import random
def map_1() -> Map:
'''
作用:生成中国地图
'''
c=(
Map()
.add("中国地图", [list(z) for z in zip(leibie, values_1)], "china")#以二维列表形式传入
.set_series_opts(label_opts=opts.LabelOpts(is_show=True))#显示省份名称和对应的数量
.set_global_opts(title_opts=opts.TitleOpts(title="各地评论数量"),
visualmap_opts=opts.VisualMapOpts(max_=13,is_piecewise=True))#根据最大值进行颜色区分
)
return c
各地评论数量可视化结果如下:根据各地评论数量进行颜色区分,广东省的评论数量最多(红色)
(2)对广东省数据进行提取分析:首先通过条件筛选从data
数据集中选出所有“用户地区”为“广东省”的记录。然后,使用value_counts()
方法统计这些记录中“用户评分”的分布情况。将其转化为列表,存储在values_1
变量。通过导入pyecharts 、matplotlib将上述数据绘制饼图、柱状图。
#通过过滤,提取出广东省数据
data_2 = dict(data[data['用户地区']=='广东省']['用户评分'].value_counts())
values_1 = list(data_2.values())
leibie = list(data_2.keys())
values_1 = [int(value) for value in values_1]
list3 = [[leibie[i],values_1[i]] for i in range(len(values_1))]
#绘制环形饼图
from pyecharts import options as opts
from pyecharts.charts import Pie
def map_2() -> Pie:
c = (
Pie()
.add("",list3 ,radius=['40%', '60%'], center=['50%', '50%'])#定义饼图半径及中心点位置
.set_series_opts(label_opts=opts.LabelOpts())
.set_global_opts(title_opts=opts.TitleOpts(title="广东省用户评分统计"))
)
return c
#绘制柱状图
data_6 = data['day'].value_counts()
data_6 = dict(data_6)
day = list(data_6.keys())
values = list([int(i) for i in data_6.values()])
from pyecharts.charts import Bar
def map_4() -> Map:
bar = (
Bar()
.add_xaxis(day)#添加横轴
.add_yaxis("次数", values)#添加纵轴
.set_global_opts(title_opts=opts.TitleOpts(title="每个日期出现次数"),
datazoom_opts=opts.DataZoomOpts(type_="slider"))
)
return bar
map_4().render_notebook()
# 绘制饼图
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['FangSong'] # 设置显示中文 字体为宋体
plt.rcParams['font.size']=15 # 设置字体大小
x = data['用户评分'].value_counts().index.tolist()#将值转化位列表
y = data['用户评分'].value_counts().tolist()
plt.pie(y, labels=x, autopct='%1.1f%%',colors = ['red','green','orange','blue','yellow'])
# 显示图例
# plt.legend(x, loc='best')
plt.title("各个评分段占比")
# 显示图形
plt.show()
广东省数据分析结果可视化:
首先检查了数据的维度,data.shape
返回一个元组,表示data
的行数和列数;然后使用dropna()
方法从data
中删除包含缺失值(NaN)的行,创建了一个空列表list_new并
添加为data
的一个新列,列名为'三级评分',其中包含了相应的转换值。
print(data.shape)#查看列表维度
data = data.dropna()#删除缺失值
#运用for循环将值添加至列表
list_new = []
for i in data['用户评分']:
if i==5:
list_new.append(1)
elif i==4 or i==3:
list_new.append(0)
else:
list_new.append(-1)
data['三级评分'] = list_new
结果如下:
从data
中选取'三级评分'列,并使用value_counts()
方法统计每个不同值(即每个评论等级)的出现次数,使用dict()
函数将得到的Series转化为字典并存储在变量overall_dict
中,绘制评论等级的数量分布图,并显示每个等级的数量。
plt.rcParams['axes.unicode_minus'] = False
overall_dict = dict(data['三级评分'].value_counts())
plt.bar(overall_dict.keys(),overall_dict.values())
plt.title("评论等级数量分布")
plt.ylabel("数量")
plt.xlabel("评论等级")
plt.show()
评论等级可视化结果如下:
(3)绘制词云图
导入text将data
中'评论内容'列的所有评论连接起来,形成一个完整的文本;导入jieba库,用于中文分词;以及Counter,用于统计词语出现的次数;定义函数用于分词、过滤停用词,并统计每个词的出现次数。打印出现次数最多的100个词及其次数,执行分词并获取结果。
#绘制词云图
def plotciyun(data):
text = ''
for i in data['评论内容']:
text = text+str(i)
import jieba#中文分词工具
from collections import Counter#统计词语出现的字数
def get_words(txt):#嵌套函数
seg_list = jieba.cut(txt)#切分文本并放入列表
stopwords = ["头发", "洗发水", "感觉",'效果','国货','包装','京东','比较','不少','没有','一般','洗完','支持','之后']
seg_list = [word for word in seg_list if word not in stopwords]#过滤停用词
#对seg_list中的每个词(word),不在stopwords中,保留它;在stopwords中的则移除。
c = Counter()#统计经过停用词过滤后的词频
for x in seg_list:#for循环,遍历seg_list中的每一个词
if len(x) >1 and x != '\r\n':#只统计长度大于1的词,并且忽略掉换行符
c[x] = c[x] +1
print('常用词频度统计结果')
for (k ,v) in c.most_common(100):
print('%s%s %s %d' % (' ' *( 5 -len(k)), k, '* ' *int( v /3), v))
return c
rusult_text = get_words(text)#统计出词频
rusult_text = dict(rusult_text)#词频转换为字典
values_3 = list(rusult_text.values())#字典提取键值对
text = list(rusult_text.keys())
text_tup = [tuple(i) for i in zip(text,values_3)]#构建二维列表
return text_tup
接着导wordcloud库,根据上述的二维列表分别绘制积极态度、中立态度、消极态度词云图,每个词的大小表示其出现的次数。
#绘制中立态度词云图
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType
c = (
WordCloud()
.add("", plotciyun(data_mid),word_size_range=[20, 100])
.set_global_opts(title_opts=opts.TitleOpts(title="中立态度词云图"))
)
c.render_notebook()
#绘制积极态度词云图
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType
c = (
WordCloud()
.add("", plotciyun(data_up),word_size_range=[20, 100])
.set_global_opts(title_opts=opts.TitleOpts(title="积极态度词云图"))
)
c.render_notebook()
#绘制消极态度词云图
from pyecharts import options as opts
from pyecharts.charts import Page, WordCloud
from pyecharts.globals import SymbolType
c = (
WordCloud()
.add("", plotciyun(data_down),word_size_range=[20, 100])
.set_global_opts(title_opts=opts.TitleOpts(title="消极态度词云图"))
)
c.render_notebook()
词云图如下:
爬取结果的可视化分析完成啦!
5.机器学习
机器学习算法可以快速处理大规模数据,现隐藏的模式和规律并进行自我学习和调整,在数据分析中展现出强大的潜力和应用前景。接下来,我们接着看看对于爬虫得到的结果,用机器学习模型如何分析,可以得到什么样的结果。
首先,导入SnowNLP用于处理中文文本,通过初始化名为list_sentiments
的空列表,用于存储文本的情感倾向结果;通过for循环遍历'评论内容'列表,每一个评论i
,使用SnowNLP
类来分析其情感倾向,并将结果存储在sentiments_score
变量中。根据sentiments_score
的值,判断并添加结果到列表中,该值中1表示正面,0表示负面。
import pandas as pd
data = pd.read_excel("评论结果.xlsx").drop(columns =['Unnamed: 0'])
from snownlp import SnowNLP#中文文本处理的库,分析文本的情感、关键字等
list_sentiments=[]#初始化空列表存储文本的情感倾向结果
for i in data['评论内容']:#遍历评论内容
sentiments_score = SnowNLP(i).sentiments#分析文本的情感倾向
if sentiments_score < 0.5:#代表负面情感,1代表正面情感
list_sentiments.append(0)
else:
list_sentiments.append(1)
data.sample(5)
然后,对原始数据进行了预处理,定义函数accuracy
,用于计算预测准确率,并使用这个函数来计算data['orig_score']
和data['snow_score']
两列之间的准确率:将list_sentiments
中的值赋给data
的snow_score
列;创建了一个新的列'orig_score',该列基于'用户评分'列的值(snow_score
列):如果'用户评分'是4或5,则'orig_score'为1,否则为0。
定义函数accuracy,包括y_test
和y_pred两个参数,
初始化一个变量correct
为0,用于计数预测正确的样本数量,使用for循环遍历y_test
中的每一个元素,检查当前索引下的真实(y_test[i]
)是否等于预测值(y_pred[i],
返回准确率,即预测正确的样本数除以总样本数。
data['snow_score'] = list_sentiments
data['orig_score'] = data['用户评分'].apply(lambda x: 1 if x in [4, 5] else 0 )
def accuracy(y_test, y_pred):
correct = 0
for i in range(len(y_test)):
if y_test[i] == y_pred[i]:
correct += 1
return correct / len(y_test)
print("准确率: ", accuracy(data['orig_score'], data['snow_score']))
Accuracy: 0.907407407407407
创建原始数据集副本data_copy,
选择'评论内容'和'orig_score'两列,使用jieba
对df['评论内容']
中的每个评论进行分词处理,使用CountVectorizer
进行特征提取,停用词设置为英文;将数据集分割为训练集和测试集,使用MultinomialNB
(朴素贝叶斯分类器的一种)进行模型训练,并在测试集上进行预测,并评估模型的准确率,准确率的计算是基于真实标签和预测标签是否相等。
data_copy = data.copy()
data_copy =data_copy[['评论内容','orig_score']]
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.model_selection import train_test_split
import jieba
df = data_copy
df['评论内容'] = df['评论内容'].apply(lambda x: ' '.join(jieba.cut(x)))
vectorizer = CountVectorizer(stop_words='english')
X = vectorizer.fit_transform(df['评论内容'])
y = df['orig_score'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
clf = MultinomialNB()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
accuracy = np.mean(y_pred == y_test)
print('Accuracy: ', accuracy)
Accuracy: 0.907407407407407
首先复制了原始数据集data
,然后选择了'评论内容'和'用户评分'两列作为数据集的主要内容;使用jieba
库对中文评论进行分词处理;为了与XGBoost的多分类目标函数相匹配,将原始的评分标签(4、2、其他)转换为0、1、2的标签;创建了一个CountVectorizer
对象来将文本转换为词频矩阵;使用train_test_split
函数将数据集拆分为训练集和测试集;创建一个XGBoost分类器对象,并指定使用多分类的softmax作为目标函数;计算准确率,包括各类别的精确度、召回率和F1分数等。
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report
from xgboost import XGBClassifier
data_copy = data.copy()
data_copy =data_copy[['评论内容','用户评分']]
df = data_copy
# 对中文进行分词处理
df['评论内容'] = df['评论内容'].apply(lambda x: ' '.join(jieba.cut(x)))
list_temp = []
for i in df['用户评分']:
if i==4:
list_temp.append(2)
elif i==2:
list_temp.append(1)
else:
list_temp.append(0)
df['用户评分'] = list_temp
# 创建特征向量
vectorizer = CountVectorizer(stop_words='english') # 去除英文停用词
X = vectorizer.fit_transform(df['评论内容']) # 将文本转化为特征向量
y = df['用户评分'].values # 获取标签
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练XGBoost模型
model = XGBClassifier(use_label_encoder=False, objective='multi:softmax', num_class=10) # 使用多分类softmax作为目标函数,类别数为10(假设有10个类别)
model.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = model.predict(X_test)
from sklearn.metrics import accuracy_score
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")
print(classification_report(y_test, y_pred))
模型精度报告如下:
模型性能较好!
打个广告:这是帮一个学妹大学生做的课程大作业实践,配套代码和报告均有保存,需要的话私信我领取吧!