《一出好戲》講述人性,使用Python抓取貓眼近10萬條評論並分析,一起揭秘“這出好戲”到底如何?

來源:互聯網
上載者:User

標籤:ESS   圖形   做了   date   地理   response   arm   鄭州   legend   

黃渤首次導演的電影《一出好戲》自8月10日在全國上映,至今已有10天,其主演陣容強大,相信許多觀眾也都是衝著明星們去的。
目前《一出好戲》在貓眼上已經獲得近60萬個評價,評分為8.2分,票房已破10億。

作者本人(湯小洋 )今天也走進了電影院,對這部電影做了親身的觀看,看完後的感覺是有些許失落的,本以為是喜劇片,結果發現笑點一般,從搞笑的角度來看,不如《西虹市首富》,影片更多的是反映人類本性的一部電影,不應當做喜劇片來看,影片中展現的人與人之間的關係倒是值得我們去深思。

今天就跟著 湯老師 一起來揭秘影片《一出好戲》,看看“這出好戲”到底如何?

我們將使用Python抓取貓眼近10萬條評論資料,並對擷取到的資料進行分析,看看觀眾對這部電影的評價究竟如何?

整個資料分析的過程分為四步:

  1. 擷取資料
  2. 處理資料
  3. 儲存資料
  4. 資料視覺效果
一、擷取資料1. 簡介

? 本次擷取的是貓眼APP的評論資料,:

通過分析發現貓眼APP的評論資料介面為:

http://m.maoyan.com/mmdb/comments/movie/1200486.json?_v_=yes&offset=0&startTime=2018-07-28%2022%3A25%3A03

? 通過對評論資料進行分析,得到如下資訊:

  • 返回的是json格式資料

  • 1200486表示電影的專屬id;offset表示位移量;startTime表示擷取評論的起始時間,從該時間向前取資料,即擷取最新的評論

  • cmts表示評論,每次擷取15條,offset位移量是指每次擷取評論時的起始索引,向後取15條

  • hcmts表示熱門評論前10條

  • total表示總評論數
2. 代碼實現

? 這裡先定義一個函數,用來根據指定url擷取資料,且只能擷取到指定的日期向前擷取到15條評論資料

# coding=utf-8__author__ = ‘湯小洋‘from urllib import requestimport jsonimport timefrom datetime import datetimefrom datetime import timedelta# 擷取資料,根據url擷取def get_data(url):    headers = {        ‘User-Agent‘: ‘Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36‘    }    req = request.Request(url, headers=headers)    response = request.urlopen(req)    if response.getcode() == 200:        return response.read()    return Noneif __name__ == ‘__main__‘:    html = get_data(‘http://m.maoyan.com/mmdb/comments/movie/1200486.json?_v_=yes&offset=0&startTime=2018-07-28%2022%3A25%3A03‘)    print(html)
二、處理資料

對擷取的資料進行處理,轉換為json

# 處理資料def parse_data(html):    data = json.loads(html)[‘cmts‘]  # 將str轉換為json    comments = []    for item in data:        comment = {            ‘id‘: item[‘id‘],            ‘nickName‘: item[‘nickName‘],            ‘cityName‘: item[‘cityName‘] if ‘cityName‘ in item else ‘‘,  # 處理cityName不存在的情況            ‘content‘: item[‘content‘].replace(‘\n‘, ‘ ‘, 10),  # 處理評論內容換行的情況            ‘score‘: item[‘score‘],            ‘startTime‘: item[‘startTime‘]        }        comments.append(comment)    return commentsif __name__ == ‘__main__‘:    html = get_data(‘http://m.maoyan.com/mmdb/comments/movie/1200486.json?_v_=yes&offset=0&startTime=2018-07-28%2022%3A25%3A03‘)    comments = parse_data(html)    print(comments)
三、儲存資料

? 為了能夠擷取到所有評論資料,方法是:從目前時間開始,向前擷取資料,根據url每次擷取15條,然後得到末尾評論的時間,從該時間繼續向前擷取資料,直到影片上映日期(2018-08-10)為止,擷取這之間的所有資料。

# 儲存資料,儲存到文字檔def save_to_txt():    start_time = datetime.now().strftime(‘%Y-%m-%d %H:%M:%S‘)  # 擷取目前時間,從目前時間向前擷取    end_time = ‘2018-08-10 00:00:00‘    while start_time > end_time:        url = ‘http://m.maoyan.com/mmdb/comments/movie/1203084.json?_v_=yes&offset=0&startTime=‘ + start_time.replace(‘ ‘, ‘%20‘)        html = None        ‘‘‘            問題:當請求過於頻繁時,伺服器會拒絕串連,實際上是伺服器的反爬蟲策略            解決:1.在每個請求間增加延時0.1秒,盡量減少請求被拒絕                 2.如果被拒絕,則0.5秒後重試        ‘‘‘        try:            html = get_data(url)        except Exception as e:            time.sleep(0.5)            html = get_data(url)        else:            time.sleep(0.1)        comments = parse_data(html)        print(comments)        start_time = comments[14][‘startTime‘]  # 獲得末尾評論的時間        start_time = datetime.strptime(start_time, ‘%Y-%m-%d %H:%M:%S‘) + timedelta(seconds=-1)  # 轉換為datetime類型,減1秒,避免擷取到重複資料        start_time = datetime.strftime(start_time, ‘%Y-%m-%d %H:%M:%S‘)  # 轉換為str        for item in comments:            with open(‘comments.txt‘, ‘a‘, encoding=‘utf-8‘) as f:                f.write(str(item[‘id‘])+‘,‘+item[‘nickName‘] + ‘,‘ + item[‘cityName‘] + ‘,‘ + item[‘content‘] + ‘,‘ + str(item[‘score‘])+ ‘,‘ + item[‘startTime‘] + ‘\n‘)if __name__ == ‘__main__‘:    # html = get_data(‘http://m.maoyan.com/mmdb/comments/movie/1200486.json?_v_=yes&offset=0&startTime=2018-07-28%2022%3A25%3A03‘)    # comments = parse_data(html)    # print(comments)    save_to_txt()

? 有兩點需要說明:

  1. 伺服器一般都有反爬蟲策略,當請求過於頻繁時,伺服器會拒絕部分串連,我這裡是通過增加每個請求間延時來解決,只是一種簡單的解決方案,還望各位看客理解包涵
  2. 根據資料量的多少,抓取資料所需時間會有所不同,我抓取的是2018-8-19到2018-8-10(上映當天)之間的資料,大概花了2個小時,共抓取約9.2萬條評論資料

四、資料視覺效果

? 這裡使用的是pyecharts,pyecharts是一個用於產生Echarts圖表的類庫,便於在Python中根據資料產生可視化的圖表。

? Echarts是百度開源的一個資料視覺效果JS庫,主要用於資料視覺效果。

? 參考:http://pyecharts.org/

# 安裝pyechartspip install pyecharts 

? pyecharts v0.3.2以後,pyecharts 將不再內建地圖 js 檔案。如使用者需要用到地圖圖表,可自行安裝對應的地圖檔案包。

# 安裝地圖檔案包pip install echarts-china-provinces-pypkg # 中國省、市、縣、區地圖pip install echarts-china-cities-pypkgpip install echarts-china-counties-pypkgpip install echarts-china-misc-pypkg pip install echarts-countries-pypkg # 全球國家地圖pip install echarts-united-kingdom-pypkg
1. 粉絲位置分布

? 代碼實現

# 匯入Style類,用於定義樣式風格from pyecharts import Style# 匯入Geo組件,用於產生地理座標類圖from pyecharts import Geoimport json# 匯入Geo組件,用於產生柱狀圖from pyecharts import Bar# 匯入Counter類,用於統計值出現的次數from collections import Counter# 資料視覺效果def render():    # 擷取評論中所有城市    cities = []    with open(‘comments.txt‘, mode=‘r‘, encoding=‘utf-8‘) as f:        rows = f.readlines()        for row in rows:            city = row.split(‘,‘)[2]            if city != ‘‘:  # 去掉城市名為空白的值                cities.append(city)    # 對城市資料和座標檔案中的地名進行處理    handle(cities)    # 統計每個城市出現的次數    # data = []    # for city in set(cities):    #     data.append((city, cities.count(city)))    data = Counter(cities).most_common()  # 使用Counter類統計出現的次數,並轉換為元組列表    # print(data)    # 定義樣式    style = Style(        title_color=‘#fff‘,        title_pos=‘center‘,        width=1200,        height=600,        background_color=‘#404a59‘    )    # 根據城市資料產生地理座標圖    geo = Geo(‘《一出好戲》粉絲位置分布‘, ‘資料來源:貓眼-湯小洋採集‘, **style.init_style)    attr, value = geo.cast(data)    geo.add(‘‘, attr, value, visual_range=[0, 3500],            visual_text_color=‘#fff‘, symbol_size=15,            is_visualmap=True, is_piecewise=True, visual_split_number=10)    geo.render(‘粉絲位置分布-地理座標圖.html‘)    # 根據城市資料產生柱狀圖    data_top20 = Counter(cities).most_common(20)  # 返回出現次數最多的20條    bar = Bar("《一出好戲》粉絲來源排行TOP20", "資料來源:貓眼-湯小洋採集", title_pos=‘center‘, width=1200, height=60)    attr, value = bar.cast(data_top20)    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("粉絲來源排行-柱狀圖.html")

? 出現的問題:

  • 報錯:ValueError: No coordinate is specified for xxx(地名)

  • 原因:pyecharts的座標檔案中沒有該地名,實際上是名稱不一致導致的,如資料中地名為‘達州‘,而座標檔案中為‘達州市‘

    座標檔案所在路徑:項目/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json

  • 解決:修改座標檔案,在原位置下複製個同樣的,然後修改下地名
{  "達州市": [    107.5,    31.22  ],   "達州": [    107.5,    31.22  ],}    

? 不過由於要修改的地名太多,上面的方法實在是麻煩,所以我定義了一個函數,用來處理地名資料找不到的問題

# 處理地名資料,解決座標檔案中找不到地名的問題def handle(cities):    # print(len(cities), len(set(cities)))    # 擷取座標檔案中所有地名    data = None    with open(            ‘/Users/wangbo/PycharmProjects/python-spider/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json‘,            mode=‘r‘, encoding=‘utf-8‘) as f:        data = json.loads(f.read())  # 將str轉換為json    # 迴圈判斷處理    data_new = data.copy()  # 拷貝所有地名資料    for city in set(cities):  # 使用set去重        # 處理地名為空白的資料        if city == ‘‘:            while city in cities:                cities.remove(city)        count = 0        for k in data.keys():            count += 1            if k == city:                break            if k.startswith(city):  # 處理簡寫的地名,如 達州市 簡寫為 達州                # print(k, city)                data_new[city] = data[k]                break            if k.startswith(city[0:-1]) and len(city) >= 3:  # 處理行政變更的地名,如縣改區 或 縣改市等                data_new[city] = data[k]                break        # 處理不存在的地名        if count == len(data):            while city in cities:                cities.remove(city)    # print(len(data), len(data_new))    # 寫入覆蓋座標檔案    with open(            ‘/Users/wangbo/PycharmProjects/python-spider/venv/lib/python3.6/site-packages/pyecharts/datasets/city_coordinates.json‘,            mode=‘w‘, encoding=‘utf-8‘) as f:        f.write(json.dumps(data_new, ensure_ascii=False))  # 將json轉換為str

可視化結果:

粉絲人群主要集中在沿海一帶

從可以看出,《一出好戲》的觀影人群主要集中在沿海一帶,這些地方經濟相對發達,城市人口基數龐大,極多的熒幕數量和座位、極高密度的排片場次,讓觀眾便捷觀影,活躍的觀眾評論也多,自然也就成為票房的主要貢獻者。

粉絲來源排名前20的城市依次為:北京、深圳、上海、成都、武漢、廣州、西安、鄭州、重慶、南京、天津、瀋陽、長沙、東莞、哈爾濱、青島、杭州、合肥、大連、蘇州

電影消費是城市消費的一部分,從某種角度來看,可以作為考察一個城市購買力的指標。這些城市在近年的GDP排行中大都居上遊,消費水平較高。

2. 詞雲圖

? jieba是一個基於Python的分詞庫,完美支援中文分詞,功能強大

pip install jieba

? Matplotlib是一個Python的2D繪圖庫,能夠產生高品質的圖形,可以快速產生繪圖、長條圖、功率譜、柱狀圖、誤差圖、散佈圖等

pip install matplotlib

? wordcloud是一個基於Python的詞雲產生類庫,可以產生詞雲圖

pip install wordcloud

? 代碼實現:

# coding=utf-8__author__ = "湯小洋"# 匯入jieba模組,用於中文分詞import jieba# 匯入matplotlib,用於產生2D圖形import matplotlib.pyplot as plt# 匯入wordcount,用於製作詞雲圖from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator# 擷取所有評論comments = []with open(‘comments.txt‘, mode=‘r‘, encoding=‘utf-8‘) as f:    rows = f.readlines()    for row in rows:        comment = row.split(‘,‘)[3]        if comment != ‘‘:            comments.append(comment)# 設定分詞comment_after_split = jieba.cut(str(comments), cut_all=False)  # 非全模式分詞,cut_all=falsewords = " ".join(comment_after_split)  # 以空格進行拼接# print(words)# 設定屏蔽詞stopwords = STOPWORDS.copy()stopwords.add("電影")stopwords.add("一部")stopwords.add("一個")stopwords.add("沒有")stopwords.add("什麼")stopwords.add("有點")stopwords.add("這部")stopwords.add("這個")stopwords.add("不是")stopwords.add("真的")stopwords.add("感覺")stopwords.add("覺得")stopwords.add("還是")stopwords.add("但是")stopwords.add("就是")# 匯入背景圖bg_image = plt.imread(‘bg.jpg‘)# 設定詞雲參數,參數分別表示:畫布寬高、背景顏色、背景圖形狀、字型、屏蔽詞、最大詞的字型大小wc = WordCloud(width=1024, height=768, background_color=‘white‘, mask=bg_image, font_path=‘STKAITI.TTF‘,               stopwords=stopwords, max_font_size=400, random_state=50)# 將分詞後資料傳入雲圖wc.generate_from_text(words)plt.imshow(wc)plt.axis(‘off‘)  # 不顯示座標軸plt.show()# 儲存結果到本地wc.to_file(‘詞雲圖.jpg‘)

可視化結果:

總體評價很不錯

? 對評論資料進行分詞後製作如下詞雲圖:

? 從詞雲圖中可以看到:

  • 評論中多次出現“可以”、“好看”、“不錯”等熱詞,說明觀眾對《一出好戲》的總體評價還是很不錯的
  • 同時對該影片中“張藝興”的“演技”也給予了很大的認可,我本人今天在觀看後也有同感,讓我們看到了不一樣的張藝興,實力演員
  • 對於初次“導演”電影的“黃渤”,能拍出這樣的影片,粉絲們也是比較肯定的,同時其本身就是票房的保障
  • 至於劇情方面,“現實”、“喜劇”、“搞笑”、“故事”等詞語,能看出這是一部反映現實的故事片,同時也兼具喜劇搞笑
  • 對於評論中出現的“一般”、“失望”等,這些粉絲或許是和我一樣,本以為這是一部爆笑喜劇片,笑點應該會很多(畢竟在我們心中,黃渤、王寶強等就是諧星),沒想到笑點並不很多,至少與期待的有差距,導致心裡有落差的原因吧^_^

3. 評分星級

? 代碼實現:

# coding=utf-8__author__ = "湯小洋"# 匯入Pie組件,用於產生餅圖from pyecharts import Pie# 擷取評論中所有評分rates = []with open(‘comments.txt‘, mode=‘r‘, encoding=‘utf-8‘) as f:    rows = f.readlines()    for row in rows:        rates.append(row.split(‘,‘)[4])# print(rates)# 定義星級,並統計各星級評等數量attr = ["五星", "四星", "三星", "二星", "一星"]value = [    rates.count(‘5‘) + rates.count(‘4.5‘),    rates.count(‘4‘) + rates.count(‘3.5‘),    rates.count(‘3‘) + rates.count(‘2.5‘),    rates.count(‘2‘) + rates.count(‘1.5‘),    rates.count(‘1‘) + rates.count(‘0.5‘)]# print(value)pie = Pie(‘《一出好戲》評分星級比例‘, title_pos=‘center‘, width=900)pie.add("7-17", attr, value, center=[75, 50], is_random=True,        radius=[30, 75], rosetype=‘area‘,        is_legend_show=False, is_label_show=True)pie.render(‘評分.html‘)

可視化結果:

四、五星級影評合計高達83%

? 可以看出,五星比例接近62%,四星比例為21%,兩者合計高達83%,可見口碑還是相當不錯的,一星佔比不足6%

? 《一出好戲》作為黃渤第一次執導的作品,在拍攝過程中導演渤哥對自己的要求也是很嚴格的,所以有這樣的成績,也是理所當然。

附:今天看電影的票根 ^_^

《一出好戲》講述人性,使用Python抓取貓眼近10萬條評論並分析,一起揭秘“這出好戲”到底如何?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.