地区电影市场分析:用Python爬虫抓取猫眼_灯塔专业版各地区票房
在当今高度数据驱动的影视行业,精准把握地区票房表现是制片方、宣发团队和影院经理做出关键决策的基础。一部电影在北上广深的表现与二三线城市有何差异?哪种类型的电影在特定区域更受欢迎?回答这些问题,不能再依赖“拍脑袋”和经验主义,而需要真实、及时、细粒度的数据支撑。
猫眼专业版(piaofang.maoyan.com)和灯塔专业版(box.taobao.com)作为国内最权威的票房数据平台,每日发布包括全国、省、市乃至单个影院的多维度票房数据。这些数据是进行深度市场分析的宝藏。本文将详细介绍如何利用Python爬虫技术,自动化地从这些平台抓取各地区票房数据,并完成一次小规模的分析实践。
一、技术选型与思路分析
在开始编写代码之前,我们需要对目标和数据获取方式进行一番侦察。
- 目标网站分析:猫眼和灯塔专业版的数据部分为公开数据(如首页榜单)和非公开的详细数据(需登录账号)。本文将以猫眼专业版的日票房排行榜及其背后的单日影片地区票房明细作为抓取目标。这类数据通常通过XHR(Ajax)请求动态加载,而非直接渲染在HTML中,这决定了我们的技术路线。
- 反爬策略考虑:专业数据平台通常没有较强的反爬机制,如猫眼专业版,但我们会遵循道德爬虫的准则。灯塔作为阿里系产品,反爬机制可能更为严格(需要更复杂的请求头模拟、Cookie处理等),本文为简化流程,将以猫眼为例。
- 技术栈:
- 请求库:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">requests</font>**
,用于发送HTTP请求,简单易用。 - 解析库:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">json</font>**
,因为数据接口返回的是JSON格式,直接解析即可,无需HTML解析器。 - 数据存储:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">pandas</font>**
和**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">csv</font>**
,用于将爬取的数据结构化并存储到CSV文件中,方便后续分析。 - 可视化:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">pyecharts</font>**
,一个非常强大的可视化库,可以生成交互式的、美观的图表。
- 请求库:
核心思路:
- 打开浏览器开发者工具(F12),切换到“网络(Network)”面板。
- 刷新猫眼专业版页面,筛选XHR请求。
- 逐个查看请求,找到返回票房数据的API接口。
- 分析该接口的URL、请求头(Headers)和请求参数(Payload)。
- 在Python代码中模拟这个请求,获取返回的JSON数据。
- 从JSON数据中提取我们需要的信息(日期、影片名、总票房、地区、地区票房等)。
- 将数据存储到CSV文件或数据库中。
- 利用
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">pandas</font>**
进行数据清洗和初步分析,并用**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">pyecharts</font>**
进行可视化。
二、代码实现过程
下面我们以抓取猫眼专业版某一天的影片地区票房明细为例。
步骤1:分析API接口
通过浏览器开发者工具分析,我们找到了获取地区票房数据的接口(注:接口地址和参数可能随时间变化,请以实际分析为准)。
一个典型的接口URL可能类似于:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">https://piaofang.maoyan.com/movie/1281575/regionbox?date=2023-10-01</font>**
其中:
**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">1281575</font>**
是影片的唯一ID(例如《志愿军:雄兵出击》)。**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">date=2023-10-01</font>**
指定了要查询的日期。
请求这个URL,服务器会返回一个JSON对象,其中**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">data</font>**
字段下的**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">list</font>**
包含了各个地区的详细票房数据。
步骤2:编写爬虫代码
首先,安装必要的库(如果尚未安装):
然后,开始编写代码:
import requests
import pandas as pd
from pyecharts.charts import Bar, Map
from pyecharts import options as opts
from pyecharts.globals import ThemeType
import json
import time
import csv# 代理配置信息
proxyHost = "www.16yun.cn"
proxyPort = "5445"
proxyUser = "16QMSOML"
proxyPass = "280651"# 代理服务器
proxyMeta = f"http://{proxyUser}:{proxyPass}@{proxyHost}:{proxyPort}"proxies = {"http": proxyMeta,"https": proxyMeta,
}# 定义一个请求头,模拟浏览器行为,避免被简单的反爬机制拦截
headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36','Accept': 'application/json, text/plain, */*','Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8','Connection': 'keep-alive',# 'Cookie': '你的Cookie(如果需要的话)', # 猫眼这个接口通常不需要Cookie'Referer': 'https://piaofang.maoyan.com/'
}def fetch_movie_list(date):"""获取某一天的票房排行榜,从而得到电影ID列表"""# 这是一个获取单日大盘数据的接口,返回榜单url = f"https://piaofang.maoyan.com/box-office?date={date}&type=1"try:response = requests.get(url, headers=headers, proxies=proxies, timeout=15)response.raise_for_status() # 如果状态码不是200,抛出异常data = response.json()# 解析JSON,获取电影列表# 实际路径需要根据返回的JSON结构调整movie_list = data['data']['list']print(f"成功获取{date}日票房榜单,共{len(movie_list)}部电影")return movie_listexcept requests.exceptions.ProxyError as e:print(f"代理连接失败: {e}")return []except requests.exceptions.RequestException as e:print(f"请求电影列表失败: {e}")return []except json.JSONDecodeError as e:print(f"解析电影列表JSON失败: {e}")return []def fetch_movie_region_boxoffice(movie_id, movie_name, date):"""获取单一电影在指定日期的地区票房明细"""url = f"https://piaofang.maoyan.com/movie/{movie_id}/regionbox?date={date}"try:response = requests.get(url, headers=headers, proxies=proxies, timeout=15)response.raise_for_status()data = response.json()region_list = data['data']['list']data_to_save = []for region in region_list:# 提取每个地区的信息region_data = {'date': date,'movie_id': movie_id,'movie_name': movie_name,'region': region.get('regionName'),'box_office': region.get('boxInfo'), # 票房,单位通常是万元'box_office_ratio': region.get('boxRate'), # 票房占比'avg_price': region.get('avgViewBox'), # 平均票价'attendance': region.get('attendance'), # 场均人次}data_to_save.append(region_data)print(f"成功获取电影《{movie_name}》在{date}的地区票房数据,共{len(region_list)}个地区")return data_to_saveexcept requests.exceptions.ProxyError as e:print(f"代理连接失败(电影《{movie_name}》): {e}")return []except requests.exceptions.RequestException as e:print(f"请求电影《{movie_name}》的地区票房失败: {e}")return []except json.JSONDecodeError as e:print(f"解析电影《{movie_name}》的地区票房JSON失败: {e}")return []except KeyError as e:print(f"JSON数据结构异常(电影《{movie_name}》): {e}")return []def main():target_date = "2023-10-05" # 指定要抓取的日期all_region_data = [] # 存储所有电影的地区数据# 测试代理连接try:test_response = requests.get("http://httpbin.org/ip", proxies=proxies, timeout=10)print(f"代理连接测试成功,当前IP: {test_response.json()['origin']}")except Exception as e:print(f"代理连接测试失败: {e}")print("请检查代理配置信息是否正确,网络是否通畅")return# 1. 获取当天的电影排行榜movies = fetch_movie_list(target_date)if not movies:print("未获取到电影列表,程序退出")return# 2. 遍历榜单中的每一部电影,获取其地区明细for movie in movies:movie_id = movie.get('movieId')movie_name = movie.get('movieName')if not movie_id:continue# 暂停一小段时间,避免请求过于频繁time.sleep(1.5) # 稍微延长等待时间,避免触发反爬single_movie_data = fetch_movie_region_boxoffice(movie_id, movie_name, target_date)if single_movie_data:all_region_data.extend(single_movie_data)# 3. 将所有数据保存到CSV文件if all_region_data:df = pd.DataFrame(all_region_data)filename = f'maoyan_region_boxoffice_{target_date}.csv'df.to_csv(filename, index=False, encoding='utf-8-sig') # utf-8-sig支持Excel直接打开显示中文print(f"所有数据已保存到文件: {filename}")print(f"共爬取{len(all_region_data)}条地区票房记录")# 这里可以调用数据分析函数# analyze_data(df, target_date)else:print("未获取到任何地区票房数据")if __name__ == '__main__':main()
步骤3:数据清洗与存储
上述代码已经将数据存储为CSV文件。**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">pandas</font>**
库使得数据清洗变得非常简单。例如,票房数据可能是字符串“12.3万”,我们需要将其转换为浮点数**<font style="color:rgb(64, 64, 64);background-color:rgb(236, 236, 236);">123000.0</font>**
以便于计算。
# 在analyze_data函数或单独进行数据清洗
def clean_data(df):# 示例:清洗票房数据(假设原始数据是'1.2万'的形式)def convert_box_office(val):if '万' in val:return float(val.replace('万', '')) * 10000else:return float(val)df['box_office_clean'] = df['box_office'].apply(convert_box_office)# 类似地,可以清洗其他列...return df
三、数据分析与可视化示例
数据抓取和清洗完成后,我们就可以进行分析了。假设我们想分析《志愿军:雄兵出击》在2023年国庆档期间在全国各省的票房分布。
def analyze_data(df, date):# 假设我们只分析一部特定的电影target_movie = "志愿军:雄兵出击"df_movie = df[df['movie_name'] == target_movie].copy()if df_movie.empty:print(f"未找到电影《{target_movie}》的数据")return# 1. 绘制全国票房分布地图# 准备地图数据:列表,元素为[省份名称,票房值] map_data = [[row['region'], row['box_office_clean']] for _, row in df_movie.iterrows()]map_chart = (Map(init_opts=opts.InitOpts(theme=ThemeType.ROMA, width="1200px", height="600px")).add(series_name="票房",data_pair=map_data,maptype="china",is_map_symbol_show=False,).set_global_opts(title_opts=opts.TitleOpts(title=f"{target_movie} {date} 全国各省票房分布(元)"),visualmap_opts=opts.VisualMapOpts(max_=max(df_movie['box_office_clean']), # 视觉映射的最大值is_piecewise=False, # 是否为分段型range_text=['高', '低'],),).set_series_opts(label_opts=opts.LabelOpts(is_show=True)) # 显示省份名称)map_chart.render(f"{target_movie}_{date}_票房地图.html")# 2. 绘制票房TOP10省份柱状图df_sorted = df_movie.sort_values(by='box_office_clean', ascending=False).head(10)regions = df_sorted['region'].tolist()box_offices = df_sorted['box_office_clean'].tolist()bar_chart = (Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT)).add_xaxis(regions).add_yaxis("票房(元)", box_offices).set_global_opts(title_opts=opts.TitleOpts(title=f"{target_movie} {date} 省份票房TOP10"),xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)), # 旋转x轴标签避免重叠yaxis_opts=opts.AxisOpts(name="票房"),))bar_chart.render(f"{target_movie}_{date}_票房TOP10.html")print(f"可视化图表已生成完毕。")
运行上述代码后,将会生成两个交互式的HTML图表文件:一个是中国地图,颜色深浅代表票房高低;另一个是柱状图,直观展示票房最高的10个省份。
四、总结与展望
通过本文的技术讲解和代码实现,我们成功地构建了一个可以自动抓取、解析、存储和分析猫眼专业版地区票房数据的Python爬虫。这套方法不仅可以用于单日分析,稍加改造(如循环日期)即可用于分析时间序列数据,研究电影票房在不同地区的生命周期和走势。