什么是生命,這取決於肝臟。——《調音師》影評


 

調音師是一部很有看點的電影,在朋友的安利下看了兩遍!不錯!就是兩遍!我覺得我爬完這個數據還可以再來一遍!

10分鍾的劇情給我反轉反轉再反轉!

是一部人性的劇,最后結局導演給大家留下了一個很懸的疑點:“劇中究竟死了多少人?” !!!

確實,這也成為了大家討論的點。因為有太多的可能性,一個個鏡頭的暗喻,一顆看似有無的樹居然也有那么大的隱含!?我要重新仔細看一遍了!

 

現在說說我爬到數據的過程~主要用了scrapy框架,下面簡單介紹一下他的模塊功能和開發爬蟲的流程:

模塊功能
Scrapy Engine(引擎):
處理整個系統各個模塊間信號
Spiders(爬蟲類):
發起起始的請求,返回request給Scheduler
定義如何爬取一個網站,獲取數據
Scheduler(調度器):
接收引擎發過來的request請求,壓入隊列
引擎需要時,取出request請求,返回給引擎
Downloader(下載器):
接收請求,返回響應
ItemPipeline(管道):
數據后續處理,處理Spiders返回的item.

分析目標站點,測試反爬

創建項目:scrapy startproject <項目名>

明確目標

創建爬蟲:scrapy genspider <爬蟲名> <域名>

保存

上主要代碼!

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author : jin  time :2019/3/3
import pandas as pd
from collections import Counter
from pyecharts import Geo, Bar, Scatter
import jieba
import matplotlib.pyplot as plt
from wordcloud import WordCloud, STOPWORDS
import time

#觀眾地域圖中部分注釋
#attr:標簽名稱(地點)
#value:數值
#visual_range:可視化范圍
#symbol_size:散點的大小
#visual_text_color:標簽顏色
#is_visualmap:是否映射(數量與顏色深淺是否掛鈎)
#maptype:地圖類型

#讀取csv文件(除了詞雲,其它圖表用的源數據)
def read_csv(filename, titles):
    comments = pd.read_csv(filename, names = titles, low_memory = False)

    return comments

#詞雲用的源數據(比較小)
def read_csv1(filename1, titles):
    comments = pd.read_csv(filename1, names = titles, low_memory = False)

    return comments


#觀眾地域排行榜單
def draw_bar(comments):
    data_top20 = Counter(comments['city_name']).most_common(20) #前二十名城市
    bar = Bar('《調音師》觀眾地域排行榜單', '數據來源:Mr.W', title_pos = 'center', width = 1200, height = 600)
    attr, value = bar.cast(data_top20)
    bar.add('', attr, value, is_visualmap = True, visual_range = [0, 4500], visual_text_color = '#fff', is_more_utils = True, is_label_show = True)
    bar.render('G:\\影評\\觀眾地域排行榜單-柱狀圖.html')
    print('觀眾地域排行榜單已完成')


#觀眾評論數量與日期的關系
#必須統一時間格式,不然時間排序還是亂的
def draw_data_bar(comments):
    time1 = comments['time']
    time_data = []
    for t in time1:
        if pd.isnull(t) == False and 'time' not in t: #如果元素不為空
            date1 = t.replace('/', '-')
            date2 = date1.split(' ')[0]
            current_time_tuple = time.strptime(date2, '%Y-%m-%d') #把時間字符串轉化為時間類型
            date = time.strftime('%Y-%m-%d', current_time_tuple) #把時間類型數據轉化為字符串類型
            time_data.append(date)
    data = Counter(time_data).most_common() #data形式[('2019/2/10', 44094), ('2019/2/9', 43680)]
    data = sorted(data, key = lambda data : data[0]) #data1變量相當於('2019/2/10', 44094)各個元組 itemgetter(0)
    bar =Bar('《調音師》觀眾評論數量與日期的關系', '數據來源:Mr.W', title_pos = 'center', width = 1200, height = 600)
    attr, value = bar.cast(data) #['2019/2/10', '2019/2/11', '2019/2/12'][44094, 38238, 32805]
    bar.add('', attr, value, is_visualmap = True, visual_range = [0, 3500], visual_text_color = '#fff', is_more_utils = True, is_label_show = True)
    bar.render('G:\\影評\\觀眾評論日期-柱狀圖.html')
    print('觀眾評論數量與日期的關系已完成')


#觀眾評論數量與時間的關系
#這里data中每個元組的第一個元素要轉化為整數型,不然排序還是亂的
def draw_time_bar(comments):
    time = comments['time']
    time_data = []
    real_data = []
    for t in time:
        if pd.isnull(t) == False and ':' in t:
            time = t.split(' ')[1]
            hour = time.split(':')[0]
            time_data.append(hour)
    data = Counter(time_data).most_common()
    for item in data:
        temp1 = list(item)
        temp2 = int(temp1[0])
        temp3 = (temp2,temp1[1])
        real_data.append(temp3)
    data = sorted(real_data, key = lambda x : x[0])
    bar = Bar('《調音師》觀眾評論數量與時間的關系', '數據來源:Mr.W', title_pos = 'center', width = 1200, height = 600)
    attr, value = bar.cast(data)
    bar.add('', attr, value, is_visualmap = True, visual_range = [0, 3500], visual_text_color = '#fff', is_more_utils = True, is_label_show = True)
    bar.render('G:\\影評\\觀眾評論時間-柱狀圖.html')
    print('觀眾評論數量與時間的關系已完成')


#詞雲,用一部分數據生成,不然數據量有些大,會報錯MemoryError(64bit的python版本不會)
def draw_word_cloud(comments):
    data = comments['comment']
    comment_data = []
    print('由於數據量比較大,分詞這里有些慢,請耐心等待')
    for item in data:
        if pd.isnull(item) == False:
            comment_data.append(item)
    comment_after_split = jieba.cut(str(comment_data), cut_all = False)
    words = ' '.join(comment_after_split)
    stopwords = STOPWORDS.copy()
    stopwords.update({'可以','好看','電影', '非常', '這個', '那個', '因為', '沒有', '所以', '如果', '演員', '這么', '那么', '最后', '就是', '不過', '這個', '一個', '感覺', '這部', '雖然', '不是', '真的', '覺得', '還是', '但是'})
    wc = WordCloud(width = 800, height = 600, background_color = '#000000', font_path = 'simfang', scale = 5, stopwords = stopwords, max_font_size = 200)
    wc.generate_from_text(words)
    plt.imshow(wc)
    plt.axis('off')
    plt.savefig('G:\\影評\\WordCloud.png')
    plt.show()

#觀眾評分排行榜單
def draw_score_bar(comments):
    score_list = []
    data_score = Counter(comments['score']).most_common()
    for item in data_score:
        if item[0] != 'score':
            score_list.append(item)
    data = sorted(score_list, key = lambda x : x[0])
    bar = Bar('《調音師》觀眾評分排行榜單', '數據來源:Mr.W', title_pos = 'center', width = 1200, height = 600)
    attr, value = bar.cast(data)
    bar.add('', attr, value, is_visualmap = True, visual_range = [0, 4500], visual_text_color = '#fff', is_more_utils = True, is_label_show = True)
    bar.render('G:\\影評\\觀眾評分排行榜單-柱狀圖.html')
    print('觀眾評分排行榜單已完成')


#觀眾用戶等級排行榜單
def draw_user_level_bar(comments):
    level_list = []
    data_level = Counter(comments['user_level']).most_common()
    for item in data_level:
        if item[0] != 'user_level':
            level_list.append(item)
    data = sorted(level_list, key = lambda x : x[0])
    bar = Bar('《調音師》觀眾用戶等級排行榜單', '數據來源:Mr.W', title_pos = 'center', width = 1200, height = 600)
    attr, value = bar.cast(data)
    # is_more_utils = True 提供更多的實用工具按鈕
    bar.add('', attr, value, is_visualmap = True, visual_range = [0, 4500], visual_text_color = '#fff', is_more_utils = True, is_label_show = True)
    bar.render('G:\\影評\\觀眾用戶等級排行榜單-柱狀圖.html')
    print('觀眾用戶等級排行榜單已完成')


if __name__ == '__main__':
    filename = 'G:\\info.csv'
    filename2 = 'G:\\info.csv'
    titles = ['city_name','comment','user_id','nick_name','score','time','user_level']
    comments = read_csv(filename, titles)
    comments2 = read_csv1(filename2, titles)
    draw_map(comments)
    draw_bar(comments)
    draw_data_bar(comments)
    draw_time_bar(comments)
    draw_word_cloud(comments2)
    draw_score_bar(comments)
    draw_user_level_bar(comments)

  

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

import pandas as pd
class MaoyanPipeline(object):
    def process_item(self, item, spider):
        dict_info = {'city': item['city'], 'content': item['content'], 'user_id': item['user_id'],
                     'nick_name': item['nick_name'],
                     'score': item['score'], 'time': item['time'], 'user_level': item['user_level']}
        try:
            data = pd.DataFrame(dict_info, index=[0])  # 為data創建一個表格形式 ,注意加index = [0]
            data.to_csv('G:\info.csv', header=False, index=True, mode='a',
                        encoding='utf_8_sig')  # 模式:追加,encoding = 'utf-8-sig'
        except Exception as error:
            print('寫入文件出錯-------->>>' + str(error))
        else:
            print(dict_info['content'] + '---------->>>已經寫入文件')

  

# -*- coding: utf-8 -*-
import scrapy
import random
from scrapy.http import Request
import datetime
import json
from maoyan.items import MaoyanItem

class CommentSpider(scrapy.Spider):
    name = 'comment'
    allowed_domains = ['maoyan.com']

    thisua = random.choice(uapools)
    header = {'User-Agent': thisua}
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    current_time = '2019-04-03 11:20:49'
    end_time = '2019-04-03 00:18:00'  # 電影上映時間
    url = 'http://m.maoyan.com/mmdb/comments/movie/1239544.json?_v_=yes&offset=0&startTime=' +current_time.replace(' ','%20')

    def start_requests(self):
        current_t = str(self.current_time)
        if current_t > self.end_time:
            try:
                yield Request(self.url, headers=self.header, callback=self.parse)
            except Exception as error:
                print('請求1出錯-----' + str(error))
        else:
            print('全部有關信息已經搜索完畢')

    def parse(self, response):
        item = MaoyanItem()
        data = response.body.decode('utf-8', 'ignore')
        json_data = json.loads(data)['cmts']
        count = 0
        for item1 in json_data:
            if 'cityName' in item1 and 'nickName' in item1 and 'userId' in item1 and 'content' in item1 and 'score' in item1 and 'startTime' in item1 and 'userLevel' in item1:
                try:
                    city = item1['cityName']
                    comment = item1['content']
                    user_id = item1['userId']
                    nick_name = item1['nickName']
                    score = item1['score']
                    time = item1['startTime']
                    user_level = item1['userLevel']
                    item['city'] = city
                    item['content'] = comment
                    item['user_id'] = user_id
                    item['nick_name'] = nick_name
                    item['score'] = score
                    item['time'] = time
                    item['user_level'] = user_level
                    yield item
                    count += 1
                    if count >= 15:
                        temp_time = item['time']
                        current_t = datetime.datetime.strptime(temp_time, '%Y-%m-%d %H:%M:%S') + datetime.timedelta(
                            seconds=-1)
                        current_t = str(current_t)
                        if current_t > self.end_time:
                            url1 = 'http://m.maoyan.com/mmdb/comments/movie/1239544.json?_v_=yes&offset=0&startTime=' + current_t.replace(
                                ' ', '%20')
                            yield Request(url1, headers=self.header, callback=self.parse)
                        else:
                            print('全部有關信息已經搜索完畢')
                except Exception as error:
                    print('提取信息出錯1-----' + str(error))
            else:
                print('信息不全,已濾除')

  

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

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class MaoyanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    city = scrapy.Field()  # 城市
    content = scrapy.Field()  # 評論
    user_id = scrapy.Field()  # 用戶id
    nick_name = scrapy.Field()  # 昵稱
    score = scrapy.Field()  # 評分
    time = scrapy.Field()  # 評論時間
    user_level = scrapy.Field()  # 用戶等級

  


 

爬出來的大家對這部劇的評分,還是很高的哦~5分居多

這部劇從31號開始點映,3號正式上映以來觀看人數不斷上升,看的人越來越多好評也越來越多,討論的人數也隨着觀看的人數出現了越來越多的可能性和越來越多的猜測。

有的人說“男主最后和醫生賣掉了壞女人,獲得了一筆資金”有的人說“男主最后逃了出來,獲得富婆的贊助來到了外國”,還有的人說“醫生一開始就是想賣了男主,所以男主最后把兩個人都殺了,眼睛也好了”等等。

還有很多人認為男主最后那一棍,不是隨意的,而是憤怒的一棍因為女主不是他喜歡的樣子了,人性最后還是會改變的,等等。

 

 

 

過濾掉了一些無用的詞,后再過濾一開始占榜首的“好看”,最后結果如上圖所示。

男主、結局、反轉、結尾、果然是討論最多的。細心的會發現還有幾個人們討論最多的詞“看見”、“看到”、“應該完全”,根據劇情其實可以推斷出大家更傾向的結局是****(怕沒看過的人覺得我是劇透,我把推斷出的東西寫在后面~~)

 

 

 劇透:慎看

 



 

1、我覺得劇情從這顆樹開始就有種男主自導自演的感覺。男主從一開始眼睛在水里其實就明顯一只不是全部的瞎了,一手捂住壞女人這個動作,覺得男主其實一開始是不是就有一點看得見了。

2、從數據挖出來的一些評論,基本上很多人是認為男主后面視力是恢復了的。

3、那是怎么恢復了的呢?我個人更傾向與男主把壞女人和醫生殺了,然后把他們兩個一起賣掉,拿了錢恢復了視力來到了倫敦。從警察局那里男主想象自己爆出事實的拍攝手法來看和后面樹開始的手法是一樣的,所以可以認為從那開始是男主自己想象的。

4、隱藏節點:片頭那句.....說來話長,咖啡?

礎論據:隱藏節點,電影開始的時候,是以一句說來話長,咖啡?也就是說,本電影節點一以前所以的故事也是由男主講述的,除了蘇菲參與的部分,以及新聞報道等現實能查證的事情以外,別的故事都有可能是男主編造的。

個人觀點不喜勿噴~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM