很久没写了,今天写一个关于Python爬取网络数据然后数据清洗拆分,最后通过词云图可视化的练手小项目。主要学习Python网络爬虫、解Json,存储CSV文件,再读取爬回来的CSV进行数据清洗和分词,最后用词云图可视化提供决策。
Python网络爬虫,定好要爬取的URL和header,以score=1和3分差评集和好评集,写好爬取的页数。这里你可以暂时爬12页测试。把获取的网页信息整理成标准的json格式,再把json格式转成字典,最后把数据放进2个DataFrame对象。
import urllib.request
import json
import time
import random
import requests
url=‘https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6&productId=10992609270&score=2&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1’
#跳过header
header={‘referer’:‘https://item.jd.com/10992609270.html?jt=10’,‘accept’:’/’,
‘user-agent’:‘Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36’}
#html=urllib.request.urlopen(url,headers=header).read().decode(‘utf-8’)
#批量提取评论数据,首先需要构造评论地址集,区分好评和差评,score=1差评,3好评
#爬取n页数据
pos_url=[]#初始化好评地址集
neg_url=[]#初始化差评地址集
n=12
for i in range(0,n):
pos_url.append('https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6&productId=10992609270&score=3&sortType=5&page='+str(i)+'&pageSize=10&isShadowSku=0&fold=1')
neg_url.append('https://sclub.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv6&productId=10992609270&score=1&sortType=5&page='+str(i)+'&pageSize=10&isShadowSku=0&fold=1')
import pandas as pd
import numpy as np
pos_content=pd.DataFrame()
neg_content=pd.DataFrame()
for i in range(0,n):
print('正在读第{}页评论数据'.format(i))
try:
s=requests.get(pos_url[i],headers=header)
s2=requests.get(neg_url[i],headers=header)
html=str(s.text)#把获取的网页信息
html2=str(s2.text)#把获取的网页信息
#把获取的网页信息整理成标准的json格式
jsondata=html[23:-2]
jsondata2=html2[23:-2]
#将json格式转换为字典格式
data=json.loads(jsondata)
data2=json.loads(jsondata2)
referenceName=[x['referenceName']for x in data['comments']]
nickname=[x['nickname']for x in data['comments']]
creationTime=[x['creationTime']for x in data['comments']]
content=[x['content']for x in data['comments']]
referenceName2=[x['referenceName']for x in data2['comments']]
nickname2=[x['nickname']for x in data2['comments']]
creationTime2=[x['creationTime']for x in data2['comments']]
content2=[x['content']for x in data2['comments']]
#print(referenceName,nickname,creationTime,content)
pos_content = pos_content.append(pd.DataFrame({'nickname':nickname,'referenceName':referenceName,
'creationTime':creationTime,
'content':content}))
neg_content = neg_content.append(pd.DataFrame({'referenceName':referenceName2,
'nickname':nickname2,
'creationTime':creationTime2,
'content':content2}))
time.sleep(random.randint(2,3))
except UnicodeDecodeError:
pass
print("爬取完成")
把爬取的分好评集和差评集数据存下来,可以进行好评差评分开分析。
neg_content.to_csv(r’C:/Users/lenovo/Desktop/neg_content.csv’,index=False,encoding=‘utf-8’)#存储文件,不保存索引
pos_content.to_csv(r’C:/Users/lenovo/Desktop/neg_content.csv’,index=False,encoding=‘utf-8’)#存储文件,不保存索引
2.把好评集和差评集增加type字段,好评pos,差评为neg,放到reviews.csv,然后读取进行去重复。
#数据读取
import pandas as pd
import numpy as np
reviews=pd.read_csv(r’C:/Users/lenovo/Desktop/reviews.csv’,encoding=‘gbk’)
#去重
print(‘去重前数据大小:’,reviews.shape)
reviews = reviews[[‘content’,‘type’]].drop_duplicates()
print(‘去重后数据大小:’,reviews.shape)
数据清洗,把评论集中包含数字0-9,字母A-Z和a-z以及、京东、美的、热水器、电热水器,“。”、“,”、“!”等标点符号,全部去掉。当然你想清洗更多无意义内容可以自己在compile函数中增加。
#清洗
content=reviews[‘content’]
import re
#delete =re.compile(’[0-9a-zA-Z]|京东|美的|热水器|电热水器|,|。|!|’)
delete = re.compile(’[0-9a-zA-Z]|京东|美的|热水器|电热水器|。|,|!|!|’)
content=content.apply(lambda x:delete.sub(’’,x))
#content[:5]#查前5条数据
自定义好分词函数
#分词
import jieba.posseg as psg
#自定义一个简单的分词函数
worker=lambda s:[[x.word,x.flag]for x in psg.cut(s)]
seg_word=content.apply(worker)
把清洗去重的数据进行分词
#将词语转化为数据框形式,一列是词,一列是词语所在句子的ID,最后一列是词语所在该句子的位置
#每个评论中词的个数
n_word=seg_word.apply(lambda x:len(x))
n_content=[[x+1]*y for x,y in zip(list(seg_word.index),list(n_word))]
#展开作为词所在评论的ID
index_content=sum(n_content,[])
seg_word=sum(seg_word,[])
#词
word=[x[0] for x in seg_word]
#词性
nature=[x[1] for x in seg_word]
content_type=[[x]*y for x,y in zip(list(reviews[‘type’]),list(n_word))]
content_type=sum(content_type,[])
result=pd.DataFrame({‘index_content’:index_content,‘word’:word,
'nature':nature,'content_type':content_type})
我们查询到result里面的结果是
content_type index_content nature word
0 pos 1 ns 东西
1 pos 1 v 收到
2 pos 1 r 这么久
3 pos 1 d 都
4 pos 1 v 忘
5 pos 1 ul 了
6 pos 1 v 去
7 pos 1 v 好评
8 pos 1 a 大
9 pos 1 n 品牌
10 pos 1 v 值得
11 pos 1 n 信赖
12 pos 1 ns 东西
13 pos 1 n 整体
14 pos 1 u 来看
15 pos 1 n 个人感觉
16 pos 1 d 还
17 pos 1 a 不错
18 pos 1 v 没有
19 pos 1 v 出现
20 pos 1 r 什么
21 pos 1 n 问题
22 pos 1 v 值得
23 pos 1 v 拥有
24 pos 2 v 安装
25 pos 2 nr 师傅
26 pos 2 d 很
27 pos 2 p 给
28 pos 2 n 力
29 pos 2 y 也好
… … … … …
50637 neg 1999 d 真是
50638 neg 1999 v 够
50639 neg 1999 v 磨
50640 neg 1999 n 人
50641 neg 1999 uj 的
50642 neg 1999 d 同样
50643 neg 1999 c 另外
50644 neg 1999 m 一个
50645 neg 1999 n 店
50646 neg 1999 p 在
50647 neg 1999 n 实体店
50648 neg 1999 v 买
50649 neg 1999 uj 的
50650 neg 1999 m 一套
50651 neg 1999 n 全部
50652 neg 1999 v 搞
50653 neg 1999 v 到位
50654 neg 1999 vn 服务
50655 neg 1999 n 差距
50656 neg 1999 d 太
50657 neg 1999 a 大
50658 neg 1999 ul 了
50659 neg 1999 v 想想
50660 neg 1999 d 就
50661 neg 1999 v 失望
50662 neg 2000 v 烧
50663 neg 2000 q 个
50664 neg 2000 n 水
50665 neg 2000 d 真心
50666 neg 2000 a 慢
50667 rows × 4 columns
3.词云图可视化,把分词结果利用词云图显示出来。自己定好显示的形状图片back_pic,路径要正确比如我这里用了一张我桌面的心形图love.jpg
from imageio import imread
back_pic=imread(“C:/Users/lenovo/Desktop/love.jpg”)
wordscloud=result[‘word’].value_counts()
import matplotlib.pyplot as plt
from wordcloud import WordCloud
wc=WordCloud(font_path= ‘msyh’,background_color=‘black’,mask=back_pic)#微软系统的不需要写完整路径,把字体名字写上就可以了
wc.fit_words(wordscloud)
plt.imshow(wc)
plt.axis(‘off’)
plt.savefig(‘cyuntu.jpg’,dpi=180,figsize=(6,8))#存到当前工作目录,分辨率dpi=180,大小为figsize=(6,8)
plt.show()
项目结果词云图如下(数据实时更新,每个人爬取的数据有差异,词云图就不尽相同):
从词云图可以看出词有大有小,面积越大,说明出现频率越高,但是有些词却没有什么意义,说明我们在数据清洗的时候清洗得不干净,可以调整代码,把“的,了,是,说,很”等词在 re.compile(’[0-9a-zA-Z]|京东|美的|热水器|电热水器|。|,|!|!|’)中增加去掉。从图中我们可以看到很明显的是“安装、售后、质量、师傅、服务、送货、安装费”等说明用户很关心这些问题,那我们可以给店家的建议就可以针对这些方面去关注和改善。利用词云图可视化可以很直观找出关键词,提供决策依据和方向。