在学习了python爬虫(requests,bs4)以及numpy、pandas、matplotlib库之后,就想试个小项目磨磨刀。之前只会单方面的使用,比如爬取一个网站相关数据 或者 对已经给了的数据进行分析。这个项目将这几个部分串起来了。学过这几个库的人就知道,这个项目很简单嘛。确实不难,但是自己完整的做完还是会出很多意想不到的bug。另:如果有同学只想做数据分析和可视化展示,这也没问题。以下百度网盘链接也提供了已经使用爬虫获取的数据。
环境:python(anaconda)
源码:百度网盘链接:https://pan.baidu.com/s/101ck6wc_YyHuFLAZtLgLGA
提取码:r1n1(包括源代码以及通过爬虫获取的影评内容)
源码是ipynb文件,使用Jupyter Notebook打开
忠告:朋友,可以拿我这个项目试试,今天刚出炉的,用的是,配了环境,然后安装下需要的包应就能跑的,要源码的复制上面百度网盘的链接就能获取。需要掌握的知识就是上面写的那几个python库。如有不佳,还请海涵。
直接上图:这里只显示一部分对影评分析后得到的可视化图片。
二、思路
1、进入下面url,按F12打开 开发者模式,分析html代码,这里我主要获取了评论人用户名,评论时间,评论内容,评论评星,评论点赞数等,这几个信息。通过分析发现,下一页的链接是https://movie.douban.com/subject/30163509/reviews?start=20 ,没错,这样我们只需要一个for循环就能遍历完所有的评论了。大概3000多条评论左右,数量不算多,爬虫大概跑个4-5分钟就能爬下你需要的数据,爬下的数据存于一个csv文件就好(用excel可以打开)。
https://movie.douban.com/subject/30163509/reviews
2、爬虫已经获取的数据,这里我们再使用numpy、pandas库对其进行数据分析,使用matplotlib来进行画图操作。就这些步骤,就这么简单。
三、具体实现(上代码)tips:如果在实战这个项目的同学,建议下载好我分享的源码,以下内容只是将源码解释一遍
1、爬取数据,存储至csv文件
以下代码是爬虫获取数据并且将其存入pacong.csv文件中,以上也说了,csv文件excel可以打开
其实运行以下代码爬到了大概3000多行数据后会报错。这不要紧,这个时候pacong.csv文件中已经将3000多条评论数据都存下来了。
这里使用csv库来存数据。其实也可以用mongodb数据库来存,但是配环境太烦了,这里就用了csv。这个csv库也简单,几行代码就解决了存储数据的问题。
import csv
import numpy as np
import requests
from bs4 import BeautifulSoup
import time
def getHtmlText(url):
headers = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0',
'Connection': 'close'
}
html = requests.get(url,headers = headers,verify=False).text
return html
def solveAndSave(url,writer):
html = getHtmlText(url)
soup = BeautifulSoup(html,'html.parser')
review_list = soup.find('div','review-list')
# print (review_list.div,'\n\n\n')
# 这个方法遍及儿子节点,每次都会少第一个评论
for div in review_list.div.find_next_siblings()[0:-1]:
# print ('\n\n\n',div)
div = div('div')[0]
# print (div)
header = div('header')[0]
# print (header)
main_body = div('div')[0]
# find header useful
name = header('a')[1].string
stars = header('span')[0].get('title')
if len(header('span'))==1:
time = 'no star'
else:
time = header('span')[1].string
# find main body usefful
title = main_body('h2')[0]('a')[0].string
content = main_body.find('div','short-content').string
action = main_body.find('div','action')
userful_nums = str(action('a')[0]('span')[0].string).replace(' ','')
useless_nums = str(action('a')[1]('span')[0].string.replace(' ',''))
reply_nums = str(action('a')[2].string.replace(' ',''))
data = [(name,stars,time,title,content,userful_nums,useless_nums,reply_nums)]
writer.writerows(data) # 多行用writerows
# csvfile.close()
# print (name,stars,time,userful_nums,useless_nums,reply_nums)
def main():
# write in csv
csvfile = open('pacong.csv', 'w',newline='',encoding='utf-8')
# 如果不指定newline='',有时则每写入一行将有一空行被写入
writer = csv.writer(csvfile)
writer.writerow(['评论人姓名', '评价', '评论时间','评论标题','评论主体','赞成数','反对数','回复数']) # 写入一行用writerow
for i in range(0,3980,20):
time.sleep(0.5)
url = 'https://movie.douban.com/subject/30163509/reviews?start='+str(i)
solveAndSave(url,writer)
csvfile.close()
main()
大概csv内容的样子如下:
2、分析数据并画图
这里使用csv文件中评论标题这一列,做个词云来玩玩。词云里面可以不加 ’mask=background_image‘这个参数,这个主要控制词云生成的形状。当然你也就不用导入cv2的库了
这里上代码:
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from wordcloud import WordCloud
import jieba
import cv2 as cv
# 读入图片背景
# 对于中文词云首先使用jieba来中文分词,然后还要记得指定font_path设置字体识别
# 想要的话还能设置词云的背景图片
background_image = cv.imread('../image/ciyun.jpg') # 不设置background_image可以不加这行,得到的词云就是矩形了
# with open('pacong.csv','r',encoding='utf-8') as f:
# text = f.read()
# print (text)
yingping = pd.read_csv('pacong.csv')
all_content = ''
for i in range(0,len(yingping['评论标题'])):
all_content= all_content+yingping['评论标题'][i]
cut_text = " ".join(jieba.cut(all_content))
# print (cut_text)
# print (all_content)
# yingping.head()
wordcloud = WordCloud(font_path="C:/Windows/Fonts/simfang.ttf",mask=background_image,background_color='white').generate(cut_text)
plt.figure(figsize=(10,10))
plt.imshow(wordcloud,interpolation="bilinear")
plt.axis("off")
plt.show()
效果:
接下来,开始对数据坐下子预处理咯,你看下面代码,就是把赞成数,反对数,回复数这几列处理了下。我们爬下来的csv中,这几列有一些换行和文字,用string的repalce方法替换一下就行。还要将评价的文字转化为评论得分,
这个操作很简单对不对,但是可以说的高大上点,就是做数据挖掘(就是把数据的文本信息提取为我们可分析的数据类型)
# help(yingping.last)
print (yingping.head())
def prepressingData(data1):
data = data1.copy()
zancheng = data['赞成数']
fandui = data['反对数']
huifu = data['回复数']
pingjia = data['评价']
star = []
for i in range(0,len(zancheng)):
zancheng[i] = zancheng[i].replace('\n','')
fandui[i] = fandui[i].replace('\n','')
huifu[i] = huifu[i].replace('回应',' ')
if pingjia[i]=='力荐':
star.append(5)
elif pingjia[i]=='推荐':
star.append(4)
elif pingjia[i]=='还行':
star.append(3)
elif pingjia[i]=='较差':
star.append(2)
elif pingjia[i]=='很差':
star.append(1)
else:
star.append(0)
data['评价得分'] = pd.Series(star)
data = data.drop(axis=1,columns=['评论主体'])
# 删除列,后要赋值过去才算成功
return data
yingping = prepressingData(yingping)
将我们上面通过评价列得到的评价得分列做个直方图,
yingping.head(50)
# yingping['赞成数'][3377]
yingping.isnull().any()
# 画图开始
plt.rcParams['font.sans-serif']=['SimHei']
plt.figure(figsize=(10,8))
plt.hist(yingping['评价得分'],bins=20)
plt.xlabel('星级(0表示没有评级)',size=14)
plt.ylabel('人数',size=14)
plt.show()
效果:通过结果可以看出评分4-5颗星占大多数,应该属于一个好评居多的电影。(没看过飞驰人生的人可以康康,毕竟自己分析的这个电影还不错撒)
然后呢,接下来的代码我就不具体解释了,直接上代码和效果,毕竟大家还有度娘
将以下几种类型转化为数字类型,有NAN(缺失值)的使用fillna进行填充
yingping.head()
def cvtInt(data1):
data = data1.copy()
data['赞成数'] = pd.to_numeric(yingping['赞成数'],errors='ignore')
data['赞成数'] = data['赞成数'].fillna(0)
data['反对数'] = pd.to_numeric(yingping['反对数'],errors='ignore')
data['反对数'] = data['反对数'].fillna(0)
data['回复数'] = pd.to_numeric(yingping['回复数'],errors='ignore')
return data
yingping = cvtInt(yingping)
# yingping.sort_values(by=['赞成数'],ascending=False)
# yingping.sort_values(by=['回复数'],ascending=False)
# yingping.isnull().any()
import numpy as np
# pd.to_numeric(yingping['赞成数'],errors='ignore')
yingping['评论时间']
def dropUselessTime(data):
data1 = data.copy()
index = data1[data1['评论时间']=='no star'].index
data1 = data1.drop(axis=0,index=index)
return data1
yingping = dropUselessTime(yingping)
yingping.index = yingping['评论时间']
yingping
效果:
接下来:
# help(yingping.drop)
# yingping['year'] = pd.to_datetime(yingping['评论时间']).dt.year
yingping['month'] = pd.to_datetime(yingping['评论时间']).dt.month
yingping['hour'] = pd.to_datetime(yingping['评论时间']).dt.hour
def plotTimeWithData(data):
data1 = data.copy()
cur = data1.groupby('hour').count()
plt.figure(figsize=(10,6))
plt.plot(cur.index,cur['month'])
plt.xlabel('时间/hour',size=16)
plt.ylabel('评论数量',size=16)
plt.title('评论数量随时间段的变化',size=16)
xticks=list(range(0,len(cur.index))) # 这里设置的是x轴点的位置
plt.xticks(xticks)
plt.show()
cur = data1.groupby('hour').mean()
plt.figure(figsize=(10,6))
plt.plot(cur.index,cur['评价得分'])
plt.xlabel('时间/hour',size=16)
plt.ylabel('评论分均值',size=16)
plt.title('评论均值随时间段的变化',size=16)
xticks=list(range(0,len(cur.index))) # 这里设置的是x轴点的位置
plt.xticks(xticks)
plt.show()
plotTimeWithData(yingping)
效果:
分析这两图发现,从凌晨4点-23点评论数量是不断增多的,说明大多数人喜欢在晚上看这部电影并且评论。然后咧,发现在凌晨三点评分的均值相当的低啊,说明在3点中的时候,大家心情都不太好的亚子,所以这也告诉我们,不要去惹经常熬夜的人,他们的心情可不好哦;这六点钟早起的人心情就不错,评分均值达到一天的最高点
四、总结
当然三千组数据可能还是有点少,但是我们就是学习嘛,能学到东西就好了。还有其实还能通过分析数据画很多有意义的图,有兴趣的同学可以学习以下seaborn库(matplotlib库封装的基础上的库),可以画出能多精美的图哟。可以参考我的另外一篇博客https://blog.csdn.net/weixin_41466575/article/details/104343245
有问题的伙伴可以在评论区中留言,我会及时回复大家的!!!
http://liuyishou.site 这是我个人开发的博客网站哦,欢迎大家来参观。
作者:刘一手emm