《python项目开发案例集锦》读书笔记

说明

对本书,基本都是案列;我个人对本书的例子,仅对第13章"开心麻花影视作品分析"感兴趣,所以下面的内容主要是对该章进行描述

数据获取

从网上所说的,用chrome的F12模拟手机对maoyan电影评论进行获取,方法已经失效,但链接依然是可以用的,不知道原来是啥样的,offset的数字貌似不是分页的内容

经过测试,offset到99的时候获取的数据仅仅只有124条(过滤重复后的)

但不影响进行本章节内容的学习

本部分代码完成的内容主要有

  • 访问夏洛特烦恼在猫眼的评论链接,返回json
  • 解析json数据,存放到panda中
  • 对panda中的数据进行去重,写到excel文件中

贴出获取评论内容代码如下

def getData(totalPage):
    header = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
        "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.9",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36"}
    tomato = pd.DataFrame(columns=['date', 'score', 'city', 'comment', 'nick'])
    i = 1
    while True:
        # 测试用代码
        print(i)
        if i == totalPage:
            break
        try:
            url = 'http://m.maoyan.com/mmdb/comments/movie/' + filmId + '.json?_v_=yes&offset=' + str(i)
            response = requests.get(url, headers=header)
            # 读取返回内容
            # print(response.text)
            print(url)
            content = response.text
            total = json.loads(content)['total']
            if total == 0:
                # 结束循环
                break
            else:
                data = json.loads(content)['cmts']
                datah = json.loads(content)['hcmts']
                # print(data)
                for item in data:
                    # print(item)
                    tomato = tomato.append(
                        {'date': item['time'].split(' ')[0], 'city': item.get("cityName", ""),
                         'score': item['score'], 'comment': item['content'],
                         'nick': item['nick']}, ignore_index=True)
                for item in datah:
                    # print(item)
                    tomato = tomato.append(
                        {'date': item['time'].split(' ')[0], 'city': item.get("cityName", ""),
                         'score': item['score'], 'comment': item['content'],
                         'nick': item['nick']}, ignore_index=True)
            i += 1
            time.sleep(2)
        except Exception as ee:
            i += 1
            # 跳出本次循环
            print(ee, url)
            continue
    # 去掉重复数据
    tomato = tomato.drop_duplicates(subset=['date', 'score', 'city', 'comment', 'nick'], keep='first')
    # 生成xlsx文件
    tomato.to_excel(moveName+'.xlsx', sheet_name='data')

得到的文件内容

在这里插入图片描述

评论内容生成柱状图+折线图

获取到了对应的评论信息,只需要读取进行,利用这些信息去构建想要的柱状图、折线图。panda允许我们对某一列数据做分组和聚合,我们会对score进行聚合,得到mean和count,放到pyecharts中的对应图表进行展示

pyecharts把结果保存到html文件中

本部分代码如下

def buildChart():
    # getData(1000)
    # 读取文件内容
    tomato_com = pd.read_excel(moveName + '.xlsx')
    grouped = tomato_com.groupby(['city'])
    grouped_pct = grouped['score']  # 得到分组后的score
    city_com = grouped_pct.agg(['mean', 'count']) # 对score进行聚合,得到mean和count
    # reset_index可以还原索引,从新变为默认的整型索引
    city_com.reset_index(inplace=True)
    # 返回浮点数 0.01 返回到后两位
    city_com['mean'] = round(city_com['mean'], 2)
    city_main = city_com.sort_values('count', ascending=False)[0:10]
    attr = city_main['city']
    v1 = city_main['count']
    v2 = city_main['mean']

    # 柱状图的绘制
    bar = Bar({"theme": ThemeType.MACARONS})
    bar.add_xaxis(attr.tolist())
    bar.extend_axis(
            yaxis=opts.AxisOpts(
                # name="评分",
                type_="value",
                min_=0,
                max_=5,
                interval=1,
                axislabel_opts=opts.LabelOpts(formatter="{value} °分"),
            )
        )

    bar.set_global_opts(
        title_opts=opts.TitleOpts(title="主要城市评论数"),
        tooltip_opts=opts.TooltipOpts(
            is_show=True, trigger="axis", axis_pointer_type="cross" # 十字轴
        ),
        xaxis_opts=opts.AxisOpts(
            # name="城市名",
            type_="category",
            axispointer_opts=opts.AxisPointerOpts(is_show=True, type_="shadow"),
        ),
        yaxis_opts=opts.AxisOpts(
            name="评论数量",
            type_="value",
            min_=0,
            max_=10,
            interval=2,
            axislabel_opts=opts.LabelOpts(formatter="{value}"),
            axistick_opts=opts.AxisTickOpts(is_show=True),
            splitline_opts=opts.SplitLineOpts(is_show=True),
        ),
    )

    bar.add_yaxis("评论数", v1.tolist())

    # 折线图的绘制
    line = (
        Line()
            .add_xaxis(xaxis_data=attr.tolist())
            .add_yaxis(
            series_name="评分",
            yaxis_index=1,
            y_axis=v2.tolist(),
            label_opts=opts.LabelOpts(is_show=True),
            # linestyle_opts=opts.LineStyleOpts(color="#fff"),
            # itemstyle_opts=opts.ItemStyleOpts(
            #     color="red", border_color="#fff", border_width=3
            # ),
            markpoint_opts=opts.MarkPointOpts(
                data=[
                    opts.MarkPointItem(type_="max", name="最大值"),
                    opts.MarkPointItem(type_="min", name="最小值"),
                ]
            ),
        )
        .set_global_opts(
            yaxis_opts=opts.AxisOpts(
                type_="category",
                boundary_gap=False,
                axislabel_opts=opts.LabelOpts(margin=30, color="#ffffff63"),
                axisline_opts=opts.AxisLineOpts(is_show=False),
                axistick_opts=opts.AxisTickOpts(
                    is_show=True,
                    length=250,
                    linestyle_opts=opts.LineStyleOpts(color="#ffffff1f"),
                ),
                splitline_opts=opts.SplitLineOpts(
                    is_show=True, linestyle_opts=opts.LineStyleOpts(color="#ffffff1f")
                ),
            ),
        )
    )
    bar.overlap(line).render(outputHtmlName)

可以看到得到的html文件内容如下

在这里插入图片描述

评论内容生成词云

图云需要首先进行分词,这里使用的jieba,读入词云背景.jpg作为背景模板,如果不设置模板生成是一张矩形图

得到了分词的结果,需要对每个词出现的次数做统计,在词云中出现次数越多的词,绘制字体越大

接着就是绘制到内存中,保存到file

完整代码如下

def buildWordCloud():
    tomato_com = pd.read_excel(moveName + '.xlsx')
    # 评论内容
    tomato_str = ' '.join(tomato_com['comment'])
    words_list = []
    # 用结巴分词
    word_generator = jieba.cut_for_search(tomato_str)
    for word in word_generator:
        words_list.append(word)
    words_list = [k for k in words_list if len(k) > 1]
    back_color = imageio.imread(wcMaskFileName)  # 解析该图片
    wc = WordCloud(background_color='white',  # 背景颜色
                   max_words=200,  # 最大词数
                   mask=back_color,  # 以该参数值作图绘制词云,这个参数不为空时,width和height会被忽略
                   max_font_size=300,  # 显示字体的最大值
                   font_path=fontFileName,  # 字体
                   # random_state=42,  # 为每个词返回一个PIL颜色
                   # width=800,  # 图片的宽
                   # height=600  # 图片的长
                   )
    tomato_count = collections.Counter(words_list) # 统计元素出现的次数
    wc.generate_from_frequencies(tomato_count) # 给定词频去绘制词
    # 基于彩色图像生成相应彩色
    image_colors = ImageColorGenerator(back_color)
    # 绘制词云
    plt.figure()
    plt.imshow(wc.recolor(color_func=image_colors))
    # 去掉座标轴
    plt.axis('off')
    # 保存词云图片
    wc.to_file(outputWcFileName)

生成的词云效果

在这里插入图片描述

其余部分代码

# -*- coding: utf-8 -*-

import json
import requests
import time
import collections

import pandas as pd
import matplotlib.pyplot as plt
from pyecharts.charts import Line, Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from wordcloud import WordCloud, ImageColorGenerator

import jieba
import imageio


filmId = "246082"
moveName = "夏洛特烦恼"
outputHtmlName = "bar_base.html"
wcMaskFileName = "词云背景.jpg"
fontFileName = "STFANGSO.ttf"
outputWcFileName = "词云.png"


if __name__ == "__main__":
    # 从猫眼电影中获取数据
    getData(100)

    # 生成对应柱状图的的html文件
    buildChart()

    # 生成图云
    buildWordCloud()

整个项目代码下载

CSDN链接:https://download.csdn.net/download/zengraoli/12257686

参考链接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章