票房和口碑稱霸國慶檔,用 Python 爬取貓眼評論區看看電影《我和我的家鄉》到底有多牛
- 2020 年 10 月 5 日
- 筆記
今年的國慶檔電影市場的表現還是比較強勢的,兩名主力《我和我的家鄉》和《姜子牙》起到了很好的帶頭作用。
《姜子牙》首日破 2 億,一舉刷新由《哪吒之魔童降世》保持的中國影市動畫電影首日票房紀錄,但因其後續口碑下滑,目前已被《我和我的家鄉》在口碑和票房上實現了全面的超越,如不出意外,《我和我的家鄉》將會是今年國慶檔的最大贏家。
從上圖中我們可以看出《我和我的家鄉》在貓眼上目前有 29.6 萬人評分,總體評分 9.3,可以說是一個相當不錯的成績了,本文我們爬取該片的貓眼電影評論,一起分析下這部影片評論區的內容。
爬取
首先,我們來爬取貓眼電影評論數據,因 PC 端只能看到貓眼上的幾條評論,所以我們要藉助 APP 介面來爬取,介面格式為://m.maoyan.com/mmdb/comments/movie/movieid.json?_v_=yes&offset=15&startTime=xxx
,兩個參數說明如下:
- movieid:網站中每部影片的唯一 id
- startTime:當前頁面中第一條評論的時間,每頁共有 15 條評論
爬取的主要實現程式碼如下:
# 獲取頁面內容
def get_page(url):
headers = {
'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit'
'/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1',
'accept': '*/*'
}
try:
r = requests.get(url, headers=headers)
r.raise_for_status()
return r.text
except requests.HTTPError as e:
print(e)
except requests.RequestException as e:
print(e)
except:
print("出錯了")
# 解析介面返回數據
def parse_data(html):
json_data = json.loads(html)['cmts']
comments = []
# 解析數據並存入數組
try:
for item in json_data:
comment = []
comment.append(item['nickName']) # 昵稱
comment.append(item['cityName'] if 'cityName' in item else '') # 城市
comment.append(item['content'].strip().replace('\n', '')) # 內容
comment.append(item['score']) # 星級
comment.append(item['startTime'])
comment.append(item['time']) # 日期
comment.append(item['approve']) # 贊數
comment.append(item['reply']) # 回複數
if 'gender' in item:
comment.append(item['gender']) # 性別
comments.append(comment)
return comments
except Exception as e:
print(comment)
print(e)
# 保存數據,寫入 csv
def save_data(comments):
filename = 'comments.csv'
dataObject = pd.DataFrame(comments)
dataObject.to_csv(filename, mode='a', index=False, sep=',', header=False, encoding='utf_8_sig')
本文我們爬取了 2w 條左右評論數據,並將爬取的數據保存到了 csv 文件中。
數據分析
評分星級
首先,我們看一下爬取數據中每個評分星級的比例情況,主要實現程式碼如下:
# 評分星級
rates = []
for s in df.iloc[:, 3]:
rates.append(s)
sx = ["五星", "四星", "三星", "二星", "一星"]
sy = [
str(rates.count(5.0) + rates.count(4.5)),
str(rates.count(4.0) + rates.count(3.5)),
str(rates.count(3.0) + rates.count(2.5)),
str(rates.count(2.0) + rates.count(1.5)),
str(rates.count(1.0) + rates.count(0.5))
]
(
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK, width='700px', height='400px'))
.add("", list(zip(sx, sy)), radius=["40%", "70%"])
.set_global_opts(title_opts=opts.TitleOpts(title="評分星級比例", subtitle="數據來源:貓眼電影", pos_left = "left"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%", font_size=12))
).render_notebook()
效果如下:
從圖中我們可以看出:有接近 9 成的人給了該片 5 星,1、2、3 星總共佔比只有 5% 左右,說明該片的品質得到了大部分人的認可。
性別比例
我們接著看評論人中的性別情況,主要實現程式碼如下:
# 性別比例
rates = []
for s in df.iloc[:, 8]:
if s != 1 and s != 2:
s = 3
rates.append(s)
gx = ["男", "女", "未知"]
gy = [
rates.count(1),
rates.count(2),
rates.count(3)
]
(
Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK, width="700px", height="400px"))
.add("", list(zip(gx, gy)))
.set_global_opts(title_opts=opts.TitleOpts(title="性別比例", subtitle="數據來源:貓眼電影", pos_left = "left"))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%", font_size=12))
).render_notebook()
效果如下:
通過上圖我們可以發現:大部分人是比較注重自己的隱私的,沒有顯示自己的性別,通過性別可見的數據,我們可以發現男人和女人在評論區的活躍程度比較接近,女人略高一些。
位置分布
我們再接著看評論人位置分布情況,先看下評論數量前 100 名的位置坐標情況,主要程式碼實現如下:
cities = []
for city in df.iloc[:, 1]:
if city != "":
cities.append(city)
data = Counter(cities).most_common(100)
gx1 = []
gy1 = []
for c in data:
gx1.append(c[0])
gy1.append(c[1])
geo = Geo(init_opts=opts.InitOpts(width="700px", height="400px", theme=ThemeType.DARK, bg_color="#404a59"))
(
geo.add_schema(maptype="china", itemstyle_opts=opts.ItemStyleOpts(color="#323c48", border_color="#111"))
.add("評論數量", list(zip(gx1, gy1)))
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
toolbox_opts=opts.ToolboxOpts,
title_opts=opts.TitleOpts(title="位置分布地理坐標", subtitle="數據來源:貓眼電影", pos_left = "left"),
visualmap_opts=opts.VisualMapOpts(max_=500, is_piecewise=True)
)
).render_notebook()
效果如下:
下面再通過柱狀圖來展示一下評論數量前 15 名的城市,主要程式碼實現如下:
data_top15 = Counter(cities).most_common(15)
gx2 = []
gy2 = []
for c in data_top15:
gx2.append(c[0])
gy2.append(c[1])
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK, width="700px", height="400px"))
.add_xaxis(gx2)
.add_yaxis("", gy2)
.set_global_opts(
title_opts=opts.TitleOpts(title="城市來源 TOP15", subtitle="數據來源:貓眼電影", pos_left = "center")
)
).render_notebook()
效果如下:
通過以上兩圖,我們可以直觀的看出哪些城市的人在該片下的評論數量多少,進而可以相應的了解到其對該片的感興趣程度。
時評數量
我們接著看 24 小時中的評論數量,主要程式碼實現如下:
times = df.iloc[:, 5]
hours = []
for t in times:
hours.append(str(t[11:13]))
hdata = sorted(Counter(hours).most_common())
hx = []
hy = []
for c in hdata:
hx.append(c[0])
hy.append(c[1])
(
Line(init_opts=opts.InitOpts(theme=ThemeType.CHALK, width="700px", height="400px"))
.add_xaxis(hx)
.add_yaxis("", hy, areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="24小時評論數量", subtitle="數據來源:貓眼電影", pos_left = "center")
)
).render_notebook()
效果如下:
從圖中我們可以看出大家在下午 ~ 晚間活躍程度比較高,因 19 左右是晚飯時間,這個時間段評論數量下降也合乎常理。
主要演員
我們接著來看主要演員(包括其飾演的角色)在評論區中被提及的情況,主要程式碼實現如下:
cts_list = df.iloc[:, 2]
cts_str ="".join([str(i) for i in cts_list])
px = ["黃渤", "王寶強", "劉昊然", "葛優", "劉敏濤", "范偉", "張譯", "鄧超", "閆妮", "沈騰", "馬麗"]
py = [cts_str.count("黃渤") + cts_str.count("黃大寶"), cts_str.count("王寶強") + cts_str.count("老唐"),
cts_str.count("劉昊然") + cts_str.count("小秦"), cts_str.count("葛優") + cts_str.count("張北京"),
cts_str.count("劉敏濤") + cts_str.count("玲子"), cts_str.count("范偉") + cts_str.count("老范"),
cts_str.count("張譯") + cts_str.count("姜前方"), cts_str.count("鄧超") + cts_str.count("喬樹林"),
cts_str.count("閆妮") + cts_str.count("閆飛燕"), cts_str.count("沈騰") + cts_str.count("馬亮"),
cts_str.count("馬麗") + cts_str.count("秋霞")]
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.CHALK, width="700px", height="400px"))
.add_xaxis(px)
.add_yaxis("", py)
.set_global_opts(
title_opts=opts.TitleOpts(title="主要演員及其飾演角色被提及次數", subtitle="數據來源:貓眼電影", pos_left = "center")
)
).render_notebook()
效果如下:
從圖中我們可以看出主要演員在評論區出現次數的前三強為:沈騰、范偉和鄧超,進而說明這幾位演員的熱度比較高,在評論區引起了大家廣泛的熱議。
電影單元
我們接著看每個電影單元在評論區被提及的情況,主要程式碼實現如下:
mx = ["天上掉下個UFO", "北京好人", "最後一課", "回鄉之路", "神筆馬亮"]
my = [cts_str.count("天上掉下個UFO"), cts_str.count("北京好人"), cts_str.count("最後一課"), cts_str.count("回鄉之路"), cts_str.count("神筆馬亮")]
(
Bar(init_opts=opts.InitOpts(theme=ThemeType.DARK, width="700px", height="400px"))
.add_xaxis(mx)
.add_yaxis("", my)
.set_global_opts(
title_opts=opts.TitleOpts(title="電影單元被提及次數", subtitle="", pos_left = "center")
)
).render_notebook()
效果如下:
從圖中我們可以看齣電影單元《最後一課》被提及的次數超過了其它幾個單元被提及次數的總和,進而可以看出其熱度比較高,引起了大家的共鳴,有點一枝獨秀的感覺。
詞雲展示
整體詞雲
首先我們來看一下整體評論的詞雲,程式碼實現如下:
cts_list = df.iloc[:, 2]
cts_str ="".join([str(i) for i in cts_list])
stylecloud.gen_stylecloud(text=cts_str, max_words=400,
collocations=False,
font_path="SIMLI.TTF",
icon_name="fas fa-home",
size=800,
output_name="total.png")
Image(filename="total.png")
效果如下:
從圖中我們可以直觀的看出:好看、很好看、值的一看、不錯、最後一課等被提及的次數比較多,說明大多數人對影片是比較滿意,電影單元最後一課熱度比較高、引起了很多人的共鳴。
熱評詞雲
最後,我們看一下熱門評論(點贊多、回復多的評論內容)的詞雲,程式碼實現如下:
hot_str = ""
for index, row in df.iterrows():
content = row[2]
support = row[6]
reply = row[7]
if(support > 30):
hot_str += content
elif (reply > 5):
hot_str += content
stylecloud.gen_stylecloud(text=hot_str, max_words=200,
collocations=False,
font_path="SIMLI.TTF",
icon_name="fas fa-fire",
size=800,
output_name="hot.png")
Image(filename="hot.png")
效果如下:
這個熱門評論的畫風和之前有點不一樣了,最醒目(最大)的辭彙是:UFO、難看、電影倒是沒看、和對象開演前十分鐘分手了… 最後這個不多說了,大家自行體會吧~
因採集的評論數據有限,可能與實際情況存在一定的偏差,大家理性看待即可。
公眾號 Python小二 後台回復 201005 領取源碼。