閑話休題として,特定の映画のレビューを全件取得し,頻出の単語の集計を行います.
ほとんど,コピペと今までのコードの流用です.
本稿は筆者の趣味の塊ですので,ご容赦ください.
#レビュー取得のコード
特定の映画のレビューを1ページ分取得するコードを紹介します.申し訳ありませんが,引用元以上のコードをかける自信がなかったので9割9分コピペです.
def fetch_movie_reviews_per_page(beautiful_soup_object):
"""
Fetch movie reviews per page. Max 10 reviews.
:param beautiful_soup_object:
:return list of dict:
"""
output = []
# 辞書型で格納
review = dict(review_id="",
review_text="",
posted_date="",
rating_score=0)
soup = beautiful_soup_object
# id_urlsのリストを取得(ここを変更しました)
review_idurls = soup.select(".c-media__content > .c-media__text > a")
# レビューのリストを取得
review_texts = soup.select(".p-mark__review")
# 投稿日時のリストを取得
posted_dates = soup.select(".c-media__content > time")
# 評価(星)のリストを取得
rating_scores = soup.select(".c-media__content > div > .c-rating__score")
# レビューがあれば
if review_texts:
# id_urls,レビュー,投稿日時,評価を各々のリストから1ずつ処理
for review_idurl,review_text, posted_date, rating_score in zip(review_idurls,review_texts,posted_dates, rating_scores):
# id_urlsを取得(ここを変更しました)
review_id = review_idurl.attrs['href'].split('/')[-1]
# レビューを取得
review_text = review_text.text.replace("\u3000", "")
# 投稿日時を取得
posted_date = posted_date.get("datetime")
# 評価無しでは0
if rating_score.text == "-":
review['rating_score'] = 0
# 文字列から数値へ
else:
rating_score = float(rating_score.text)
review['rating_score'] = rating_score
review['review_id'] = review_id
review['review_text'] = review_text
review['posted_date'] = posted_date
output.append(review.copy()) # output.append(review)ではすべての要素が同じになるダメ
return output
#頻出単語の集計
今回はMecabで形態素解析を行い,一般名詞に限り頻出単語を集計してみようと思います.
形態素解析は文章を名詞,形容詞等の品詞ごとに分割することで,Mecabはpythonと連携できる形態素解析のオープンソースです.他にjanome,jumanなどがありますが,Mecabが簡単でしたのでしようしました.
Mecabの名前の由来は,開発者の好物が「海藻のメカブだった」ことだそうです.
コードは以下の通りです.
import MeCab
import sys
import re
from collections import Counter
import pandas as pd
# レビューはcsvで出力したので読み込む
df = pd.read_csv('joker_reviews.csv')
# 形態素解析の準備
m = MeCab.Tagger()
items = []
# 1行ずつ解析
for i in range(len(df)):
# 形態素解析
parse = m.parse (df.review_text[i])
# 形態素解析の結果を改行で区切ってリスト化
lines = parse.split('\n')
# 形態素解析の結果を再整理
for line in lines:
# リストの要素を\t・,で区切る
mecab = re.split('[\t,]',line)
items.append(mecab)
# 形態素解析の結果の内を名詞抽出
# 一般名詞をcount
words = [[item[0],1]
for item in items
# 名詞をリストに格納
if (item[0] not in ('EOS', '', 't', 'ー','‼') and
(item[1] == '名詞') and (item[2] == '一般'))]
word_df = pd.DataFrame(words,columns=['一般名詞','count'])
# '一般名詞'ごとに頻度計算
out_df = word_df.groupby(['一般名詞']).sum().reset_index()
頻出単語の集計が終わりましたので,上記の出力結果の頻出単語の上位30位をグラフで示します.
# グラフ描画のためmatplotlibのpyplotをインポート
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
#最大表示列数の指定(ここでは50列を指定)
pd.set_option('display.max_columns', 50)
pd.set_option('display.max_rows', 500)
# ノートブック内で拡大・縮小可能
#%matplotlib notebook
%matplotlib inline
# seabornのスタイルでプロット
sns.set(style="darkgrid", palette="muted", color_codes=True,font=['IPAGothic'])
# 降順に並べる
rank_df = out_df.sort_values('count',ascending=False).reset_index(drop=True)
# 棒グラフを出力-x軸
labels = rank_df.iloc[:30,0].tolist()
x_axis = np.arange(len(labels)) # numpyで横軸を設定
# バーの太さ
height = 0.5
# 5月の棒グラフ
# 図の大きさ
plt.figure(figsize=(15,20))
#plt.ylim(0, 900)
y = rank_df.iloc[:30,1].to_numpy()
plt.barh(x_axis,y[::-1],height=height)
plt.yticks(x_axis,labels[::-1])# ラベル
plt.show()
出力結果
ここからのグラフを見たときの筆者の浅い感想です.
タイトルにもなっている「ジョーカー」が一番多いですね.
あとは,ジョーカーのキャライメージの「悪,狂気,笑い」や「ダーク,ナイト,ヒース」のジョーカーが登場したダークナイトのキーワードがありますね.
意外だったのが「階段」ですね.おそらく,階段でのダンスシーンのことを言ってると思いますが,上位30位に入るほど印象に残ってるとは思いませんでした.
おわりに
今回は,箸休めがてらレビューの抽出・集計を行いました.
次回は年代別で高評価の映画の抽出をします.