僞漫迷用數據假裝看了一遍《復聯4》

寫在前面的話:因爲本人在職,所以沒有充分的時間寫博客,所以經常是寫好整個框架,再陸陸續續的補充修改。所以如果發現什麼錯誤請留言。

這是一個心情愉悅的週六下午,在免費給公司加了幾個小時班後,突然想看電影了,但是作爲一個junior engineer,我怎麼能像那些senior engineer一樣拿着輕鬆賺來毛爺爺去電影院揮霍呢?(看官COS:電影都捨不得看,還說的這麼冠冕堂皇,真特麼屌絲!)
首先我們先來學習一下復聯4的英文名字Avengers: Endgame
Avengers: 復仇者
Endgame:最後階段,尾聲
那麼從這裏開始我們就稱這個電影爲AE吧。
AE上映於xxx年xx月xx日,導演XXX,算了我不編了,自己點擊下方的鏈接進行閱讀吧。
https://movie.ccccc.com/subject/26100958/
反正那幾個演員的名字除了小羅伯特唐尼其他都記不住,因爲這人演的鋼鐵俠據說原型是特斯拉的創始人XXX,好吧,其實記外國人的人名對我來說是有一定困難的。
收,下面正式開始我的用數據看電影之旅。

第一階段 分析項目風險

作爲一個三無人員,我需要自己採集數據,這裏就用爬蟲來抓取豆瓣網的數據吧。在爬取數據之前,需要先看一下網站上數據長什麼樣子,預估一下什麼數據可以爬取到手。
豆瓣截圖_AE
上面這個截圖出自之前的那個介紹鏈接,圖中紅色區域的數據是本次所必須爬取的數據,而黃色的則是Nice to have.
除了這個基本介紹頁面,豆瓣還有一個專門的影評頁面:
https://movie.douban.com/subject/26100958/reviews

豆瓣影評截屏_AE
這裏同樣用紅色和黃色的框框標出了需要爬取的數據。
好的,到這裏第一步的目標就確定了,接下來用工具看一下豆瓣網頁的源碼。
源碼查看1
源碼查看2
從源碼來看基本上設定的目標數據都能夠爬取到,除了那個影評的展開功能,那本次爬取就先不獲取全部影評了。當然,目前的設想也是沒有考量豆瓣網在反爬蟲的技術所做的工作的。(非技術人員可以跳過這個部分了O(∩_∩)O哈哈~)
下面廢話不多說,開始寫爬蟲(寫完才發現豆瓣做了反爬蟲,至今還沒想到如何解決,但是小弟表示不服,這個flag先立在這了····)。

第二階段 數據收集

1. 獲取自己的cookie

在這裏插入圖片描述
打開Chrome,找到開發者工具或者按F12,選到cookie標籤頁,輸入document.cookie即可獲得你自己這個時刻訪問所使用的cookie,這個cookie只有幾分鐘的時效,會經常變,所以每次跑程序之前先獲取一下這個cookie。

2. 爬取home頁面的basic info

首先右鍵download一下這個頁面,這樣的話你在本地就可以看到源碼,方便自己調試。
這裏直接貼上爬取數據的代碼,至於別的代碼可以去我的GitHub上下載。

 # 獲取主頁的的信息
def get_home_info(url):
    html = get_html(url)
    doc = pq(html)
    # movie_name = doc('#content h1 span').text()
    movie = doc('#content h1 span').items()
    movie_info = [x.text() for x in movie]
    final_rate = doc('.ll.rating_num').text()
    total_people = doc('.rating_people span').text()
    rating = doc('.item span').items()
    rating_info = [x.text() for x in rating]
    res = [movie_info, final_rate, total_people, rating_info]
    return res

3. 爬取comments頁面的user,time,comments

這個頁面稍微複雜些,其實最大的問題還是那個只能訪問12頁的問題,希望各位大蝦能夠給點指導意見。(已解決,小樣需要知道怎麼解決的,給個專注,私信告訴你。)

# return a dataframe
def parse_content(html):
    doc = pq(html) 
    users = doc('.avatar a').items()
    users_herf = doc('.avatar a').items()
    comment_votes = doc('.comment-vote span').items()
    comment_time = doc('.comment-time').items()
    comment_content = doc('.comment-item p').items()
    res_df = df(columns=['user_name', 'user_url', 'comment_votes', 'comment_time', 'comment_content'])
    res_df['user_name'] = [u.attr('title') for u in users]
    res_df['user_url'] = [h.attr('href') for h in users_herf]
    res_df['comment_votes'] = [v.text() for v in comment_votes]
    res_df['comment_time'] = [h.attr('title') for h in comment_time]
    res_df['comment_content'] = [v.text() for v in comment_content]
    return res_df

4. 爬取user主頁的basic info

根據前面爬取到的user Home 頁面的URL,再去爬取其的基礎信息,這裏只爬取了用戶註冊的地址。

# Get user's location
def get_user_info(url):
    html = get_html(url)
    doc = pq(html)
    location = doc('.user-info a')
    return location.text(), location.attr('href')

5. 針對主頁的幾個基本信息爬取

這一步其實是個多餘的操作,主頁我需要的信息也不是很多,直接寫死也就好了。
但是你們覺得我會只曾這一部電影的熱度嗎?呵o( ̄︶ ̄)o,年輕人!!!

def get_home_info(url):
    html = get_html(url)
    doc = pq(html)
    # movie_name = doc('#content h1 span').text()
    movie = doc('#content h1 span').items()
    movie_info = [x.text() for x in movie]
    final_rate = doc('.ll.rating_num').text()
    total_people = doc('.rating_people span').text()
    rating = doc('.item span').items()
    rating_info = [x.text() for x in rating]
    res = [movie_info, final_rate, total_people, rating_info]
    return res

第三部分 數據分析

至此,我們獲取了660條評論數據,數據維度包括評論人,評論時間,評論內容,評論地點(用戶的註冊地址)。接下來的操作大部分都會選用在pandas的datafram裏面進行操作。

1. 數據清洗

不要以爲數據少,就不做清洗了。這裏把用戶數據裏沒有填寫的空值都轉換成了other,而有一些寫的是豆瓣二十二島主之類,就把豆瓣這兩個字去除了。因爲這裏不打算做地圖chart,所以只是簡單做了些處理。刪掉了無用列,轉換了時間格式,清洗了用戶註冊的地點數據。

def loc_clean(user_loc):
    print(user_loc.dtype)
    l = user_loc.size
    for i in range(l):
        tmp = re.sub('\s+$', '', str(user_loc[i]))
        if "豆瓣" in tmp:
            user_loc[i] = re.sub("\s+豆瓣(.|\n|[^\x00-\xff])*", "", tmp)
        else:
            user_loc[i] = tmp
    return user_loc

def data_clean(data_df):
    print(data_df.columns)
    data_df.drop(axis=1, labels=['user_url', 'user_loc_url'], inplace=True)
    data_df["commemt_dt"] = data_df["comment_time"].str[0:9]

    data_df["commemt_ts"] = pd.to_datetime(data_df["comment_time"].str[11:], format='%H:%M:%S')

    data_df["comment_time"] = pd.to_datetime(data_df["comment_time"], format='%Y-%m-%d %H:%M:%S')

    data_df["user_loc"].replace(NaN, 'other', inplace=True)
    data_df["user_loc"] = loc_clean(data_df["user_loc"])
    print(data_df.info())
    return data_df

d. 分詞

2. 多維數據分析

首先先用descrip()函數來看一下comment_votes的分佈情況

	votes_se=pd.Series(data_df['comment_votes'])

    pd.plotting.bootstrap_plot(votes_se)
    votes_se.plot()

    plt.show()

在這裏插入圖片描述
在這裏插入圖片描述

metric votes
count 659.000000
mean 699.251897
std 2185.730366
min 0.000000
25% 27.000000
50% 53.000000
75% 236.000000
max 22969.000000

從引導圖中可以看出數據大部分在50左右,不是一個特別標準的正態分佈。
從表中數據上看最高投票數爲22969,從第二個圖裏看至少有兩個這樣的評論,讓我們來看看他是誰,講了啥

	index_list = data_df[data_df.comment_votes >= 22960].index.tolist()
   	for i in index_list:
        print(data_df['user_name'][i])
        print(data_df['comment_time'][i])
        print(data_df['comment_content'][i])

在這裏插入圖片描述
結果有點出乎意料,竟然開頭是這麼簡單的一句話,而且是任何電影都適用的一句話(這裏加粗顯示一下,畢竟人家是冠軍):

“如果你不喜歡這部電影,說明他不是爲你準備的,故事的終章是爲讀過故事的人準備的。。。”

由於第一次爬豆瓣網,技術有限,只是抓了其短評,但是個人覺得這也說明了一些問題,這句話很貼合粉絲的心意呀,爲了向那些不瞭解自己的故事的人證明自己的價值,這句話是內心裏最有力的安慰。
突然想給這篇文章加第一個評論:

如果你看不懂這篇文章,說明他不是爲你準備的,文章的結論是爲學過數據分析技術的人準備的。。。

這裏純屬娛樂,還是歡迎大家吐槽和批評指正的,這是一個言論自由的技術交流平臺,歡迎大家隨便吐槽。

a. 評論時間的分佈情況

在這裏插入圖片描述
從時間上看4月24日上映當日,發表的評論獲得的投票最多,所以想要在豆瓣上發表評論收到更多的vote,可以選擇在第一時間進行影評發表。

b. 評論地點的分佈情況

由於豆瓣的反爬蟲,只能抓取12頁短評,總共240條短評數據。數據不具有代表性,這裏花了三天,嘗試了代理IP,cookie,切換agent等方法,終於想到辦法破解豆瓣12頁數據的現在已經完整的爬取了復聯4全部短評。
這裏講一下豆瓣短評的背景知識,豆瓣提供了一個平臺,用戶可以註冊,登錄對自己感興趣的電影評論和點擊“想看”和“已經看過”,同時用戶也可以對別人的評價進行認可投票(vote)。
畫圖的代碼如下:

def data_analysis_loc(csv):
    data_df = pd.read_csv(csv, header=0, encoding='utf8')
    print(data_df.columns)
    data_df = data_clean(data_df)
    tmp_df = data_df[['comment_votes', 'user_loc']]
    data_grouped = tmp_df.groupby('user_loc')
    # res = pd.DataFrame(data_grouped.sum()).sort_values('comment_votes', ascending=False)
    # label_list = res.index[:10]
    # x_list = res['comment_votes'][:10]
    # p = plt.pie(x_list, labels=label_list, shadow=True, autopct='%.2f')
    # for front in p[1]:
    #     front.set_fontproperties(myfont)
    # plt.title("來自不同地方的短評獲得投票總數統計", fontproperties=myfont)
    # # res.plot.pie(subplots=True, )
    # plt.show()
    # print(res.info())

    tmp_df = data_df[['comment_content', 'user_loc']]
    data_grouped = tmp_df.groupby('user_loc')
    res = pd.DataFrame(data_grouped.count()).sort_values('comment_content', ascending=False)
    print("==" * 30)
    print(res.index)
    print(res.columns)
    label_list = res.index[:10]
    x_list = res['comment_content'][:10]
    print(label_list)
    print(x_list)
    # res.columns = ['user_loc', 'comment_content']
    # res.set_index(['user_loc'], inplace=True)
    # plt.xlabel(x_list, fontproperties=myfont)
    # plt.ylabel(label_list, fontproperties=myfont)
    p = plt.pie(x_list, labels=label_list, shadow=True, autopct='%.2f')
    for front in p[1]:
        front.set_fontproperties(myfont)
    plt.title("不同地方參與短評的人數統計", fontproperties=myfont)
    # res.plot.pie(subplots=True, )
    plt.show()
    print(res.info())

在這裏插入圖片描述在這裏插入圖片描述
上面兩個餅圖,是此次數據的一個統計。從這兩圖裏看出北京上海無論是人數還是獲得的投票數都是最高的,而有一個城市非常有意思,那就是山西太原,他們參與短評的人數都排不進前十名,也就是不到2.24%,而獲得的投票數卻佔了16.64%,同樣現象也發生在南京人身上。
跪求下面請南京人和太原人多多給本文一些評論,這樣我的文章就可以上頭條了。(加粗)

c. 評論內容的詞雲

這裏分爲三個步驟
步驟一: 使用jieba分詞對短評內容進行分詞,製作初版的詞雲。

    for c in data_df["comment_content"]:
    	#這裏選了false是爲了避免重複的詞
        c_words += " ".join(jieba.cut(c, cut_all=False))
        print(c_words)
        all_words.append(" ".join(jieba.cut(c, cut_all=False)))
    data_df["comment_words"]=all_words

這裏選擇鋼鐵俠的靚照作爲背景圖,主要是考慮到配色比較鮮明。
在這裏插入圖片描述
將所有的評論放在一起,得到這樣一個詞雲,可以發現這裏有幾個問題。

  1. 詞語"漫威",“電影”,“我們”等詞語都是沒有意義的。
  2. 副詞、介詞、連詞、助詞這些虛詞沒有去除。
  3. 缺少專有名詞,例如:粉絲喜歡稱
    在這裏插入圖片描述

步驟二: 對短評分詞後的數據進行清洗。
這裏參考一下以下文章,加入一些粉絲創造的詞語,看了之後發現急需一個真粉絲出來一個個解釋下,這些別名都是怎麼回事。
https://baijiahao.baidu.com/s?id=1597535514187562838&wfr=spider&for=pc
https://baijiahao.baidu.com/s?id=1620981295879150934&wfr=spider&for=pc
這裏把寡姐等詞語加入到詞庫後,再對“電影”,“漫威”等詞語進行了過濾,並使用了extract_tags函數對短評進行了關鍵字提取後這纔得到一個勉強能用的詞雲。
下面是代碼和詞雲:

def word_cloud(words, id):
    # new_worlds = " ".join(words)
    # 選了一個鋼鐵俠的照片做了背景圖
    coloring = np.array(Image.open("ironman.jpg"))

    my_wordcloud = WordCloud(background_color="white", max_words=800, mask=coloring,
                             max_font_size=120, random_state=30, scale=2,
                             font_path='c:\windows\fonts\STKAITI.TTF').generate(words)

    image_colors = ImageColorGenerator(coloring)
    plt.imshow(my_wordcloud.recolor(color_func=image_colors))
    plt.imshow(my_wordcloud)
    plt.axis("off")
    plt.show()

    # 保存圖片
    my_wordcloud.to_file('word_cloud_{0}.png'.format(id))


def word_analysis(csv):
    data_df = pd.read_csv(csv, header=0, encoding='utf8')
    print(data_df.columns)
    data_df = data_clean(data_df)
    all_words = list()
    #
    c_words = ''
    # 加載定義詞庫
    jieba.load_userdict('custom_words.txt')
    stop_words=["漫威","電影","復仇者","粉絲","最後","英雄",""]
    for c in data_df["comment_content"]:
        # c = jieba.analyse.extract_tags(c, allowPOS=('ns', 'n', 'vn', 'v', 'nr', 'nz'))
        tmp = jieba.analyse.extract_tags(c)
        for t in tmp:
            if t in stop_words:
                tmp.remove(t)

        c_words += " ".join(tmp)
        # 精準模式分詞
        # c_words += " ".join(jieba.cut(c, cut_all=False))
        # 搜索引擎分詞
        # c_words += " ".join(jieba.cut_for_search(c))
        all_words.append(" ".join(jieba.cut(c, cut_all=False)))
    data_df["comment_words"] = all_words

    word_cloud(c_words, "all_words")

在這裏插入圖片描述

步驟三: 按照不同空間和時間對數據進行分類,分別製作詞雲。

3. 情感分析(待續)

目前已經有全部(總共二十二部電影)短評數據,希望感興趣的大蝦留言一起研究分析。

4. 總結

本文得到三個結論:

  1. 評論的字數不在於長,而在於精。例如使用以下句式造句“xxx是爲懂的人準備的,而不是xxxx,如果xxxx,那麼說明xxxx”
  2. 要想自己的評論得到更多的投票數,請一定要在第一時間發表自己的評論。
  3. 山西太原人和南京人的評論更受歡迎,熱烈歡迎南京人和太原人在下方吐槽我,哈哈哈!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章