Python全面解读2018电影票房市场

2023-11-09

640


作者 | 法纳斯特

来源 | 法纳斯得


双11已经过去,双12即将来临,离2018年的结束也就2个月不到,还记得年初立下的flag吗?


完成了多少?相信很多人和我一样,抱头痛哭...


本次利用猫眼电影,实现对2018年的电影大数据进行分析。


640



/ 01 / 网页分析


01  标签


640


通过点击猫眼电影已经归类好的标签,得到网址信息。


02  索引页


640


打开开发人员工具,获取索引页里电影的链接以及评分信息。


索引页一共有30多页,但是有电影评分的只有10页。


本次只对有电影评分的数据进行获取。


03  详情页


640


对详情页的信息进行获取。


主要是名称,类型,国家,时长,上映时间,评分,评分人数,累计票房。



/ 02 / 反爬破解


640


通过开发人员工具发现,猫眼针对评分,评分人数,累计票房的数据,施加了文字反爬。


640


通过查看网页源码,发现只要刷新页面,三处文字编码就会改变,无法直接匹配信息。


所以需要下载文字文件,对其进行双匹配。


 
  

from fontTools.ttLib import TTFont

#font = TTFont('base.woff')
#font.saveXML('base.xml')
font = TTFont('maoyan.woff')
font.saveXML('maoyan.xml')

将woff格式转换为xml格式,以便在Pycharm中查看详细信息。


利用下面这个网站,打开woff文件。


url: http://fontstore.baidu.com/static/editor/index.html


可以得到下面数字部分信息(上下两块)。


在Pycharm中查看xml格式文件(左右两块),你就会发现有对应信息。


640

通过上图你就可以将数字6对上号了,其他数字一样的。


 
  

def get_numbers(u):
    """
    对猫眼的文字反爬进行破解
    """

    cmp = re.compile(",\n           url\('(//.*.woff)'\) format\('woff'\)")
    rst = cmp.findall(u)
    ttf = requests.get("http:" + rst[0], stream=True)
    with open("maoyan.woff""wb"as pdf:
        for chunk in ttf.iter_content(chunk_size=1024):
            if chunk:
                pdf.write(chunk)
    base_font = TTFont('base.woff')
    maoyanFont = TTFont('maoyan.woff')
    maoyan_unicode_list = maoyanFont['cmap'].tables[0].ttFont.getGlyphOrder()
    maoyan_num_list = []
    base_num_list = ['.''3''0''8''9''4''1''5''2''7''6']
    base_unicode_list = ['x''uniF561''uniE6E1''uniF125''uniF83F''uniE9E2''uniEEA6''uniEEC2''uniED38''uniE538''uniF8E7']
    for i in range(112):
        maoyan_glyph = maoyanFont['glyf'][maoyan_unicode_list[i]]
        for j in range(11):
            base_glyph = base_font['glyf'][base_unicode_list[j]]
            if maoyan_glyph == base_glyph:
                maoyan_num_list.append(base_num_list[j])
                break
    maoyan_unicode_list[1] = 'uni0078'
    utf8List = [eval(r"'\u" + uni[3:] + "'").encode("utf-8"for uni in maoyan_unicode_list[1:]]
    utf8last = []
    for i in range(len(utf8List)):
        utf8List[i] = str(utf8List[i], encoding='utf-8')
        utf8last.append(utf8List[i])
    return (maoyan_num_list ,utf8last)



/ 03 / 数据获取


01  构造请求头


 
  

head = """
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.8
Cache-Control:max-age=0
Connection:keep-alive
Host:maoyan.com
Upgrade-Insecure-Requests:1
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36
"""


def str_to_dict(header):
    """
    构造请求头,可以在不同函数里构造不同的请求头
    """

    header_dict = {}
    header = header.split('\n')
    for h in header:
        h = h.strip()
        if h:
            k, v = h.split(':'1)
            header_dict[k] = v.strip()
    return header_dict


因为索引页和详情页请求头不一样,这里为了简便,构造了一个函数。


02  获取电影详情页链接


 
  

def get_url():
    """
    获取电影详情页链接
    """

    for i in range(030030):
        time.sleep(10)
        url = 'http://maoyan.com/films?showType=3&yearId=13&sortId=3&offset=' + str(i)
        host = """Referer:http://maoyan.com/films?showType=3&yearId=13&sortId=3&offset=0
        """

        header = head + host
        headers = str_to_dict(header)
        response = requests.get(url=url, headers=headers)
        html = response.text
        soup = BeautifulSoup(html, 'html.parser')
        data_1 = soup.find_all('div', {'class''channel-detail movie-item-title'})
        data_2 = soup.find_all('div', {'class''channel-detail channel-detail-orange'})
        num = 0
        for item in data_1:
            num += 1
            time.sleep(10)
            url_1 = item.select('a')[0]['href']
            if data_2[num-1].get_text() != '暂无评分':
                url = 'http://maoyan.com' + url_1
                for message in get_message(url):
                    print(message)
                    to_mysql(message)
                print(url)
                print('---------------^^^Film_Message^^^-----------------')
            else:
                print('The Work Is Done')
                break


03  获取电影详情页信息


 
  

def get_message(url):
    """
    获取电影详情页里的信息
    """

    time.sleep(10)
    data = {}
    host = """refer: http://maoyan.com/news
    """

    header = head + host
    headers = str_to_dict(header)
    response = requests.get(url=url, headers=headers)
    u = response.text
    # 破解猫眼文字反爬
    (mao_num_list, utf8last) = get_numbers(u)
    # 获取电影信息
    soup = BeautifulSoup(u, "html.parser")
    mw = soup.find_all('span', {'class''stonefont'})
    score = soup.find_all('span', {'class''score-num'})
    unit = soup.find_all('span', {'class''unit'})
    ell = soup.find_all('li', {'class''ellipsis'})
    name = soup.find_all('h3', {'class''name'})
    # 返回电影信息
    data["name"] = name[0].get_text()
    data["type"] = ell[0].get_text()
    data["country"] = ell[1].get_text().split('/')[0].strip().replace('\n''')
    data["length"] = ell[1].get_text().split('/')[1].strip().replace('\n''')
    data["released"] = ell[2].get_text()[:10]
    # 因为会出现没有票房的电影,所以这里需要判断
    if unit:
        bom = ['分', score[0].get_text().replace('.''').replace('万'''), unit[0].get_text()]
        for i in range(len(mw)):
            moviewish = mw[i].get_text().encode('utf-8')
            moviewish = str(moviewish, encoding='utf-8')
            # 通过比对获取反爬文字信息
            for j in range(len(utf8last)):
                moviewish = moviewish.replace(utf8last[j], maoyan_num_list[j])
            if i == 0:
                data["score"] = moviewish + bom[i]
            elif i == 1:
                if '万' in moviewish:
                    data["people"] = int(float(moviewish.replace('万''')) * 10000)
                else:
                    data["people"] = int(float(moviewish))
            else:
                if '万' == bom[i]:
                    data["box_office"] = int(float(moviewish) * 10000)
                else:
                    data["box_office"] = int(float(moviewish) * 100000000)
    else:
        bom = ['分', score[0].get_text().replace('.''').replace('万'''), 0]
        for i in range(len(mw)):
            moviewish = mw[i].get_text().encode('utf-8')
            moviewish = str(moviewish, encoding='utf-8')
            for j in range(len(utf8last)):
                moviewish = moviewish.replace(utf8last[j], maoyan_num_list[j])
            if i == 0:
                data["score"] = moviewish + bom[i]
            else:
                if '万' in moviewish:
                    data["people"] = int(float(moviewish.replace('万''')) * 10000)
                else:
                    data["people"] = int(float(moviewish))
        data["box_office"] = bom[2]
    yield data



/ 04 / 数据存储


01  创建数据库及表格


 
  

db = pymysql.connect(host='127.0.0.1', user='root', password='774110919', port=3306)
cursor = db.cursor()
cursor.execute("CREATE DATABASE maoyan DEFAULT CHARACTER SET utf8mb4")
db.close()


 
  

db = pymysql.connect(host='127.0.0.1', user='root', password='774110919', port=3306, db='maoyan')
cursor = db.cursor()
sql = 'CREATE TABLE IF NOT EXISTS films (name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL, country VARCHAR(255) NOT NULL, length VARCHAR(255) NOT NULL, released VARCHAR(255) NOT NULL, score VARCHAR(255) NOT NULL, people INT NOT NULL, box_office BIGINT NOT NULL, PRIMARY KEY (name))'
cursor.execute(sql)
db.close()


其中票房收入数据类型为BIGINT(19位数),最大为18446744073709551615。


INT(10位数),最大为2147483647,达不到36亿(3600000000)。


02  数据存储


 
  

def to_mysql(data):
    """
    信息写入mysql
    """

    table = 'films'
    keys = ', '.join(data.keys())
    values = ', '.join(['%s'] * len(data))
    db = pymysql.connect(host='localhost', user='root', password='774110919', port=3306, db='maoyan')
    cursor = db.cursor()
    sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table, keys=keys, values=values)
    try:
        if cursor.execute(sql, tuple(data.values())):
            print("Successful")
            db.commit()
    except:
        print('Failed')
        db.rollback()
    db.close()


最后成功存储数据


640



/ 05 / 数据可视化


可视化源码就不放了,公众号回复电影即可获得。


01  电影票房TOP10


640


还剩一个多月,不知道榜单上会不会有新成员。最近「毒液」很火,蛮有希望。


02  电影评分TOP10


640


这里就得吐槽一下pyecharts,坐标转换后,坐标值名称太长就会被遮挡,还需改进呢~


03  电影人气TOP10


640


茫茫人海之中,相信一定也有大家的身影,我也是其中的一员!!!


04  每月电影上映数量


640


每月上映数好像没什么大差距,7月最少,难道是因为天气热?


05  每月电影票房


640


这里就看出春节档电影的威力了,金三银四、金九银十,各行各业的规律,电影行业也不例外。


上一张图我们知道7月份电影上新最少,票房反而是第二。


这里看了下数据,发现有「我不是药神」「西虹市首富」「邪不压正」「摩天营救」「狄仁杰之四大天王」几部大剧撑着。


06  各国家电影数量TOP10


640


原来中国电影这么高产的,可是豆瓣TOP250里又有多少中国电影呢?深思!!!


07  中外票房对比


640


2017年的年度票房是560亿,估计今年快要突破了。据说今年全年票房有望突破600亿。


08  电影名利双收TOP10


640


计算公式是,把某部电影的评分在所有电影评分中的排名与这部电影的票房在所有票房中的排名加起来,再除以电影总数。


除了「侏罗纪世界2」「无双」「捉妖记2」,我都看过啦!


09  电影叫座不叫好TOP10


640


计算公式是,把某部电影的票房排名减去某部电影的评分排名加起来,再除以电影总数。


可能是猫眼的用户比较仁慈吧,与豆瓣相比,普遍评分都比较高。我个人都不太敢相信这个结果。


不过有一个还是挺准的,「爱情公寓」。


10  电影类型分布


640

剧情电影永远引人深思。感觉今年的电影好多跟钱有关,比如「我不是药神」「西虹市首富」「一出好戏」「头号玩家」,贫穷限制了大家伙们。


公众号回复电影。即可获取全部源码。


文章的封面自己做的,觉得文章不错的。


文末点个赞,比心!!!


◆ ◆ ◆  ◆ ◆

数据森麟
长按二维码关注我们





数据森麟公众号的交流群已经建立,许多小伙伴已经加入其中,感谢大家的支持。大家可以在群里交流关于数据分析&数据挖掘的相关内容,还没有加入的小伙伴可以通过扫描下方管理员二维码,让管理员帮忙拉进群,期待大家的加入。


管理员二维码:


猜你喜欢

● 

● 

● 

● 

● 


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python全面解读2018电影票房市场 的相关文章

  • Java多线程两种实现

    在java中实现多线程的方式有两种 一种是继承Thread类 另一个是实现Runnable接口 对于两种实现 各有优缺点 接下来进行对比总结一下 这两种方法 都可以实现多线程 以下为两种实现的写法 继承Thread类的方式 package
  • 五、语言特性之<=default,=delete、using、noexcept、override、final、以及和const对比>

    目录 一 default delete 1 首先我们要回顾一下编译器提供的默认函数 2 何时需要自定义big three 构造函数 拷贝构造 拷贝赋值 big five 新增移动构造函数 移动赋值函数 3 default delete关键字
  • Yearning做SQL审核

    系统环境 Centos7一 Inception安装 1 安装相关依赖包 yum install bison ncurses libs libncurses5 devel ncurses devel wget git cmake openss
  • C++模板特例化

    模板是用来写一些独立化特定类型的代码 但是对于有些类型 在处理时 细节上却有所差别 常见的如char 如 现在你打算写一个栈 可以用于任何数据类型 那你肯定首先想到的就是模板啦 template
  • LeetCode-797. All Paths From Source to Target

    Given a directed acyclic graph of N nodes Find all possible paths from node 0 to node N 1 and return them in any order T
  • 【满分】【华为OD机试真题2023 JAVA&JS】知识图谱新词挖掘1

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 知识图谱新词挖掘1 知识点滑窗 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 小华负责公司知识图谱产品 现在要通过新词挖掘完善知识图谱 新词挖掘 给出一个待挖掘
  • C++ Primer 学习笔记 第十五章 面向对象程序设计

    面向对象程序设计 OOP 基于三个概念 数据抽象 只暴露类的接口 而如何实现的是不透明的 即类的接口和实现分离 继承 能实现相似的类型 动态绑定 忽略相似类型的区别 以统一方式使用它 继承关系联系在一起的类构成层次关系 在最低层有一个基类
  • 从海明校验码深入了解

    首先 海明校验码的学习看视频没看明白 看了博客有所感悟 1 海明校验码不是万能的 根据信息论也知道不可能 写在海明校验码之前 海明校验码的原理和我之前遇到的一道题目很像 10只老鼠试验1024瓶药是否有毒 有1024瓶药 其中已知有1瓶且只
  • java事务

    转载http blog csdn net foart archive 2009 06 11 4260864 aspx 一 什么是Java事务 通常的观念认为 事务仅与数据库相关 事务必须服从ISO IEC所制定的ACID原则 ACID是 原
  • SQL Server中使用convert转化长日期为短日期

    一般存入数据库中的时间格式为yyyy mm ddhh mm ss 如果要转换为yyyy mm dd 短日期格式 可以使用convert函数 下面是sqlserver帮助中关于convert函数的声明 使用 CONVERT CONVERT d
  • 保姆级系列教程-玩转Fiddler抓包教程(1)-HTTP和HTTPS基础知识

    1 简介 有的小伙伴或者童鞋们可能会好奇地问 不是讲解和分享抓包工具了怎么这里开始讲解HTTP和HTTPS协议了 这是因为你对HTTP协议越了解 你就能越掌握Fiddler的使用方法 反过来你越使用Fiddler 就越能帮助你了解HTTP协
  • FPGA原理与结构——时钟IP核原理学习

    一 前言 在之前的文章中 我们介绍了FPGA的时钟结构 FPGA原理与结构 时钟资源https blog csdn net apple 53311083 article details 132307564 spm 1001 2014 300
  • postgres基本操作(个人总结版)

    postgres 基本操作 登录 psql 连接数据库 默认用户和数据库都是postgres psql U
  • Qt开发基础(8)——自定义封装控件

    创建一个Widget之后 再进行新建如下设计师界面 创建好了就是这样多了一个smallwidget ui 假如我们需要将Spin Box和Horizontal Slider封装在一起 我们可以看到封装的小控件是一个QWidget类型 所以我
  • 【硬件】【传感器 BH1750FVI】

    Ambient Light Sensor 环境光传感器 BH1750FVI 简介 环境光传感器 厂商 ROHM 立创商城采购链接 测量精度 0 96 1 2 1 44 分辨率 1 65535 lx 工作电压 2 4 3 6V Typ 3 0
  • SpringBoot + Vue 用户登入token 之租房管理系统后台 模板

    SpringBoot 项目构建 SpringBoot MySQL8 MyBatis Plus Redis 定时任务框架 elastic job Spring Security JWT 前后端分离Token csdn 下载地址 https d
  • 经济法基础:第八章 劳动合同与社会保险法律制度

  • Three.js打造H5里的“3D全景漫游”秘籍

    近来风生水起的VR虚拟现实技术 抽空想起年初完成的 星球计划 项目 总结篇文章与各位分享一下制作基于Html5的3D全景漫游秘籍 QQ物联与深圳市天文台合作 在手Q 发现新设备 公共设备 里 连接QQ物联摄像头为用户提供2016年天体大事件
  • 记LGSVL Map Annotation(2)导入点云、以及地图

    导入点云 内置的点云导入器工具提供了将最流行的点云文件格式 PCD PLY LAS LAZ 转换为可用于仿真的数据所需的所有功能 要访问点云导入器窗口 请在 Unity 编辑器中打开模拟器项目 然后导航到 Simulator Import
  • Netty实战(十)编解码器框架

    编解码器框架 一 什么是编解码器框架 1 1 解码器 1 1 1 抽象类 ByteToMessageDecoder 1 1 2 抽象类 ReplayingDecoder 1 1 3 抽象类 MessageToMessageDecoder 1

随机推荐

  • 蓝桥杯 基础练习 2n皇后问题

    题目 问题描述 给定一个n n的棋盘 棋盘中有一些位置不能放皇后 现在要向棋盘中放入n个黑皇后和n个白皇后 使任意的两个黑皇后都不在同一行 同一列或同一条对角线上 任意的两个白皇后都不在同一行 同一列或同一条对角线上 问总共有多少种放法 n
  • 埃加洛尔虚拟服务器,致我终将逝去的二区:新一轮大服务器实装

    已实装wow大服务器配对列表 8月13日已完成 第一大区 鹰巢山 第十大区 达尔坎 第一大区 玛多兰 第一大区 银月 第二大区 黑暗之门 第十大区 血吼 第二大区 埃苏雷格 第一大区 凯尔萨斯 8月6日已完成 第二大区 格鲁尔 第一大区 斯
  • anaconda创建环境失败解决方案

    在深度学习中 我们常采用anaconda进行环境管理 这次出现了一个问题 当在 base 环境下输入命令 conda create n env name python x x 来创建一个环境名称为env name python版本为x x的
  • 如何通过OpenFace实现人脸识别框架

    本文中 笔者将介绍OpenFace中实现人脸识别的pipeline 这个pipeline可以看做是使用深度卷积网络处理人脸问题的一个基本框架 很有学习价值 它的结构如下图所示 Input Image gt Detect 输入 原始的可能含有
  • 物联网毕设分享 - stm32单片机的远程WIFI密码锁 - 物联网 嵌入式

    文章目录 0 前言 1 简介 主要器件 实现效果 4 硬件设计 WIFI模块 OLED显示屏 相关原理图 硬件接线 5 软件说明 开发环境介绍 程序下载配置 设备初始化打印的信息 6 部分核心代码 7 最后 0 前言 这两年开始毕业设计和毕
  • 合理配置线程池核心线程数(IO密集型和CPU密集型)

    1 代码查看服务器的核心数 要合理配置线程数首先要知道公司服务器是几核的 代码查看服务器核数 System out println Runtime getRuntime availableProcessors 2 合理线程数配置之CPU密集
  • 使用Python实现单隐藏层神经网络的训练

    文章目录 1 实验内容 2 实验要求 3 实验原理 多层感知机 前向传播与后向传播 4 具体实现 数据加载与可视化 激活函数 单隐层神经网络 前向传播 后向传播 Mini batch梯度下降 预测与评估 分类结果可视化 5 实验结果 不同激
  • 表情符号(emoji)大全,只此一文便够了

    本文由 大侠 AhcaoZhu 原创 转载请声明 链接 https blog csdn net Ahcao2008 表情符号 emoji 大全 只此一文便够了 摘要 集中展示 笑脸和动物 人 庆贺和物品 食品和物 交通和地点 符号 符号表
  • QT编译警告 warning LNK4042: 对象被多次指定;已忽略多余的指定

    目录 场景复现 解决方案 场景复现 在一次移植QT工程时 发现qmake完成后报了下面一个警告 warning LNK4042 对象被多次指定 已忽略多余的指定 因为我只是移植工程 所以问题只能出在pro配置文件中 反复仔细观看发现在源文件
  • JS/TS格式化日期

    interface Date format this Date fmt string gt string Date prototype format function fmt const ss new Map M this getMonth
  • UE4C++泛型蓝图节点之K2Node蓝图节点

    UE4C 泛型蓝图节点之K2Node蓝图节点 前言 上篇我们讲解了以CustomThunk方式创建自定义泛型节点 今天在此我们讲解以K2Node实现自定义蓝图节点 首先 我们来比较这俩种方法 CustomThunk创建泛型节点时 代码简洁
  • 2014年第五届蓝桥杯Java程序设计本科B组决赛 供水设施(编程大题)

    2014年第五届蓝桥杯Java程序设计本科B组决赛个人题解汇总 https blog csdn net daixinliangwyx article details 89948727 第六题 标题 供水设施 交题测试链接 https www
  • IDEA配置Maven

    1 IDEA配置Maven环境 先在IDEA中配置Maven环境 选择 IDEA中 File gt Settings 搜索 maven 设置 IDEA 使用本地安装的 Maven 并修改配置文件路径 2 IDEA 创建 Maven项目 创建
  • sklearn实战之决策树

    sklearn实战系列 1 sklearn实战之决策树 2 sklearn实战之随机森林 3 sklearn实战之数据预处理与特征工程 4 sklearn实战之降维算法PCA与SVD 5 sklearn实战之逻辑回归与制作评分卡 6 skl
  • 《乌合之众》读书笔记

    作者 法 古斯塔夫 勒庞 译者 马晓佳 背景 法国大革命 导言 群体的时代 真正的历史变革 并不是那些以宏伟和暴力的场景令我们震惊的事情 能够令文化实现伟大复兴的唯一重要的变化 是对思想 观念和信仰产生影响的变化 令人印象深刻的历史事件只不
  • [CCPC] 2017秦皇岛 NumbersI

    题目描述 DreamGrid has a nonnegative integer n He would like to divide n into m nonnegative integers a1 a2 am and minimizes
  • LeetCode高频算法刷题记录4

    文章目录 1 二叉树的最近公共祖先 中等 1 1 题目描述 1 2 解题思路 1 3 代码实现 2 全排列 中等 2 1 题目描述 2 2 解题思路 2 3 代码实现 3 相交链表 简单 3 1 题目描述 3 2 解题思路 3 3 代码实现
  • Ubuntu18.04 下载与安装

    阿里云里面有很多镜像 https opsx alibaba com mirror Ubuntu各个版本的镜像下载地址 http mirrors melbourne co uk ubuntu releases 最新百度经验 Ubuntu19
  • 纯HTML+CSS网页设计——林允儿(可做网页课程作业)

    作品介绍 网页为作者一次课程作业 效果个人觉得还行 其中抛弃了导航栏的使用 主要每次都导航栏 写烦了 采用的是图谱的形式 主要也是因为最近在学 页面主要有6个 有三个是较重复的 所以主要页面是四个 具体的直接看图吧 作品展示 首页 首页背景
  • Python全面解读2018电影票房市场

    作者 法纳斯特 来源 法纳斯得 双11已经过去 双12即将来临 离2018年的结束也就2个月不到 还记得年初立下的flag吗 完成了多少 相信很多人和我一样 抱头痛哭 本次利用猫眼电影 实现对2018年的电影大数据进行分析 01 网页分析