电影评论爬取与分析

用户电影评论分析

from snapshot_selenium import snapshot as driver

from pyecharts.render import make_snapshot

from pyecharts.globals import CurrentConfig,NotebookType

CurrentConfig.NOTEBOOK_TYPE=NotebookType.JUPYTER_LAB
import pandas as pd
import json

datas=[]

with open("review_final.json","r",encoding="utf-8") as f:
    
    for line in f.readlines():
        data=list(json.loads(line).values())
        datas.append(data)
        
f.close()
import csv
with open('review_final.csv', 'w', encoding='utf-8', newline='') as csvFile:
    csv.writer(csvFile).writerow(['用户id','用户名','评论内容','用户链接','电影id','电影title','电影tag','电影评分','导演','电影类型','国家','片长','发布时间'])
    for rows in datas:
        csv.writer(csvFile).writerow(rows)
df=pd.read_csv('review_final.csv',engine='python',encoding='utf-8')
df.shape
(85692, 13)
df.head(5)
用户id 用户名 评论内容 用户链接 电影id 电影title 电影tag 电影评分 导演 电影类型 国家 片长 发布时间
0 phoebe627 小月 标题和故事的idea大概出自松本清张的《富士山禁恋》,一个有能力的左右逢源的男人的妻子出轨,... https://www.douban.com/people/phoebe627/ 30405087 火口的两人 爱情 7.0 霍建起 ['剧情', '爱情'] 中国大陆 96分钟 2020-03-31 12:04:50
1 yukiyuko 口袋_肥力士 吃饭睡觉聊天打豆豆【误】两位演员的表演都很自然平实,音乐也好听。其实有的时候人和人在一起,做... https://www.douban.com/people/yukiyuko/ 30405087 火口的两人 爱情 7.0 霍建起 ['剧情', '爱情'] 中国大陆 96分钟 2020-03-25 20:16:00
2 luhua 芦哲峰 特别喜欢这没羞没臊的两个人,没日没夜没完没了地做啊做,在床上做,在桌上做,在路边胡同里做,在... https://www.douban.com/people/luhua/ 30405087 火口的两人 爱情 7.0 霍建起 ['剧情', '爱情'] 中国大陆 96分钟 2020-04-01 09:33:19
3 luzhiyu 陆支羽 4.0。两个想过去死的人。 https://www.douban.com/people/luzhiyu/ 30405087 火口的两人 爱情 7.0 霍建起 ['剧情', '爱情'] 中国大陆 96分钟 2020-03-17 01:54:49
4 99556117 八屋 (被开动了贤者模式) https://www.douban.com/people/99556117/ 30405087 火口的两人 爱情 7.0 霍建起 ['剧情', '爱情'] 中国大陆 96分钟 2020-03-23 19:13:52
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 85692 entries, 0 to 85691
Data columns (total 13 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   用户id     85692 non-null  object 
 1   用户名      85685 non-null  object 
 2   评论内容     85691 non-null  object 
 3   用户链接     85692 non-null  object 
 4   电影id     85692 non-null  int64  
 5   电影title  85692 non-null  object 
 6   电影tag    85692 non-null  object 
 7   电影评分     85692 non-null  float64
 8   导演       85692 non-null  object 
 9   电影类型     85692 non-null  object 
 10  国家       85692 non-null  object 
 11  片长       85692 non-null  object 
 12  发布时间     83504 non-null  object 
dtypes: float64(1), int64(1), object(11)
memory usage: 8.5+ MB
df.index=range(len(df))

1.用户评论次数分析

df['用户id'].value_counts()
qijiuzhiyue     731
luzhiyu         578
ifanmu          564
lingrui1995     558
3540441         475
               ... 
23260274          1
168654517         1
zxc_suki          1
qingyewuchen      1
65507794          1
Name: 用户id, Length: 17959, dtype: int64
x=list(df['用户id'].value_counts().index)[:10]
x
['qijiuzhiyue',
 'luzhiyu',
 'ifanmu',
 'lingrui1995',
 '3540441',
 'zhangzongqian',
 'ruo1996',
 'tjz230',
 'diewithme',
 'xilouchen']
y=list(df['用户名'].value_counts().head(10))
y
[731, 578, 564, 558, 475, 462, 428, 418, 413, 356]
data_pairs=[i for i in zip(x,y)]
from pyecharts import options as opts
from pyecharts.charts import Pie

p1=(
    Pie(init_opts=opts.InitOpts(width="1000px",height="600px"))
    .add(
        series_name="用户评论数量",
        data_pair=data_pairs
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="用户评论次数分析"),
        legend_opts=opts.LegendOpts(type_="scroll",pos_left="80%",orient="vertical")
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}"))
)
make_snapshot(driver,p1.render("Top10-user.html"),"Top10-user.png")

2.用户观看电影类型分析

user=df[df['用户id']==x[0]]
user['电影类型'].index
Int64Index([  167,   182,   234,   300,   475,   510,   527,   540,   664,
              775,
            ...
            82568, 82803, 83268, 83584, 84110, 84198, 84446, 84505, 85283,
            85410],
           dtype='int64', length=731)
user['电影类型']
167                  ['剧情', '爱情']
182      ['剧情', '喜剧', '悬疑', '犯罪']
234                  ['爱情', '动画']
300                  ['剧情', '爱情']
475            ['剧情', '动作', '冒险']
                   ...           
84198                ['动作', '奇幻']
84446                ['动作', '奇幻']
84505                ['动作', '奇幻']
85283          ['喜剧', '动作', '动画']
85410          ['喜剧', '动作', '动画']
Name: 电影类型, Length: 731, dtype: object
user_type=user.loc[:,'电影类型']
x=user_type.value_counts()
x
['剧情', '喜剧']          50
['剧情', '家庭']          47
['剧情']                42
['动作', '科幻', '冒险']    37
['剧情', '爱情']          33
                      ..
['爱情', '动画']           1
['悬疑', '惊悚', '恐怖']     1
['剧情', '传记']           1
['剧情', '动作']           1
['科幻', '恐怖']           1
Name: 电影类型, Length: 82, dtype: int64
res="".join(list(x.index))
res
"['剧情', '喜剧']['剧情', '家庭']['剧情']['动作', '科幻', '冒险']['剧情', '爱情']['动作', '科幻', '奇幻', '冒险']['动作', '科幻', '动画', '冒险']['剧情', '爱情', '战争']['喜剧', '爱情']['剧情', '动画', '冒险']['动作', '奇幻']['剧情', '喜剧', '传记']['喜剧', '动作', '犯罪']['剧情', '同性', '音乐', '传记']['爱情', '动画', '奇幻']['动作', '惊悚', '冒险']['剧情', '爱情', '悬疑', '战争']['剧情', '家庭', '犯罪']['科幻', '悬疑', '惊悚']['喜剧', '动作', '冒险']['剧情', '悬疑', '犯罪']['喜剧', '动作', '悬疑', '犯罪']['科幻', '惊悚']['动作', '惊悚', '犯罪']['喜剧', '动作']['剧情', '爱情', '同性']['剧情', '喜剧', '冒险']['剧情', '犯罪']['动作']['剧情', '惊悚', '犯罪']['惊悚', '恐怖']['科幻', '惊悚', '恐怖']['喜剧']['剧情', '家庭', '传记']['爱情']['动画', '奇幻']['喜剧', '动画', '奇幻']['喜剧', '爱情', '奇幻']['剧情', '喜剧', '爱情', '战争']['剧情', '喜剧', '动画', '奇幻']['动作', '犯罪']['动作', '惊悚']['剧情', '传记', '犯罪']['喜剧', '动画', '奇幻', '冒险']['喜剧', '惊悚', '奇幻', '冒险']['科幻', '悬疑', '犯罪']['剧情', '悬疑', '恐怖']['喜剧', '动画', '冒险']['动画']['科幻', '冒险', '灾难']['动作', '奇幻', '冒险']['剧情', '爱情', '情色', '传记']['动作', '悬疑', '奇幻', '武侠', '古装']['剧情', '悬疑']['动作', '灾难']['剧情', '动作', '冒险']['剧情', '喜剧', '动作']['剧情', '动作', '武侠']['剧情', '爱情', '情色']['动作', '恐怖']['恐怖']['惊悚', '犯罪']['剧情', '动作', '科幻', '动画']['剧情', '科幻', '动画']['动作', '动画', '犯罪']['喜剧', '动作', '动画']['剧情', '喜剧', '悬疑', '犯罪']['喜剧', '爱情', '家庭']['科幻', '动画']['喜剧', '同性']['剧情', '惊悚', '历史']['喜剧', '动作', '奇幻', '冒险']['喜剧', '情色']['动作', '战争']['动作', '动画', '冒险']['动作', '动画', '家庭']['奇幻', '古装']['爱情', '动画']['悬疑', '惊悚', '恐怖']['剧情', '传记']['剧情', '动作']['科幻', '恐怖']"
import re

pattern=re.compile(r'\w+')

s=pattern.findall(res)
from collections import Counter

res=Counter(s)
x=[]

y=[]

for k,v in res.items():
    x.append(k)
    y.append(v)
data_pairs=[]

for k,v in res.items():
    data_pairs.append((k,v))
data_pairs
[('剧情', 32),
 ('喜剧', 23),
 ('家庭', 5),
 ('动作', 28),
 ('科幻', 12),
 ('冒险', 15),
 ('爱情', 13),
 ('奇幻', 13),
 ('动画', 17),
 ('战争', 4),
 ('传记', 6),
 ('犯罪', 13),
 ('同性', 3),
 ('音乐', 1),
 ('惊悚', 12),
 ('悬疑', 10),
 ('恐怖', 7),
 ('灾难', 2),
 ('情色', 3),
 ('武侠', 2),
 ('古装', 2),
 ('历史', 1)]
from pyecharts import options as opts
from pyecharts.charts import Bar

b1=(
    Bar(init_opts=opts.InitOpts(width="1000px",height="600px"))
    .add_xaxis(x)
    .add_yaxis("电影类型次数",y)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="用户观看电影类型分析"),
        datazoom_opts=opts.DataZoomOpts(),
    )
)
make_snapshot(driver,b1.render("User_movie.html"),"User_movie.png")

3.用户某个电影分析

users=list(df['用户id'].value_counts().index)[:10]
users
['qijiuzhiyue',
 'luzhiyu',
 'ifanmu',
 'lingrui1995',
 '3540441',
 'zhangzongqian',
 'ruo1996',
 'tjz230',
 'diewithme',
 'xilouchen']
user_1=df[df['用户id']==users[0]]
user_1['电影title'].value_counts()
阴曹使者           36
好莱坞往事          20
星球大战9:天行者崛起    20
刺猬的优雅          20
第一滴血5:最后的血     20
               ..
一百样东西           2
朋克武士            2
大人物             1
虽然只是弄丢了手机       1
我的100分男友        1
Name: 电影title, Length: 65, dtype: int64
user_1=df[df['用户id']==users[0]]
user_1[user_1['电影title']=='阴曹使者'].info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 36 entries, 922 to 84505
Data columns (total 13 columns):
 #   Column   Non-Null Count  Dtype  
---  ------   --------------  -----  
 0   用户id     36 non-null     object 
 1   用户名      36 non-null     object 
 2   评论内容     36 non-null     object 
 3   用户链接     36 non-null     object 
 4   电影id     36 non-null     int64  
 5   电影title  36 non-null     object 
 6   电影tag    36 non-null     object 
 7   电影评分     36 non-null     float64
 8   导演       36 non-null     object 
 9   电影类型     36 non-null     object 
 10  国家       36 non-null     object 
 11  片长       36 non-null     object 
 12  发布时间     36 non-null     object 
dtypes: float64(1), int64(1), object(11)
memory usage: 3.9+ KB
comment="".join(user_1['评论内容'].to_list())
pattern = re.compile(r"[^a-zA-Z0-9\u4e00-\u9fa5]")
comment = pattern.sub('',comment)
import jieba
from pyecharts import options as opts
from pyecharts.charts import WordCloud
def split_word(comment):
    
    word_list=list(jieba.cut(comment))
    
    with open("stop_words.txt",encoding="utf-8") as f:
        meaningless_word=f.read().splitlines()
        
    result=[]
    
    for i in word_list:
        if i not in meaningless_word:
            result.append(i.replace(" ",""))
            
    return result

def word_counter(words):
    
    words_counter=Counter(words)
    
    words_list=words_counter.most_common(100)
    
    return words_list


def word_cloud(data):
    
    w=(
        WordCloud()
        .add(
            series_name="用户评论词云",
            data_pair=data,
            word_size_range=[10,120],
            shape="cursive"
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="用户评论",title_textstyle_opts=opts.TextStyleOpts(font_size=23)),
            tooltip_opts=opts.TooltipOpts(is_show=True)
        )
    )
    
    return w

def main():
    
    words=split_word(comment)
    
    data=word_counter(words)
    
    w=word_cloud(data)
    
    return w

if __name__=="__main__":
    
    w1=main()
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\lenovo\AppData\Local\Temp\jieba.cache
Loading model cost 1.450 seconds.
Prefix dict has been built successfully.
make_snapshot(driver,w1.render('User_word.html'),"User_word.png")

4.电影评论客观词云分析

df['电影title'].value_counts()
阴曹使者        4740
秦明·生死语者     2400
刺猬的优雅       2380
路边野餐        2320
幻视          1780
            ... 
生日乐园         540
我的100分男友     240
一百样东西        240
少林寺十八罗汉       60
龙牌之谜          60
Name: 电影title, Length: 71, dtype: int64
comment1=df[df["电影title"]=="阴曹使者"]
comment1="".join(set(comment1['评论内容'].to_list()))
pattern = re.compile(r"[^a-zA-Z0-9\u4e00-\u9fa5]")
comment1 = pattern.sub('',comment1)
def split_word(comment):
    
    word_list=list(jieba.cut(comment))
    
    with open("stop_words.txt",encoding="utf-8") as f:
        meaningless_word=f.read().splitlines()
        
    result=[]
    
    for i in word_list:
        if i not in meaningless_word:
            result.append(i.replace(" ",""))
            
    return result

def word_counter(words):
    
    words_counter=Counter(words)
    
    words_list=words_counter.most_common(200)
    
    return words_list


def word_cloud(data):
    
    w=(
        WordCloud()
        .add(
            series_name="电影评论客观词云",
            data_pair=data,
            word_size_range=[10,120],
            shape="cursive"
        )
        .set_global_opts(
            title_opts=opts.TitleOpts(title="电影评论客观词云",title_textstyle_opts=opts.TextStyleOpts(font_size=23)),
            tooltip_opts=opts.TooltipOpts(is_show=True)
        )
    )
    
    return w

def main():
    
    words=split_word(comment1)
    
    data=word_counter(words)
    
    w=word_cloud(data)
    
    return w

if __name__=="__main__":
    
    w2=main()
make_snapshot(driver,w2.render('Movie_word.html'),"Movie_word.png")

5.用户观看电影类别分析

movie_type=df['国家'].value_counts()
x=list(movie_type.index)[:10]
y=movie_type.to_list()[:10]
x
[' 美国',
 ' 日本',
 ' 韩国',
 ' 中国大陆',
 ' 美国 / 英国',
 ' 英国 / 法国',
 ' 美国 / 中国大陆',
 ' 法国',
 ' 美国 / 新西兰',
 ' 西班牙']
y
[18680, 15600, 13362, 11590, 2800, 1680, 1680, 1620, 1620, 1560]
data_pairs=[z for z in zip(x,y)]
from pyecharts import options as opts
from pyecharts.charts import Funnel

f1=(
    Funnel()
    .add(
        series_name="",
        data_pair=data_pairs
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="电影国家比重"),
        legend_opts=opts.LegendOpts(type_="scroll",pos_left="0%",pos_top="20%",orient="vertical")
    )
)
make_snapshot(driver,f1.render("电影国家比重.html"),"电影国家比重.png")

6.电影月份评分

data=df.dropna()
data.index=range(len(data))
def Month(s):
    
    s=s.split('-')
    
    if s[1]=="01":
        return "一月"
    elif s[1]=="02":
        return "二月"
    elif s[1]=="03":
        return "三月"
    else:
        return "四月"
data["电影月份"]=data["发布时间"].apply(Month)
E:\Anaconda\envs\mypython\lib\site-packages\ipykernel_launcher.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  """Entry point for launching an IPython kernel.
month_one=data[data['电影月份']=="一月"]["电影评分"]
one_result=float(sum(month_one.to_list())/len(month_one.to_list()))
one_result=float(str(one_result)[:4])
one_result
6.91
month_one=data[data['电影月份']=="一月"]["电影评分"]
one_result=float(sum(month_one.to_list())/len(month_one.to_list()))
month=["一月","二月","三月","四月"]

def average_rate():
    
    rate=[]
    
    for i in month:
        month_res=data[data['电影月份']==i]["电影评分"]
        result=float(sum(month_res.to_list())/len(month_res.to_list()))
        
        result=float(str(result)[:4])
        
        rate.append(result)
        
    return rate
        
    
rate=average_rate()
month
['一月', '二月', '三月', '四月']
rate
[6.91, 6.97, 6.88, 6.85]
from pyecharts import options as opts
from pyecharts.charts import Line

l1=(
    Line(init_opts=opts.InitOpts(width="1000px",height="600px"))
    .add_xaxis(month)
    .add_yaxis("电影评分",rate)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="评分")
    )
)
make_snapshot(driver,l1.render("每月评分.html"),"每月评分.png")

7.电影类别评分

types=df['电影tag'].value_counts()
x=list(types.index)
y=types.to_list()
from pyecharts import options as opts
from pyecharts.charts import Pie

p2=(
    Pie()
    .add("电影Tag",
         [z for z in zip(x,y)]
        )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="电影类别统计"),
        legend_opts=opts.LegendOpts(type_="scroll",pos_left="80%",orient="vertical")
    )
    .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{c}"))
)
make_snapshot(driver,p2.render("电影类别统计.html"),"电影类别统计.png")

8.各种电影评分

def average_rate():
    
    rate=[]
    
    for i in x:
        month_res=df[df['电影tag']==i]["电影评分"]
        result=float(sum(month_res.to_list())/len(month_res.to_list()))
        
        result=float(str(result)[:4])
        
        rate.append(result)
        
    return rate
rate=average_rate()
rate
[5.82,
 8.42,
 6.85,
 6.9,
 7.39,
 6.04,
 6.57,
 5.5,
 6.25,
 8.84,
 8.29,
 5.0,
 5.74,
 6.58,
 9.25,
 6.89]
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.faker import Faker

p3 = (
    Pie()
    .add(
        "",
        [list(z) for z in zip(x,rate)],
        radius=["40%", "55%"],
        label_opts=opts.LabelOpts(
            position="outside",
            formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}: }{c}  {per|{d}%}  ",
            background_color="#eee",
            border_color="#aaa",
            border_width=1,
            border_radius=4,
            rich={
                "a": {"color": "#999", "lineHeight": 22, "align": "center"},
                "abg": {
                    "backgroundColor": "#e3e3e3",
                    "width": "100%",
                    "align": "right",
                    "height": 22,
                    "borderRadius": [4, 4, 0, 0],
                },
                "hr": {
                    "borderColor": "#aaa",
                    "width": "100%",
                    "borderWidth": 0.5,
                    "height": 0,
                },
                "b": {"fontSize": 16, "lineHeight": 33},
                "per": {
                    "color": "#eee",
                    "backgroundColor": "#334455",
                    "padding": [2, 4],
                    "borderRadius": 2,
                },
            },
        ),
    )
    .set_global_opts(
        title_opts=opts.TitleOpts(title="电影类别平均评分"),
        legend_opts=opts.LegendOpts(type_="scroll",pos_left="0%",pos_top="20%",orient="vertical"),
        toolbox_opts=opts.ToolboxOpts(is_show=True)
    )
)
make_snapshot(driver,p3.render('电影类别平均评分.html'),"电影类别平均评分.png")

类别柱状图

from pyecharts import options as opts
from pyecharts.charts import Bar

b2=(
    Bar(init_opts=opts.InitOpts(width="1000px",height="600px"))
    .add_xaxis(x)
    .add_yaxis("电影Tag",rate)
    .set_global_opts(
        title_opts=opts.TitleOpts(title="电影Tag评分"),
        datazoom_opts=opts.DataZoomOpts(),
    )
)
make_snapshot(driver,b2.render('电影Tag2.html'),"电影Tag2.png")

9.电影导演分析

df["导演"].value_counts()
安东尼·明格拉     2800
是枝裕和        2520
福田雄一        2500
金容华         2460
鲍勃·佩尔西凯蒂    1900
            ... 
彼得·博格         60
森义隆           40
郑建国           40
欧·帕克          40
J·A·巴亚纳       20
Name: 导演, Length: 158, dtype: int64
x=list(df["导演"].value_counts().index)[:10]
def average_rate():
    
    rate=[]
    
    for i in x:
        month_res=df[df['导演']==i]["电影评分"]
        result=float(sum(month_res.to_list())/len(month_res.to_list()))
        
        result=float(str(result)[:4])
        
        rate.append(result)
        
    return rate
rate=average_rate()
rate
[7.94, 8.0, 6.15, 6.29, 6.65, 7.49, 8.79, 7.0, 6.59, 8.26]
from pyecharts import options as opts
from pyecharts.charts import Line


b3=(
    Bar(init_opts=opts.InitOpts(width="1000px",height="600px"))
    .add_xaxis(x)
    .add_yaxis("电影Tag",rate)
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)),
        title_opts=opts.TitleOpts(title="电影导演评分"),
        #datazoom_opts=opts.DataZoomOpts(),
    )
)

make_snapshot(driver,b3.render("导演评分.html"),"导演评分.png")

十.图形合并

from pyecharts.charts import Page

page=Page(layout=Page.DraggablePageLayout)
page.add(p1,b1,w1,w2,f1,l1,p2,p3,b2,b3)
page.render('用户电影评论分析.html')
'F:\\Python\\Pytest\\spider\\movietest2\\用户电影评论分析.html'

代码链接:代码

posted @ 2020-05-21 20:15  LQ6H  阅读(362)  评论(0编辑  收藏  举报