python抓取淘宝商品评论并分词分析.docx
《python抓取淘宝商品评论并分词分析.docx》由会员分享,可在线阅读,更多相关《python抓取淘宝商品评论并分词分析.docx(18页珍藏版)》请在冰豆网上搜索。
![python抓取淘宝商品评论并分词分析.docx](https://file1.bdocx.com/fileroot1/2023-3/30/8d0b318a-1e0c-403c-81f2-8136f52d51ee/8d0b318a-1e0c-403c-81f2-8136f52d51ee1.gif)
python抓取淘宝商品评论并分词分析
python抓取淘宝商品评论并分词分析
数据时说的是很多问题和事物都可以通过数据分析达到选择最优的解决方案.不要认为这些离我们生活很远,其实不然。
比如我们经常去淘宝买东西,我们最终都是在看好的几家商铺中去选择,而我们最终选择哪家商铺大多都是根据商品的评价来选择,这是最基础的数据应用,并且这也只能看见表面的现象。
总所周知某宝或某东等各平台上,商品评价存在各种造假或者各种刷单(天猫店铺甚至连差评的标签都没有,就是说不能差评了,真鄙视它),同时评论数量很多,也没办法一条条看下去。
今天,我们就用数据分析的手段对我们想购买的商品评论进行分析,让奸商见鬼去吧。
假设我们想要个电动滑板代步车(这也算是大件了),于是在淘宝进行搜索,并最终锁定几家店铺的商品:
表面上两个商品的评价都很好但是仔细分析发现刷单很严重。
下面我就开始对各家店铺的商品评论进行分析。
这里不讨论我的爬虫设计的过程以及相关的url获取,因为这个过程比较复杂,需要不停的尝试和查找,比较偏技术(我花了好些时间才找到正确的ajx接口)。
整个数据处理以及分析过程都是基于python来实现的。
python和R语言一样,R能实现的分析算法python也能实现,而且还能实现其他非分析的功能,所以很多人从R语言转向python,当然从统计学的专业性来说R语言更权威。
首先把网页的网址复制下来
如上图:
红框内的网址,复制到数据处理脚本中
url=’
如下图:
其中527262264900是id,下面就根据这个网址进行数据抓取。
由于淘宝后台的限制,虽然评论数有2585条,但是我们只能抓取最近评论的1980条数据。
虽然不算多但是对单个产品分析还是足够的。
抓取的数据后如下图所示:
User是淘宝ID,contens是首次评价内容,datetime是首次评价日期。
Appendtime是指追评日期,appendcontents是追评内容,paytime是只购买日期(天猫店铺不提供),price是只单价(天猫店铺不提供)。
在程序的运行目录下生成下列文件,各文件的标题包含商品id
第一个文件是抓取的评论,为了防止数据重复抓取,我们把它作为txt文件存储。
主要手段是网络爬虫
由于淘宝对评论数据的限制,我们只能获取最近的2000条数据,再远的数据是获取不到的。
第二个文件日汇总统计图;每日的评价数量趋势图,主要看销量变化和价格变化(价格变化天猫店铺数据不包含)
上图体现的是评论数、和价格变化趋势。
从评论数的角度可以反推销售数。
当然销售数肯定大于评论数。
那么我们可以从上图看到什么呢?
1、3月11日后开始统计。
4月下旬后销量飙涨,然后逐月递减。
7月后回到原有销量水平。
就是说在5、6、7月商品突然维持一个高的销量水平,然后有立马降下去(即使价格下降销量还是下降)。
很显然刷单
2、一个奇怪现象,价格高销量好,价格下降了销量反而下降,很不寻常。
估计有大量刷单
3、追评数和追评率看不到特殊异状。
第三个文件是差评词云图,主要看差到哪了。
首先定义差评:
评论中包含下列词汇的我们认为这条评价是差评
【'太差','材料差','各种问题','出现问题','质量差','坑人','很差','不满意','冒牌','假的','服务差','毛病','非常差','废物','垃圾','破烂','不值','各种问题','差评','坏的','坏了','烂了','无良','骗子','欺骗','不达标','出问题','特差','上当','不能用','报废','残次',u'差劲','坑爹','太黑','不要买','后悔','有多差','被坑'】
根据差评的评论可以先分词,再按词统计生成词云。
如图所示我们有以下分析结果:
1、大家关注的要点是公里、续航、电池,大概就是电池不够、续航差,一班也就15、20、30公里
2、【作出评价】【15】【一个月】【好评】,这个词主要来源是
说明差评的买家在首次多数是没有评价的,主要是追评,追评为差评
3、【坏了】【螺丝】【质量】【客服】【售后】为特征词,大概可以想象差评的主要原因。
质量不好,某个东西容易坏、比如螺丝。
售后也不咋地,客服很垃圾。
等等
第四个是剔除刷单买家评论、绝对好评客户后的其他评论生成的词云图,主要用来看客户大致评价
首先定义疑似刷单评价,这个包含两方面一是当天评价又在10个小时内追评的(当然不包含差评),按照买家习惯。
正常买家一般不会追评,追评的一般都都是过了些天发现有问题才来差评(除非商户给买家优惠或者是买家太无聊才会追好评,这个大家经常网购的清楚),何况当天就追评的那是少之又少,我们是秉承宁可错杀1000也不放过一个原则,将能找到的刷单尽量找出来。
二是从买家ID评论的次数来看。
虽然淘宝隐藏了买家ID中间的一些文字。
但是我们还是可以从这买家ID来识别刷单。
这种买家ID出现相同的概率还不是很大,而且在同一商品下出现相同的买家ID概率会更小,但是不排除这种可能。
所以我们可以定义同一买家ID出现超过4次的认为该买家ID存在刷单行为。
至于为什么是4这个是我通过几家店铺的的评论数据百分比得出的(而且有句老话就是是不过三),当然你也可以设为5,甚至6、7、8。
按买家ID评论统计如下,同一个买家ID评论数多大36次,很显然认为是刷单专业户。
如下图
有意思t***0,t***1,t***2,t***3……t***8,t***9,这0到9都到齐了,不是刷单才怪了。
比较账号多了不好记,这样取名符合刷单特征。
极端情况我们甚至可以把以数字结尾,字母开头的非差评买家定义为刷单,这里没有,但是如果这样定义后的仍然有几百条买家评论存在也是可以的。
接着定义绝对好评,绝对好评就是首次评论中使用非常绝对的好评词汇。
例如:
【'很好','非常好','完美','很棒','很满意','很实用'u'很喜欢','很耐心','很不错','很拉风','很负责','非常棒','十分满意','非常满意','满分','很赞','非常实惠','很耐用'】。
作为首次评论用这样绝对的词汇是很有可能是刷单买家评论。
接着来分析剔除刷单买家评论、绝对好评客户后的词云图:
1、评论关注的还是公里数、续航能力
2、找到好评词汇【很快】【方便】【好评】【速度】【折叠】【喜欢】,优点词汇很少
3、找到差评词汇【坏了】【螺丝】【刹车】【差评】
4、好评都是没有从质量出发的,差评都是质量问题
5、从这里无法确定买还是不买
第五个文档是生成的评价word文档,是分析的结果文档,包含各种分析结果。
将前面的各个图表都输入到word文档上。
里面有一个非常重要的指标项可以用来判断买还是不买
就是重复评论(刷单)用户占比、扣除刷单后差评率、绝对好评率三项指标。
在重复评论(刷单)用户占比24.55%、绝对好评为37.32%的情况下,差评率仍然高达14.86显然不值得买。
这里写的算法都是对单个商品就行分析的,没有对商品群分析,所以结果不是完美。
比如从商品群的评价库提取常用的评价词汇和语句,就行更细的评价分类,和重点的分词词汇,这样词云图的结果会更明显。
再比如刷单买家的识别,如果我们有很多商品的话就可以通过买家的购买频率识别是不是刷单买家了,下面是三家电动滑板车的刷单买家统计:
商品1、
商品2、
商品3、
看了这几副图后,是不是感觉刷单的还是那几个人啊。
哈哈,废话不说了,直接贴上分析代码
#coding=utf-8
importos
importurllib2
importjieba
fromrandomimportrandint
importpandasaspd
importtime
importjson
importmath
importtypes
importmatplotlib.pyplotasplt
fromwordcloudimportWordCloud
importnumpy
fromdocximportDocument
fromdocx.sharedimportInches
#importsys
#reload(sys)
#sys.setdefaultencoding('utf-8')
#差评定义词汇
mywords=[u'太差',u'材料差',u'各种问题',u'出现问题',u'质量差',u'坑人',u'很差',u'不满意',u'冒牌',u'假的',u'服务差',u'毛病'\
u'非常差',u'废物',u'垃圾',u'破烂',u'不值',u'各种问题',u'差评',u'坏的',u'坏了',u'烂了',u'无良',u'骗子',u'欺骗',\
u'不达标',u'出问题',u'特差',u'上当',u'不能用',u'报废',u'残次',u'差劲',u'坑爹',u'太黑',u'不要买',u'后悔',u'有多差',u'被坑']
#绝对好评
goodwords=[u'很好',u'非常好',u'完美',u'很棒',u'很满意',u'很实用',u'很喜欢'\
u'很耐心',u'很不错',u'很拉风',u'很负责',u'非常棒',\
u'十分满意',u'非常满意',u'满分',u'很赞',u'非常实惠',u'很耐用']
defgetItemId(url):
uid=url[url.find('id=')+3:
url.find('id=')+18]
ifuid.find('&')>0:
itemid=uid[0:
uid.find('&')]
else:
itemid=uid
returnitemid
defgetRedf(url):
#将list数据转换
relist=[]#printurl
try:
content=json.loads(urllib2.urlopen(url).read().replace('"rateDetail":
','').replace('','').replace('',''),'gbk')#gb18030比gbk含更多字符
except:
printurl,'json解析错误'
returnpd.DataFrame(),99
ifcontent.has_key(u'rateList'):
hasprice=content[u'rateList'][0][u'attributesMap'].has_key('t_payTime')
foriinxrange(len(content[u'rateList'])):
iftype(content['rateList'][i]['appendComment'])istypes.DictType:
ifhasprice==True:
relist.append((content[u'rateList'][i]['displayUserNick'],content[u'rateList'][i]['rateContent'],content[u'rateList'][i]['rateDate']\
content[u'rateList'][i][u'attributesMap']['t_payTime'],content[u'rateList'][i][u'attributesMap']['t_detailPrice'],content[u'rateList'][i][u'attributesMap']['t_buyAmount']\
content[u'rateList'][i][u'appendComment'][u'commentTime'],content[u'rateList'][i][u'appendComment'][u'content']))
else:
relist.append((content[u'rateList'][i]['displayUserNick'],content[u'rateList'][i]['rateContent'],content[u'rateList'][i]['rateDate']\
content[u'rateList'][i]['gmtCreateTime'],0,1\
content[u'rateList'][i][u'appendComment'][u'commentTime'],content[u'rateList'][i][u'appendComment'][u'content']))
else:
ifhasprice==True:
relist.append((content[u'rateList'][i]['displayUserNick'],content[u'rateList'][i]['rateContent'],content[u'rateList'][i]['rateDate']\
content[u'rateList'][i][u'attributesMap']['t_payTime'],content[u'rateList'][i][u'attributesMap']['t_detailPrice'],content[u'rateList'][i][u'attributesMap']['t_buyAmount']\
u'',numpy.nan))
else:
relist.append((content[u'rateList'][i]['displayUserNick'],content[u'rateList'][i]['rateContent'],content[u'rateList'][i]['rateDate']\
content[u'rateList'][i]['gmtCreateTime'],0,1,u'',numpy.nan))
returnpd.DataFrame(relist),content['paginator']['lastPage']#最大页数
else:
time.sleep(5)
print'等待5毫秒:
'#,url
returngetRedf(url)
defgetDeatail(itemid='534388747823'):
baseurl="
url=baseurl.format(itemid,randint(100000000,700000000),1)
mydf,pages=getRedf(url)#mydf=pd.concat(mydf,first)#pages=totals/20+1;
p=2
while(p<=pages):
url=baseurl.format(itemid,randint(100000000,700000000),p)
print'正在读取第{0}页'.format(p)
p=p+1
tpdf,n=getRedf(url)
mydf=pd.concat([mydf,tpdf])
mydf.columns=['user','contents','datetime','t_payTime','t_detailPrice','t_buyAmount','appendtime','appendcontents']
returnmydf
defgetSeg(scarydata):
#获取分词的DataFrame注意修改一些文件路径
afterseg=[]
foruinmywords:
jieba.add_word(u)
stopwords={}.fromkeys([line.rstrip().decode('utf-8')forlineinopen('E:
/360yun/myprog/outwords.txt')])#如果确保唯一可以直接用list
stopwords[u'不错']='0'
stopwords[u'车子']='0'
fori,tinscarydata.iterrows():
tp=t[0].replace('','').replace('','')
segs=jieba.cut(tp)
forseginsegs:
iflen(seg)>1andsegnotinstopwords.keys():
afterseg.append((tp,seg))
userwords=pd.DataFrame(afterseg)
userwords.columns=['user','words']
returnuserwords
defwcfigure(wordsdf,path=r'test.jpg',mytitle=''):
#画云图图,传入dataframe,保存文件路径和名字wdcounts.head(2000).itertuples(index=False)
wordcloud=WordCloud(font_path='c:
\windows\fonts\STCAIYUN.TTF',background_color="white",margin=5,width=1800,height=1000)
#必须要加载文字体不然中文乱码#printsegStat.head(100).itertuples(index=False)
wordcloud=wordcloud.fit_words(wordsdf.itertuples(index=False))
plt.figure(num=None,figsize=(25,16),dpi=8,facecolor='w',edgecolor='k')
plt.imshow(wordcloud)
plt.axis("off")
#plt.title(mytitle)
plt.savefig(path)
plt.show()
plt.close()
defrefind((x,y)):
ifx>15000orx<20:
returnFalse
else:
returny
deffindBad(words):
flag=False
#printtype(words)
#ifisNan()
words=words.decode('utf-8')
forxinmywords:
#x=x.encode('utf-8')
ifxinwords:
flag=True
break
returnflag
deffindBest(words):
flag=False
#ifisNan()
words=words.decode('utf-8')
forxingoodwords:
#x=x.encode('utf-8')
ifxinwords:
flag=True
break
returnflag
#url='
#url='
url='
itemid=getItemId(url)
ifos.path.exists(itemid):
#当前路径shous=os.getcwd()查找是否曾经抓取数据
mydata=pd.read_csv(itemid)
else:
mydata=getDeatail(itemid)
mydata.to_csv(itemid,encoding='utf-8',index=False)
mydata=pd.read_csv(itemid)
mydata['paytime']=mydata['t_payTime'].apply(lambdax:
time.strftime('%Y-%m-%d%H:
%M:
%S',time.localtime(x/1000)))
mydata['hours']=mydata['datetime'].str[11:
13]
mydata['price']=mydata['t_detailPrice']/mydata['t_buyAmount']
delmydata['t_payTime'],mydata['t_detailPrice'],mydata['t_buyAmount']
mydata['dates']=mydata['paytime'].str[0:
10]
groupby_date=mydata.groupby(by=[u'dates'])[u'appendcontents'].agg({u'总评论数':
numpy.size,u'追评数':
'count'})
mydata=mydata.fillna('')
mydata['badcontents']=mydata['contents'].apply(findBad)|mydata['appendcontents'].apply(findBad)
mydata['best']=mydata['contents'].apply(findBest)|mydata['appendcontents'].apply(findBest)
mydata['datetime']=pd.to_datetime(mydata['datetime'])
mydata['appendtime']=pd.to_datetime(mydata['appendtime'])
mydata['difftime']=(mydata['appendtime']-mydata['datetime']).apply(lambdax:
pd.isnull(x)and200orx.total_seconds())#追评相差天数
mydata['wordsnum']=((mydata['contents'].str.len().f