自年初国内疫情爆发以来,电影、院线行业受到了严重影响。院线方面,疫情的爆发导致大量中小影院难抵现金流压力直接倒闭,加速了院线行业的出清。本文通过爬虫技术爬取相关影院、票房等影院数据,并对其进行简单的数据分析。
本文由公众号读者落叶秋风投稿,欢迎大家踊跃投稿(投稿文档见文末)!
一、简介
艺恩致力于通过大数据、AI技术连接内容与消费者数据,以驱动客户业务增长,其数据指向性和借鉴性非常强大。主要有三大类数据
- 娱乐数据:电影 | 剧综 | 动漫;
- 星星数据:小红书 | B站;
- 商业数据:公测中;
下面我们来使用selenium爬取娱乐数据中影院信息。即是图中电影的部分数据,如下所示:
首先有几个问题需要明确一下:
- 页面数据为动态数据,在网页源码中并未呈现,(非常多的数据确实也不适合全部放到页面到中,一般需要向服务器发送请求获取这么多的数据),上面只展示一页的数据(20条),实际有300多页;
- 点击下一页页面并未刷新更加应证了这一点,所以需要使用到selenium,首先需要登录,定位元素进行各种操作即可;
二、数据抓取
2.1 初步测试
代码语言:javascript复制from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from lxml import etree
import time
web = Chrome()
url = 'https://ys.endata.cn/BoxOffice/Org'
web.get(url)
time.sleep(3)
web.maximize_window()
发现程序运行正常。
2.2 登录
首先点击登录按钮,我们发现有两种方式:分别是扫码登录和账号登录,这里为了方便,我们使用扫码登录,如下所示:
代码语言:javascript复制login_btn = web.find_element(by=By.XPATH,value='//*[@id="app"]/header/section/section/section[2]/button') # 页面元素的复制完整的xpath
login_btn.click()
time.sleep(5) # 这个需要时间,等待5s进行后续操作
2.3 单页面爬取
对于单个页面的数据爬取,有两种方式:
- selenium定位然后解析保存;
- selenium获取page_resource,然后使用
lxml
的etree
函数进行解析。
这里我们使用第二种方式:
一共八个字段分别是:
title(影院名称),票房,省份,城市,场次,人次,平均票价,场均人次
。
定义一个函数即可:
def get_info():
page = web.page_source
html = etree.HTML(page)
trs = html.xpath('//*[@id="app"]/section/main/div/div[1]/div/section/section[2]/section/section[2]/div[1]/div[3]/table/tbody/tr')
for tr in trs:
title = tr.xpath('./td[2]/div/label/data/text()')[0] # 影院名称
ticket = tr.xpath('./td[3]/div/label/text()')[0] # 票房
province = tr.xpath('./td[4]/div/label/text()')[0] # 省份
city = tr.xpath('./td[5]/div/label/text()')[0] # 城市
times = tr.xpath('./td[6]/div/label/text()')[0] # 场次
popu = tr.xpath('./td[7]/div/label/text()')[0] # 人次
average_ticket = tr.xpath('./td[8]/div/label/text()')[0] # 平均票价
average_people = tr.xpath('./td[10]/div/label/text()')[0] # 平均人次
item = (title,ticket,province,city,times,popu,average_ticket,average_people)
list.append(item)
2.4 翻页爬取
登录之后我们看到如下页面,显示了300多个页面的局部导航按钮:
这里我们可以使用循环进行点击,直到达到目标页面才停止爬取;
代码语言:javascript复制count = 0
while (count < 301):
get_info()
count = 1
try:
next_btn = web.find_element(By.XPATH,
'//*[@id="app"]/section/main/div/div[1]/div/section/section[2]/section/section[2]/div[2]/button[2]')
print(next_btn)
next_btn.click()
except Exception as e:
print(e)
time.sleep(3)
2.5 文件保存
由于之前定义的单条数据上元祖,所以遍历列表濯条写入文件即可:
代码语言:javascript复制 with open('yiendata.csv','w',encoding='utf-8') as f:
f.write('n')
for j in list:
f.write(','.join(j))
f.write('n')
2.6 程序运行
编写main函数:
代码语言:javascript复制def main():
while xxx:
xxx
with open('yiendata.csv','w',encoding='utf-8') as f:
xxx
程序运行:
代码语言:javascript复制if __name__ == '__main__':
main()
结果如下:
我们看到刚好定格到300页,数据爬取完毕。
三、数据可视化
由于当下疫情形势严峻,其实我们发现实际情况不太好,并且细心的伙计可以发现数据其实更新非常快,如下所示:
但是由于影院信息固定的,所以我们可以针对影院分布来分析一下,这里我们使用到我们的pycharts
进行我们的可视化展示,非常的美观(相较于matplotlib和seaborn)。
首先简单查看下数据:
代码语言:javascript复制import pandas as pd
data = pd.read_csv('./yiendata.csv',encoding='utf-8')
data.head()
发现没有问题:
3.1 全国影院分布展示:
代码语言:javascript复制from pyecharts import options as opts
from pyecharts.charts import Map
def map_visualmap() -> Map:
c = (
Map()
.add("", [list(z) for z in zip(province, value)], "china")
.set_global_opts(
title_opts=opts.TitleOpts(title="全国影院分布"),
visualmap_opts=opts.VisualMapOpts(max_= 1000),
)
)
return c
if __name__ == '__main__':
city_ = map_visualmap()
city_.render(path="ch.html")
如下所示:
3.2 城市影院分布
我们发现广东省是分布最多的省,因此我们有必要分析一下广东省的各城市的影院分布:
代码语言:javascript复制def map_guangdong() -> Map:
c = (
Map()
.add("", [list(z) for z in zip(gd_city, value)], "广东")
.set_global_opts(
title_opts=opts.TitleOpts(title="广东地图"),
visualmap_opts=opts.VisualMapOpts(max_=100),
)
)
return c
if __name__ == '__main__':
gd = map_guangdong()
gd.render(path='gd.html')
如下所示:
我们发现广州市是广东省影院分布的最多的城市,这个其实也是无容质疑,所以广东真的是好地方。
四、总结
本文我们通过使用selenium爬取娱乐媒体数据中的影院票房信息,总的来说,逻辑并不复杂,都是基本操作,但是注意就是首先登录的问题,如果使用定位需要查看是否含有iframe
标签,然后就是翻页问题,我们点击下一页的时候,页面并无刷新,这时浏览器向服务器发送请求获取数据,这个是需要时间的(这个时间比较短暂),所以每一次都需要使用time.sleep(n)
,最终保存数据进行数据可视化。
声明:
- 本次数据爬取仅做技术分享,大家浅尝辄止,避免对服务器造成压力;
- 严禁将爬取到的数据作为商业使用。