怎样让Python推荐电影 - 初试tushare

周末想看电影,但影评网站水军太多,如果能统计近期正在上映影片的观影人数走势图,就可以直观看出谁更具有成长性。比如口碑好,有内涵的《药神》,上映初期票房不显眼,随着口碑发酵,后期票房逐步走高。
恰好tushare金融数据源有提供中国市场电影票房历史数据,于是就写了python程序,利用历史每日票房数据,得到了近10日观影人数走势图:
怎样让Python推荐电影 - 初试tushare_第1张图片
图上可以看到:

  • 蜘蛛侠在上映12天后,仍然稳坐第二,后劲绵延不绝,应该能值回票价;
  • 上映19天的千与千寻最近2周已表现乏力,国内重映的片子,票房通常都不太理想,家长带孩子怀旧一波自己的童年后,更多人还是更愿意在家看;
  • 扫毒2在上映5天后,迎来第一个周末,冲高到400万人次,势头很猛,留待观察,如果这个周末能保持这个冲劲,就很值得一看了;
  • 同样是刚上映5天的爱宠大机密2,上周末只有不到100万人次观看,如果本周还是这个数量级,说明观看人群仅限于家长陪同孩子,剧情偏向儿童,受众面较窄;

言归正传学编程

tushare是国内爱好者为Fintech人士提供的免费金融数据源,后台数据来自交易所和新浪财经,现在演化到了pro版,接口格式主要有Python和HTTPS,详见 新版官网 和 旧版官网,本文使用的是旧版tushare接口,官网说明摘要如下:

  • 调用方法:
import tushare as ts
df = ts.day_boxoffice('2019-07-10') 
  • 输入参数:date,参数为空则默认取上一日
  • 返回结果:
    AvgPrice 平均票价
    AvpPeoPle 场均人次
    BoxOffice 单日票房(万)
    BoxOffice_Up 环比变化 (%)
    IRank 排名
    MovieDay 上映天数
    MovieName 影片名
    SumBoxOffice 累计票房(万)
    WomIndex 口碑指数

闲话少说上代码

  1. 首先 import tushare 包和画图的 matplotlib 包:
import tushare as ts, datetime  #导入tushare包
import matplotlib.pyplot as plt #导入画图包
  1. 程序主框架,其中自定义函数后面会逐一介绍:
if __name__ == '__main__':
    days = 10 # 经测试旧版tushare不提供早于10天的数据
    # 得到最近指定天数的日期字符串列表,格式:YYYY-MM-DD
    date_list = getDateList(days)
    # 得到最近几天的电影票房数据,list of dataframe
    movie_data_list = getMovieData(date_list)
    # 返回一个可用于保存结果数据的列表,内嵌观影人数列表
    result_list = constructResultList(movie_data_list)
    # 汇总最近几天放映的所有电影的观影人数
    result_list = countMoviePeople(movie_data_list, result_list)
    # 根据最近几天所有放映电影的观影人数,绘制线图
    drawLine(date_list, result_list)
  1. 定义函数getDateList,得到最近指定天数的日期字符串列表,日期格式YYYY-MM-DD
def getDateList(days):
# 输入参数days表示指定向前取的天数
    date_list = []
    for i in range(days,0,-1): #从days开始每次减1
        strDate = (datetime.date.today() \
            - datetime.timedelta(days=i)) \
            .strftime('%Y-%m-%d')  
        # 日期格式:YYYY-MM-DD
        date_list.append(strDate)
    return date_list
    # 返回列表形如['2019-06-29','2019-06-30', ...]
  1. 定义函数getMovieData,从tushare得到指定日期的票房数据集dataframe
def getMovieData(date_list):
# 输入参数date_list就是最近指定天数的日期列表   
    movie_data_list = []
    for date in date_list:
    	# 从tushare获取指定日期的票房 dataframe
        dfMovie = ts.day_boxoffice(date)
        movie_data_list.append(dfMovie)
    return movie_data_list
  1. 定义函数constructResultList,返回一个可用于保存结果数据的列表List,其元素是字典Dict,字典第一个key-value是电影名称,第二个是观影人数列表(按日期从远到近排列),第三个是上映天数。该函数从tushare提供的dataframe列表中,统计最近几天放映的所有电影名,此时观影人数还未统计。
# 返回一个可用于保存结果数据的列表,内嵌观影人数列表
def constructResultList(movie_data_list):
    result_list = []
    all_movie_name_list = [] # 最近放映电影名列表  
    for movieData in movie_data_list:
        movieNameList = movieData.MovieName
        for movieName in movieNameList:
            if movieName not in all_movie_name_list:
                all_movie_name_list.append(movieName)
    # 构造业务主键为name,内嵌观影人数列表的列表 result_list
    for name in all_movie_name_list:
        result_list.append({
            'name':     name,   # 电影名称
            'people':   [],     # 观影人数列表
            'movieDay': None    # 上映天数
        })
    # 从最近一天的票房数据dataframe中获得电影已的上映天数
    movieData = movie_data_list[-1] # -1即取列表最后一个
    for result in result_list:
        numMovie = len(movieData.MovieName)
        for i in range(numMovie):
            if result['name'] == movieData.MovieName[i]:
                result['movieDay'] = movieData.MovieDay[i]
    
    return result_list
  1. 定义函数countMoviePeople,汇总最近几天放映的所有电影的观影人数:
# 汇总最近几天放映的所有电影的观影人数
def countMoviePeople(movie_data_list, result_list):
    # 遍历最近每天的电影票房数据集 dataframe
    for movieData in movie_data_list:
        # 当日放映的所有电影名称列表
        movieNameList = movieData.MovieName
        # 单日票房(万)列表
        boxOfficeList = movieData.BoxOffice
        # 平均票价列表 
        avgPriceList = movieData.AvgPrice 
        # 遍历最近放映的所有电影列表
        for result in result_list:
            foundMovie = False # 是否当日放映了该电影
            # 遍历当日放映的所有电影列表
            for i in range(len(movieNameList)):
                movieName = movieNameList[i]
                boxOffice = boxOfficeList[i]
                avgPrice = avgPriceList[i]
                if  result['name'] == movieName:
                    # 该片当日观影人数 = 当日票房 / 当日平均票价
                    countPeople = int(boxOffice)/int(avgPrice)
                    result['people'].append(int(countPeople))
                    foundMovie = True # 当日放映了该电影
            # 当日没有放映该电影,则当日观影人数为 0
            if foundMovie == False: 
                result['people'].append(0)
    
    return result_list           
  1. 定义函数drawLine,根据最近几天所有放映电影的观影人数,绘制线图
# 根据result_list保存的最近放映电影的观影人数,绘制线图
def drawLine(date_list, result_list):
    # 用于正常显示中文标签
    plt.rcParams['font.sans-serif']\
        =['SimHei'] 
    # 剔除日期字符串前面的4位年份和-字符
    for i in range(len(date_list)):
        date_list[i] = date_list[i][5:]
    # 将电影已上映天数或已下映信息加到片名后面
    for result in result_list:
        if result['movieDay'] == None:
            result['name'] += '(已下映)'
        else:
            result['name'] += '(上映'\
                 + result['movieDay'] +'天)'  
        # 最近上映的每一部电影都绘制一条折线
        plt.plot(date_list, result['people'],\
            label=result['name'])

    plt.legend() # 添加折线说明,loc默认best
    plt.ylabel('观影人数次(万)')
    plt.title('观影人数走势图')
    plt.show()

你可能感兴趣的:(Python,python,tushare,matplotlib,观影人数)