python爬虫实战+数据分析+数据可视化(分析豆瓣 《飞驰人生》影评)

一、概要

     在学习了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

扫描二维码关注公众号,回复: 10527736 查看本文章

    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  这是我个人开发的博客网站哦,欢迎大家来参观。

发布了40 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41466575/article/details/105303376