Python爬取猫眼的电影数据,拿到数据后做可视化,从年份、月份、国家、明星等角度展示猫眼电影排行榜的数据。
python中用作数据可视化的工具有多种,其中matplotlib最为基础,使用matplotlib和pyecharts作图比较。
爬虫使用requests实现,解析数据使用xpath和re,保存数据用csv,最后把数据保存到csv中,后续进行数据数据可视化。
#encoding:utf-8
# 导包
import requests
from lxml import etree
import csv
import re
import os
def get_home(url,i):
headers1 = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36',
}
data = {
'offset': i
}
html = requests.get(url, headers=headers1,data=data).text
html_xml = etree.HTML(html)
# 缩小范围
div_list = html_xml.xpath('//dl[@class="board-wrapper"]/dd')
for div in div_list:
# 获取排名
id = div.xpath('.//i//text()')[0]
# 获取电影名
title = div.xpath('.//div/div/div[1]/p[1]/a//text()')[0]
# 获取主演
author = div.xpath('.//div/div/div[1]/p[2]//text()')[0].strip().replace("主演:","")
# 获取上映时间
uptime = div.xpath('.//div/div/div[1]/p[3]//text()')[0].replace("上映时间:","")
# 获取评分
score1 = div.xpath('.//div/div/div[2]/p/i[1]//text()')[0]
score2 = div.xpath('.//div/div/div[2]/p/i[2]//text()')[0]
Score = score1 + score2
# 获取详情页的
page_url = "https://maoyan.com"+div.xpath('.//a/@href')[0]
headers2 = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',
'Referer': 'https://maoyan.com/board/4?',
'Cookie': '__mta=49697305.1591087345081.1591088551937.1591088582304.5; uuid_n_v=v1; uuid=E0450840A47911EA8B6321E51B404C84D0DD31B4C1BC4CE4BE9853C11B39428B; _lxsdk_cuid=1723c4e4dd1c8-07b735646e6764-c383f64-1fa400-1723c4e4dd1c8; _lxsdk=E0450840A47911EA8B6321E51B404C84D0DD31B4C1BC4CE4BE9853C11B39428B; mojo-uuid=5efe1ce595a87788b3933bbda8753a3b; _lx_utm=utm_source%3DBaidu%26utm_medium%3Dorganic; _csrf=69e1c4aa402dbf63b66d1107e22e8e8a7eececa5eae84154c317add4ceef9968; Hm_lvt_703e94591e87be68cc8da0da7cbd0be2=1590157359,1590191981,1591065396,1591085890; mojo-session-id={"id":"cdc6c20d76f44fe4241acb652cc55a10","time":1591085889762}; mojo-trace-id=13; Hm_lpvt_703e94591e87be68cc8da0da7cbd0be2=1591088582; _lxsdk_s=172741bf913-4c-798-9df%7C%7C21'
}
html2 = requests.get(page_url, headers=headers2).text
html_xml2 = etree.HTML(html2)
# 获取类型
style = html_xml2.xpath('//div[@class="banner"]/div/div[2]/div[1]/ul/li[1]/a//text()')
style = "".join(style).replace(" ",",")
# 获取视频时长
long_time = html_xml2.xpath('//div[@class="banner"]/div/div[2]/div[1]/ul/li[2]//text()')[0]
long_time = re.findall('.*/(.*)分钟', long_time)[0]
weike_dict = {
"id":id,
"title":title,
"author":author,
"uptime":uptime,
"Score":Score,
"style":style,
"long_time":long_time
}
# shave_csv(weike_dict)
print(weike_dict)
# print(url)
def shave_csv(weike_dict):
# 判断是否已经有表头
ifnot os.path.exists(".\data1.csv"):
with open(".\data1.csv", 'a+', encoding='gb18030', newline="") as csvfile:
writer = csv.DictWriter(csvfile,fieldnames=["id", "title", "author", "uptime", "Score", "style","long_time"])
writer.writeheader()
# 进行存储
with open(".\data1.csv", 'a+', encoding='gb18030', newline="") as csvfile:
writer = csv.DictWriter(csvfile,fieldnames=["id", "title", "author", "uptime", "Score", "style","long_time"])
writer.writerow(weike_dict)
if __name__ == '__main__':
for i in range(0, 100, 10):
url_list = 'https://maoyan.com/board/4?offset={}'.format(str(i))
get_home(url_list,i)
下面进行的是数据可视化,使用matplotlib和pyecharts数据可视化进行比较
Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。而 Python 是一门富有表达力的语言,很适合用于数据处理,而且界面很优美。
Matplotlib是一个Python 2D绘图库,它以多种硬拷贝格式和跨平台的交互式环境生成出版物质量的图形。 Matplotlib可用于Python脚本,Python和IPython (opens new window)Shell、Jupyter (opens new window)笔记本,Web应用程序服务器和四个图形用户界面工具包。
pyecharts官方文档:pyecharts.org/
Matplotlib官方文档:www.matplotlib.org.cn/intro/
# 画布大小
fig = plt.figure(figsize=(20, 10), dpi=80)
# 传入x,y
plt.plot(self.year)
# 修改x轴的显示方式
plt.xticks(rotation=-45)
# 显示文字
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置字体大小
font1 = {'family': 'simhei',
'weight': 'normal',
'size': 18, }
# 设置x轴和y轴以及标题
plt.xlabel('年份', font1)
plt.ylabel('数量', font1)
plt.title('电影年份分布情况', font1)
# 保存图片
plt.savefig("./电影年份分布情况.jpg")
# 展示绘图
plt.show()
b = []
for i in self.year.values:
b.append(int(i))
line = Line()
line.set_global_opts(
# 标题
title_opts=options.TitleOpts(
title="电影年份分布", subtitle="snowdream"),
# 开启提示框
tooltip_opts=options.TooltipOpts(is_show=True),
toolbox_opts=options.ToolboxOpts(),
# 坐标轴类型
xaxis_opts=options.AxisOpts(type_="category"),
datazoom_opts=options.DataZoomOpts()
)
line.add_xaxis(xaxis_data=self.year.index)
line.add_yaxis(series_name="数量", y_axis=b)
# 输出为html文件
line.render(".\电影年份分布情况.html")
plt.figure(figsize=(16, 12))
plt.bar(self.month.index, self.month.values, 0.5, alpha=1, color='b')
# 显示文字
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置字体大小
font1 = {'family': 'simhei',
'weight': 'normal',
'size': 18, }
# 设置x轴和y轴以及标题
plt.xlabel('月份', font1)
plt.ylabel('数量', font1)
plt.title('电影月份分布情况', font1)
# 设置数字标签
for a, b in zip(self.month.index, self.month.values):
plt.text(a, b + 0.05, '%.0f' % b, ha='center', va='bottom', fontsize=20)
# 保存图片
plt.savefig(".\电影月份分布情况.jpg", dpi=200, bbox_inches='tight')
plt.show()
b = []
for i in self.month.values:
b.append(int(i))
line = Line()
line.set_global_opts(
# 标题
title_opts=options.TitleOpts(title="电影月份分布", subtitle="snowdream"),
# 开启提示框
tooltip_opts=options.TooltipOpts(is_show=True),
toolbox_opts=options.ToolboxOpts(),
# 坐标轴类型
xaxis_opts=options.AxisOpts(type_="category"),
datazoom_opts=options.DataZoomOpts()
)
line.add_xaxis(xaxis_data=self.month.index.astype(str))
line.add_yaxis(series_name="数量", y_axis=b)
# 输出为html文件
line.render(".\电影月份分布情况.html")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
# 设置字体大小
font1 = {'family': 'simhei',
'weight': 'normal',
'size': 18, }
labels = self.country.index
sizes = self.country.values
explode = (0, 0, 0, 0, 0, 0, 0, 0, 0.1, 0, 0, 0)
plt.pie(sizes, labels=labels, explode=explode, autopct='%1.1f', shadow=False, startangle=150)
# 长宽相等
plt.axis('equal')
plt.title("电影国家分布图", font1)
# 添加图例
"""
loc = 'upper right' 位于右上角
bbox_to_anchor=[0.5, 0.5] # 外边距 上边 右边
ncol=2 分两列
borderaxespad = 0.3图例的内边距
"""
plt.legend(loc="upper right", fontsize=10, bbox_to_anchor=(1.1, 1.05), borderaxespad=0.3)
# 保存图片
plt.savefig(".\电影国家分布情况.jpg", dpi=200, bbox_inches='tight')
# 展示图片
plt.show()
b = []
for i in self.country.values:
b.append(int(i))
# 创建饼型图对象
pie = Pie()
pie.set_global_opts(title_opts=options.TitleOpts(title="国家分布统计图", subtitle="snowdream"),
legend_opts=options.LegendOpts(type_="scroll", pos_left="right", orient="vertical"))
# 鼠标悬浮在每一块饼上显示数据的格式
pie.set_series_opts(label_opts=options.LabelOpts(formatter="{b}: {c}"))
# 列表转换为字典
pie.add("", [list(z) for z in zip(self.country.index, b)])
pie.render(path=".\电影国家分布情况.html")
plt.figure(figsize=(16, 12))
plt.bar(self.actor.index, self.actor.values, width=0.5, color=['b', 'r', 'g', 'y', 'c', 'm', 'k'], alpha=1)
# 显示文字
plt.rcParams['font.sans-serif'] = ['SimHei']
# 设置字体大小
font1 = {'family': 'simhei',
'weight': 'normal',
'size': 18, }
# 设置x轴和y轴以及标题
plt.xlabel('明星', font1)
plt.ylabel('上榜次数', font1)
plt.title('电影明星上榜统计', font1)
# 设置数字标签
for a, b in zip(self.actor.index, self.actor.values):
plt.text(a, b + 0.05, '%.0f' % b, ha='center', va='bottom', fontsize=20)
# 保存图片
plt.savefig(".\电影明星上榜统计.jpg", dpi=200, bbox_inches='tight')
plt.show()
b = []
bar = Bar()
# 指定柱状图的横坐标
bar.add_xaxis(list(self.actor.index))
for i in self.actor.values:
b.append(int(i))
bar.add_yaxis("数量", b, color="green")
# 指定柱状图的标题
bar.set_global_opts(title_opts=options.TitleOpts(title="猫眼演员上榜统计图"),
datazoom_opts=options.DataZoomOpts(),
xaxis_opts=options.AxisOpts(type_="category"),
toolbox_opts=options.ToolboxOpts())
# 参数指定生成的html名称
bar.render(".\电影明星上榜统计.html")