Python爬取《流浪地球》豆瓣影评与数据分析

栏目: Python · 发布时间: 7年前

内容简介:编者按猪年春节的贺岁档电影火爆异常,尤其是口碑爆棚的《流浪地球》更是收获的无数影迷和国人的赞誉。事实胜于雄辩,数据是最有力度的事实。我们用python爬取了豆瓣的影评,客观的分析一下这部国产的划时代的科幻电影。事实证明,《流浪地球》是非常值得观看的电影,并且这部电影正在带领中国的科幻产业走向成熟。

编者按

猪年春节的贺岁档电影火爆异常,尤其是口碑爆棚的《流浪地球》更是收获的无数影迷和国人的赞誉。事实胜于雄辩,数据是最有力度的事实。我们用 python 爬取了豆瓣的影评,客观的分析一下这部国产的划时代的科幻电影。事实证明,《流浪地球》是非常值得观看的电影,并且这部电影正在带领中国的科幻产业走向成熟。

大年初一《流浪地球》全国上映。在豆瓣评分上,首日开分站稳8分以上,延续了之前点映的高口碑。微博上跟着出现吴京客串31天与投资6000万的热搜。知乎上关于“如何评价刘慈欣小说改编的同名电影《流浪地球》”的回答引起了众多人关注,包括该片导演郭帆的最高赞回答。

本篇文章爬取了豆瓣网上《流浪地球》的部分影评,并进行数据分析及可视化处理。下面是爬取分析的整个过程,让我们愉快开始吧!

一、网页分析

豆瓣网从2017年10月开始全面禁止爬取数据。在非登录状态下仅仅可以爬取200条短评,登录状态下仅可以爬取500条数据。白天一分钟最多可爬40次,晚上60次,超过次数就会封IP地址。小本聪爬取数据获得400条时被封了IP,账号被强制下线封号,之后发短信账号恢复,因此不建议多次爬取(另外,有很多解决方法,请自行搜索)。

获取对象

  • 评论用户

  • 评论内容

  • 评分

  • 评论日期

  • 用户所在城市

Python爬取《流浪地球》豆瓣影评与数据分析

值得注意的是,在地址栏我们会发现电影名字的ID编号为26266893(其他电影只需更换ID即可),并且每页有20条短评,因此我爬取了20页。评论页面没有用户所在城市,需要进入用户页面获取信息。

Python爬取《流浪地球》豆瓣影评与数据分析

二、数据获取与存储

1  获取cookies

小本聪用的是Chrome浏览器,Ctrl+F12进入开发者 工具 页面。F5刷新一下出现数据,找到cookies、headers。

Python爬取《流浪地球》豆瓣影评与数据分析

2 加载headers、cookies,并用requests库获取信息

def get_content(id, page):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
    cookies = {'cookie': 'bid=GOOb4vXwNcc; douban-fav-remind=1; ps=y; ue="maplekonghou@163.com"; push_noty_num=0; push_doumail_num=0; ap=1; ll="108288"; dbcl2="181095881:BSb6IVAXxCI"; ck=Fd1S; ct=y'}
    url = "https://movie.douban.com/subject/" + str(id) + "/comments?start=" + str(page * 10) + "&limit=20&sort=new_score&status=P"
    res = requests.get(url, headers=headers, cookies=cookies)
3 解析需求数据

此处运用xpath解析。发现有的用户虽然给了评论,但是没有给评分,所以score和date这两个的xpath位置是会变动的。因此需要加判断,如果发现score里面解析的是日期,证明该条评论没有给出评分。

for i in range(1, 21):   # 每页20个评论用户
    name = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/a/text()'.format(i))
    # 下面是个大bug,如果有的人没有评分,但是评论了,那么score解析出来是日期,而日期所在位置spen[3]为空
    score = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/span[2]/@title'.format(i))
    date = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/span[3]/@title'.format(i))
    m = '\d{4}-\d{2}-\d{2}'
    try:
        match = re.compile(m).match(score[0])
    except IndexError:
        break
    if match is not None:
        date = score
        score = ["null"]
    else:
        pass
    content = x.xpath('//*[@id="comments"]/div[{}]/div[2]/p/span/text()'.format(i))
    id = x.xpath('//*[@id="comments"]/div[{}]/div[2]/h3/span[2]/a/@href'.format(i))
    try:
        city = get_city(id[0], i)  # 调用评论用户的ID城市信息获取
    except IndexError:
        city = " "
    name_list.append(str(name[0]))
    score_list.append(str(score[0]).strip('[]\''))  # bug 有些人评论了文字,但是没有给出评分
    date_list.append(str(date[0]).strip('[\'').split(' ')[0])
    content_list.append(str(content[0]).strip())
    city_list.append(city)

4 获取电影名称

从url上只能获取电影的subject的8位ID数值,引起需要自行解析网页获取ID号对应的电影名称,该功能是后期改进添加的,因此为避免现有代码改动多(偷个懒),采用了全局变量赋值给 movie_name ,需要注意全局变量调用时,要加 global 声明一下。

pattern = re.compile('<div id="wrapper">.*?<div id="content">.*?<h1>(.*?) 短评</h1>', re.S)
global movie_name
movie_name = re.findall(pattern, res.text)[0]  # list类型

5 数据存储

由于数据不多,选择CSV存储即可。

def main(ID, pages):
    global movie_name
    for i in tqdm(range(0, pages)):  # 豆瓣只开放500条评论
        get_content(ID, i)  # 第一个<mark data-id="2e982b73-88e2-41e8-a430-f7ae5a9af4bf" data-type="technologies">参数</mark>是豆瓣电影对应的id序号,第二个<mark data-id="2e982b73-88e2-41e8-a430-f7ae5a9af4bf" data-type="technologies">参数</mark>是想爬取的评论页数
        time.sleep(round(random.uniform(3, 5), 2))  # 设置延时发出请求
    infos = {'name': name_list, 'city': city_list, 'content': content_list, 'score': score_list, 'date': date_list}
    data = pd.DataFrame(infos, columns=['name', 'city', 'content', 'score', 'date'])
    data.to_csv(movie_name + ".csv")  # 存储名为 电影名.csv

Python爬取《流浪地球》豆瓣影评与数据分析

三、数据分析与可视化

1  获取cookies

城市信息筛选中文字

def translate(str):
    line = str.strip()
    p2 = re.compile('[^\u4e00-\u9fa5]')   # 中文的编码范围是:\u4e00到\u9fa5
    zh = " ".join(p2.split(line)).strip()
    zh = ",".join(zh.split())
    str = re.sub("[A-Za-z0-9!!,%\[\],。]", "", zh)
    return str

匹配pyecharts支持的城市列表

 d = pd.read_csv(csv_file, engine='python', encoding='utf-8')
 motion_list = []
 for i in d['content']:
   try:
       s = round(SnowNLP(i).sentiments, 2)
       motion_list.append(s)
   except TypeError:
       continue
   result = {}
   for i in set(motion_list):
       result[i] = motion_list.count(i)
   return result

2 基于snownlp的情感分析

snownlp主要可以进行中文分词(算法是Character-Based Generative Model)、词性标注(原理是TnT、3-gram 隐马)、情感分析(官网木有介绍原理,但是指明购物类的评论的准确率较高,其实是因为它的语料库主要是购物方面的,可以自己构建相关领域语料库,替换原来的,准确率也挺不错的)、文本分类(原理是朴素贝叶斯)、转换拼音、繁体转简体、提取文本关键词(原理是TextRank)、提取摘要(原理是TextRank)、分割句子、文本相似(原理是BM25)【摘自CSDN】。在看此之前,建议先看一下官网,里面有最基础的一些命令的介绍。官网链接:https://pypi.org/project/snownlp/

由于snownlp全部是unicode编码,所以要注意数据是否为unicode编码。因为是unicode编码,所以不需要去除中文文本里面含有的英文,因为都会被转码成统一的编码上面只是调用snownlp原生语料库对文本进行分析,snownlp重点针对购物评价领域,所以为了提高情感分析的准确度可以采取训练语料库的方法。

attr, val = [], []
info = count_sentiment(csv_file)
info = sorted(info.items(), key=lambda x: x[0], reverse=False)  # dict的 排序 方法
for each in info[:-1]:
    attr.append(each[0])
    val.append(each[1])
line = Line(csv_file+":影评情感分析")
line.add("", attr, val, is_smooth=True, is_more_utils=True)
line.render(csv_file+"_情感分析曲线图.html")

3 评论来源城市分析

调用pyecharts的page函数,可以在一个图像对象中创建多个 chart ,只需要对应的add即可。

    geo1 = Geo("", "评论城市分布", title_pos="center", width=1200, height=600,
              background_color='#404a59', title_color="#fff")
    geo1.add("", attr, val, visual_range=[0, 300], visual_text_color="#fff", is_geo_effect_show=False,
            is_piecewise=True, visual_split_number=10, symbol_size=15, is_visualmap=True, is_more_utils=True)
    # geo1.render(csv_file + "_城市dotmap.html")
    page.add_chart(geo1)
    geo2 = Geo("", "评论来源热力图",title_pos="center", width=1200,height=600, background_color='#404a59', title_color="#fff",)
    geo2.add("", attr, val, type="heatmap", is_visualmap=True, visual_range=[0, 50],visual_text_color='#fff', is_more_utils=True)
    # geo2.render(csv_file+"_城市heatmap.html")  # 取CSV文件名的前8位数
    page.add_chart(geo2)
    bar = Bar("", "评论来源排行", title_pos="center", width=1200, height=600 )
    bar.add("", attr, val, is_visualmap=True, visual_range=[0, 100], visual_text_color='#fff',mark_point=["average"],mark_line=["average"],
            is_more_utils=True, is_label_show=True, is_datazoom_show=True, xaxis_rotate=45)
    bar.render(csv_file+"_城市评论bar.html")  # 取CSV文件名的前8位数
    page.add_chart(bar)
    pie = Pie("", "评论来源饼图", title_pos="right", width=1200, height=600)
    pie.add("", attr, val, radius=[20, 50], label_text_color=None, is_label_show=True, legend_orient='vertical', is_more_utils=True, legend_pos='left')
    pie.render(csv_file + "_城市评论Pie.html")  # 取CSV文件名的前8位数
    page.add_chart(pie)
    page.render(csv_file + "_城市评论分析汇总.html")

Python爬取《流浪地球》豆瓣影评与数据分析

Python爬取《流浪地球》豆瓣影评与数据分析

4 影片情感分析

0.5以下为负面情绪,0.5以上为正面情绪。可以看到好评还是很不错的,至于豆瓣上一些看衰评论只是少数。

Python爬取《流浪地球》豆瓣影评与数据分析

5 电影评分走势分析

  • 读取csv文件,以dataframe(df)形式保存

  • 遍历df行,保存到list

  • 统计相同日期相同评分的个数

  • 转换为df格式,设置列名

  • 按日期排序

  • 遍历新的df,每个日期的评分分为5种,因此需要插入补充缺失数值。

creat_df = pd.DataFrame(columns = ['score', 'date', 'votes']) # 创建空的dataframe
for i in list(info_new['date']):
    location = info_new[(info_new.date==i)&(info_new.score=="力荐")].index.tolist()
    if location == []:
        creat_df.loc[mark] = ["力荐", i, 0]
        mark += 1
    location = info_new[(info_new.date==i)&(info_new.score=="推荐")].index.tolist()
    if location == []:
        creat_df.loc[mark] = ["推荐", i, 0]
        mark += 1
    location = info_new[(info_new.date==i)&(info_new.score=="还行")].index.tolist()
    if location == []:
        creat_df.loc[mark] = ["还行", i, 0]
        mark += 1
    location = info_new[(info_new.date==i)&(info_new.score=="较差")].index.tolist()
    if location == []:
        creat_df.loc[mark] = ["较差", i, 0]
        mark += 1
    location = info_new[(info_new.date==i)&(info_new.score=="很差")].index.tolist()
    if location == []:
        creat_df.loc[mark] = ["很差", i, 0]
        mark += 1
info_new = info_new.append(creat_df.drop_duplicates(), ignore_index=True)

Python爬取《流浪地球》豆瓣影评与数据分析

Python爬取《流浪地球》豆瓣影评与数据分析

Python爬取《流浪地球》豆瓣影评与数据分析

由于允许爬取的量少和时间问题,部分数据不是很明显。但依然可以得出一些发现。在影片上映开始的一周内,为评论高峰,尤其是上映3天内,这符合常识,但是也可能有偏差,因为爬虫获取的数据是经过豆瓣电影排序的,倘若数据量足够大得出的趋势可能更接近真实情况。

另外发现,影片在上映前也有部分评论,分析可能是影院公映前的小规模试映,且这些提前批的用户的评分均值,差不多接近影评上映后的大规模评论的最终评分 ,从这些细节中,我们或许可以猜测,这些能提前观看影片的,可能是资深影迷或者影视从业人员,他们的评论有着十分不错的参考价值。

6 影评词云图

词云图制作时,先读取CSV文件一dataframe形式保存,去除评论中非中文文本,选了胡歌照片作为背景,并设置了停用词表。

wc = WordCloud(width=1024, height=768, background_color='white',
     mask=backgroud_Image, font_path="C:\simhei.ttf",
     stopwords=stopwords, max_font_size=400,random_state=50)

Python爬取《流浪地球》豆瓣影评与数据分析 Python爬取《流浪地球》豆瓣影评与数据分析

可以看到高频词“可以”表现出对该片的认可,“特效”体现出特效镜头对科幻片的重要性,“科幻电影”体现出影迷对科幻类电影的浓厚兴趣。

以上就是本次爬取豆瓣网《流浪地球》短评的过程与数据分析。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Using Google App Engine

Using Google App Engine

Charles Severance / O'Reilly Media / 2009-5-23 / USD 29.99

With this book, you can build exciting, scalable web applications quickly and confidently, using Google App Engine - even if you have little or no experience in programming or web development. App Eng......一起来看看 《Using Google App Engine》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具