爬取豆瓣top250电影榜的电影分类进行数据分析

2015-10-09 21:04:20

本博客采用创作共用版权协议, 要求署名、非商业用途和保持一致. 转载本博客文章必须也遵循署名-非商业用途-保持一致的创作共用协议

这是我转向数据分析第一篇博文,也是第一次的尝试,希望能从数据中,从图中找到很多有用的信息。

用爬虫爬取豆瓣top250的电影分类,并保存在mongodb中


我们要爬取的网站是这个 豆瓣top250电影榜

我们要爬取的东西,这次是这个(划红线部分),即他的分类:

pic

这次我们还是使用我们熟悉的 scrapy 爬虫框架,因为有前几次的经验,我们就直接上代码了

开启我们的爬虫项目

scrapy startproject douban_movie_category

好,同样的,我们编写我们的容器 item.py:

# -*- coding: utf-8 -*-

import scrapy

class DoubanMovieCategoryItem(scrapy.Item):

    categories=scrapy.Field()

这次我们只保存他的分类

然后我们就要编写我们的爬虫了,因为这次的爬虫任务很麻烦,因为如下图,豆瓣把很多汉字和符号都写在了一起,这让他很难处理:

pic

# -*- coding: utf-8 -*-
#encoding:utf-8

from scrapy.spiders import Spider 
from scrapy.linkextractors import LinkExtractor
from scrapy.selector import Selector
from douban_movie_category.items import DoubanMovieCategoryItem
import jieba

class CategorySpider(Spider):
    name="category_spider"

    allowed_domains=["www.movie.douban.com"]
    start_urls=[
        'http://movie.douban.com/top250?start=225&filter=&type=',
    ]

    def parse(self,response):
        sel=Selector(response)
        item=DoubanMovieCategoryItem()
        category=sel.xpath("//div[@class='info']/div[@class='bd']/p/text()").extract()

        print type(category)
        x=[]
        for i in category:

            if len(i)>5 and ':' not in i:
                i=i.split('/')
                i=i[len(i)-1]

                i=i.strip()
                i=i.replace(" ","")
                word=unicode(i)

                if word!=" " and len(word)>0:

                    print len(word)
                    print word

                    words=jieba.cut(word,cut_all=False)
                    for n in words:
                        print n
                        x.append(n)
        item['categories']=x        
        yield item

这里我们对他进行了稍许的字符串处理,因为过程很麻烦,涉及到了中文的encoding编码之类的问题,花了我很长时间,而且这段逻辑代码看着很丑陋,我就简单的说说要点吧

  • 首先下载下来的是这个带着 “导演:```````犯罪 剧情”的这么一段长长的文字,我们对他进行去除空格,并且使用 / `来裂开他们,然后我们发现裂开后的最后一个元素就是我们想要的,这是我们把它取出来

  • 第二点,这就要感谢我们天朝人们出品的动用很多机器学习算法的包 jieba,通过他的只能分词,我们可以把诸如 犯罪剧情这样的词组分成 [ u"犯罪", u"剧情"]这样,我们就能得到这个页面的所有出现过的分类了

好了,现在我们来编写我们的 pipelines.py,这次我们要使用 mongodb来保存我们爬取的数据,并且给予它一定的数数,因为我长期在写后台时基于的是 sql型的数据库,这次使用 pymongo调用使用 mongodb 感觉还不错,数度相当快,而且也非常好操作,返回回来的字典与他本身保存的 json格式很好相通

# -*- coding: utf-8 -*-
#encoding:utf-8

import pymongo
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )

class DoubanMovieCategoryPipeline(object):

    def __init__(self):
        self.mongo_url='localhost'
        self.mongo_port=27017
        self.collection_name='categories'
        self.db_name='douban_category'

    def open_spider(self,spider):
        self.client=pymongo.MongoClient(self.mongo_url,self.mongo_port)
        self.db=self.client[self.db_name]
        self.con=self.db[self.collection_name]

    def close_spider(self,spider):
            self.client.close()

    def process_item(self, item, spider):
        for i in item['categories']:
            if self.con.find_one({"category":unicode(i)}):
                add_one=self.con.find_one({'category':str(i)})
                print add_one
                count=int(add_one['count'])
                count=count+1
                add_one['count']=count
                print add_one
                print count
                self.con.save(add_one)
            else:
                self.con.insert_one({'category':i,"count":1})
                print "hello"
        print item['categories']
  • 这里我们每次爬虫都开启我们的 数据库,进行数据库操作,每次关掉爬虫就关掉(这点比去 sql型数据库的 orm舒服多了)

  • 我们做一次我们得到的数据的迭代处理,若是数据库里面有的我们就在这里加1,若是没有我们就创建,初始出现次数 count为1

好的,那么将 pipelinessettings.py中设定好,就和我前几次一样

我们就可以跑动我们的代码:

scrapy crawl category_spider

如此一来,我们变得到了他的数据

使用matplotlib对他进去数据可视化操作


我们这次使用的是 python家族做数据可视化久负盛名的包 matplotlib,他里面包含了大量的可视化操作需要调用的函数,可以画做诸如 饼状图,散点图,函数曲线图,柱状图,气象图,3d渲染图等等等等 ,因为他和 巨强大的numpy与 我还没有使用过的 scipy python家族中做科学计算的必备,也是因为有了他们,python得以在科学计算领域与 matlab 相抗衡。我们还是老规矩吧,先上代码再进行他的思路解释:

data_sol_douban.py

# -*- coding: utf-8 -*-
#encoding:utf-8

import matplotlib.pyplot as plt
from pylab import *

import pymongo  
from matplotlib.font_manager import FontProperties
import subprocess
import numpy as np

font=FontProperties(fname=r'/usr/share/fonts/truetype/字体管家扁黑体.ttf',size=14)

def pic_show():
    client=pymongo.MongoClient("localhost",27017)

    db=client['douban_category']

    con=db['categories']

    data=[]
    category=[]

    for item in con.find():
        data.append(item['count'])
        category.append(item['category'])

    print data
    for n in  category:
        print n

    y_pos=range(len(category))

    colors = np.random.rand(len(category))

    plt.barh(y_pos,data,align='center',alpha=0.4)
    plt.yticks(y_pos,category,fontproperties=font)
    for data,y_pos in zip(data,y_pos):
        plt.text(data,y_pos,data,horizontalalignment='center',verticalalignment='center', weight='bold')
    plt.ylim(+28.0,-1.0)
    plt,title(u"豆瓣电影top250部分类统计",fontproperties=font)
    plt.ylabel(u"电影分类",fontproperties=font)
    plt.subplots_adjust(bottom = 0.15)
    plt.xlabel(u"分类出现次数(一部影片分类可以多个)",fontproperties=font)
    plt.savefig("douban_category_new.png")  

pic_show()
  • 首先,我们用 pymongo,把数据从数据库中拿出来,并按照 category(分类名),data(出现次数),来存储数据,因为他是和python的dict形式很像的,所以我们使用迭代把他们拿出来

  • 然后我调用 matplotlib进行绘图,这次我们用的是柱状图(barh),还需要在y轴上做分类名的标记(ystick),并且打出他的标题(title)以及他在x轴边上是什么(xlabel),y轴边上是什么(ylabel),y轴的大小和可视面积(xlim),最后我们把它保存成图片。

  • 注意,这里要注意, matplotlib并没有包含中文字体,所以如果你想打中文上图片,便会出现方块而不是我们要的文字,所以你需要调用本地的 tff字体文件,让他打出中文!

数据分析


我们来看看我们辛苦地用 matplotlib渲染后保存在本地的得到的数据图:

pic

(我们得到数据的柱状图)

pic

(我们的数据得到的散点图,点的大小以及x轴位置可以区分他们的大小,可以明显看到他们之间的差别,这里没有标分类名,因为太多了,标了反而看不清,然后我们可以对照上图来看这图的信息)

  • 很清楚的可以看到 剧情片 遥遥领先,说明一个电影若是剧情性很强,他对观众的吸引程度更大,若是编剧在剧情的hook上面花的功夫越多,得到的后期回报(评价)就越大

  • 我们也可以看到 爱情片是评分第二的,排在第一的 剧情片有些定义笼统的成分,但是 爱情片 的定义就相当清楚啦,而爱情片的评分如此重要,一想到排名第一的《肖申克的救赎》没有什么爱情的画面,就感到它是货真价实的剧情片,而诸如《泰坦尼克号》这样的用世纪灾难来烘托男女主人公爱情的片子,确实可以在观众前赚取一份感动,因为看电影且回来豆瓣评分的人多少会有些艺术情节,而爱情是最为炽烈的情感,例如《这个杀手不太冷》里面leon和小萝莉之间的感情就让我痛苦2小时不止,也许他带给你的人生启示或是很多名言台词不多,但是谁都会憧憬一份炽烈的爱情,亚当.斯密在他的《道德情操论》中提出,很多人看到别人的动作会心生感动,怜悯之类的情感,而爱情片就是最好引起观众共鸣的情感,无论什么样的人,什么信仰的人,他都会拥有爱他人的能力。所以电影厂商的大量的充斥明星的商业爱情片(类似韩剧的狗血剧情),但这很可能是电影厂商的一种屯放资金的办法,因为办爱情片至少不会亏的太惨,能够换来下一份好电影的剧本和筹备以及健康的资金流。

  • 排名第三的是 犯罪 类型的,我们可以在榜单上面看到《教父》,《蝙蝠侠》,《无间道》,《两杆大烟枪》这些耳熟能详的影片,而犯罪片的排名这么高,实际上很多的犯罪片都在拍摄社会的另一些不轻易能够看见的地方,大多数人生活的环境不存在太多的打打杀杀,不存在特别的勾心斗角,而观众又对这样的生活猎奇,这是基础的一点,但是这还不足以称之为好片,更不用说名片的,这些出名的 犯罪 类电影都在极力的刻画那些社会阴暗面的破坏者们(犯罪者们),他们在做着“破坏”时心里想着什么,是什么诱发了这极端的举动(往往牵扯的犯罪者的极端的遭遇),这些猎奇会使得片子的回味很长,而且很不同寻常,并且这些犯罪者(如教父)手里拥有的大量的恐怖举动的权利也让人浮想,总之若是影片厂商想出犯罪类型的片子,一定要出的够重口,够传奇,主人公的经历够跌宕,这样便很有可能获得观众的兴趣,引发热议,进而获得成功。

  • 排名第四为 冒险喜剧,其实这也算是两个经久不衰的类型了,因为这两个范围很广,取材也丰富很难进行分析

  • 从这份单子里我们可以看到诸如 悬疑惊悚 这样的片子也会获得很高的评价,说明观众接受重口味的越来越多,很多影片都在寻在强烈的剧情跌宕以及骇人的场景场面,这样的电影是把双刃剑,拍差了很可能永远存放在垃圾桶里 悬疑 被人说 弱智惊悚 被人说 搞笑


同样,这次的项目,我也把它上传了源代码,以后有关数据处理相关的源代码我都放在这里 数据处理

数据分析 返回首页

Designed and built with all the love in the world by the Mr.ALJUN.

@SERVER BY NGINX AND POWER BY DIGITALOCEAN.

© COPYRIGHT BY GAGASALAMER 2015