由于疫情关系,宅在家里。记录一下作业,猫眼电影爬虫及分析,爬取猫眼电影数据,并对爬取的数据进行分析和展示。
猫眼电影爬虫
基于requests库和lxml库进去猫眼电影TOP100榜电影爬取,爬取地址为:https://maoyan.com/board/4
爬取的信息有:电影名字,主演名字,上映时间以及地点,猫眼评分得分,电影类型,电影时长。
电影数据保存为.csv格式。表头:电影名字(title),主演名字(author),上映时间以及地点(pub_time),猫眼评分得分(star),电影类型(style),电影时长(long_time)。
import requests
from lxml import etree
import csv
headers = { # 设置header
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'
}
def get_url(url): # top100电影获取
res = requests.get(url, headers=headers) # 请求
# print(res.text)
html = etree.HTML(res.text) # 获取网页源码
infos = html.xpath('//dl[@class="board-wrapper"]/dd') # 获取页面的10部电影,xpath
for info in infos:
title = info.xpath('div/div/div[1]/p[1]/a/text()')[0] # 电影名称
author = info.xpath('div/div/div[1]/p[2]/text()')[0].strip().strip('主演:') # 电影主演,strip()去掉空格
pub_time = info.xpath('div/div/div[1]/p[3]/text()')[0].strip('上映时间:') # 上映时间
star_1 = info.xpath('div/div/div[2]/p/i[1]/text()')[0] # 得分1(整数部分)
star_2 = info.xpath('div/div/div[2]/p/i[2]/text()')[0] # 得分2(小数部分)
star = star_1 + star_2 # 电影得分
movie_url = 'https://maoyan.com' + info.xpath('div/div/div[1]/p[1]/a/@href')[0] # 电影的详细页
# print(title,author,pub_time,star,movie_url)
get_info(movie_url, title, author, pub_time, star) # 进入电影的详细页爬取
print(‘保存完毕!’)
def get_info(url, title, author, pub_time, star): # 电影详细获取
res = requests.get(url, headers=headers)
html = etree.HTML(res.text)
style = html.xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[1]/text()')[0] # 电影类型
long_time = html.xpath('/html/body/div[3]/div/div[2]/div[1]/ul/li[2]/text()')[0].split('/')[1].strip().strip(
'分钟') # 电影时长
print(title, author, pub_time, star, style, long_time)
writer.writerow([title, author, pub_time, star, style, long_time]) # 写入数据
if __name__ == '__main__':
fp = open('F://maoyan.csv', 'w', newline='', encoding='utf-8') # 存储文件
writer = csv.writer(fp)
writer.writerow(['title', 'author', 'pub_time', 'star', 'style', 'long_time']) # 写入表头
urls = ['https://maoyan.com/board/4?offset={}'.format(str(i)) for i in range(0, 100, 10)] # url构造
for url in urls:
get_url(url)
数据分析
数据分析和展示时基于pandas和matplotlib。
分析了100部电影基本分析、演员出演这100部电影次数、电影的年份分布情况、电影的月份分布情况、电影的国家分布情况、前20部电影评分得分情况、电影的类型分布情况、电影的时长分布情况等。
- 演员出演这100部电影次数
(1)读取电影数据。
(2)取出主演(author)一列数据,循环对其进行字符串拼接。
(3)以“,”为分隔符进行切割,统计演员的个数以及名字、演员名字出现的次数(实现方法很多,这里使用的是Counter模块)。
(4)选取出演次数最多的六位演员。构造水平轴数据author,垂直轴数据count。
(5)使用matplotlib的pyplot绘制条形图,设置title,xlabel,ylabel。
import pandas as pd
from matplotlib import pyplot as plt
from collections import Counter
plt.rcParams['font.sans-serif'] = ['SimHei']
datas = pd.read_csv('maoyan.csv', encoding='utf-8')
s = ''
for i in range(99):
s += datas.iloc[i, 1]+','
s += datas.iloc[99, 1] # 防止最后的空格
# print(s)
authors = s.split(',')
# print(authors)
c = Counter(authors)
# print(c)
items = c.most_common(6)
print(items)
author = []
count = []
for item in items:
author.append(item[0])
count.append(item[1])
# print(author)
# print(count)
plt.bar(author, count, color='orange')
plt.title('出演次数最多的六位演员情况')
plt.xlabel('演员')
plt.ylabel('出演次数')
plt.show()
运行结果:
- 电影的年份分布情况
(1)读取电影数据。
(2)取出上映时间及地点(pub_time)一列数据。
(3)以“-”为分隔符进行切割,取出第一个元素,第二个元素是月份。存储为新的一列year。
(4)使用groupby对year这一列按照年份进行分组,并统计次数。
(5)数据的index转化为列表作为水平轴数据,数据转化为list作为垂直轴数据。
(6)使用matplotlib的pyplot绘制折线图,设置title,xlabel,ylabel。
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
datas = pd.read_csv('maoyan.csv', encoding='utf-8')
datas['year'] = datas['pub_time'].str.split('-').str[0]
datas['month'] = datas['pub_time'].str.split('-').str[1]
year = datas.groupby('year')['year'].count()
month = datas.groupby('month')['month'].count()
# print(list(year.index))
# print(list(year))
# print(month)
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(list(year.index), list(year))
plt.title('电影年份的分布情况')
plt.xlabel('年份')
plt.ylabel('电影数量')
plt.grid(alpha=0.4)
plt.show()
运行结果:
- 电影的国家分布情况
(1)读取电影数据。
(2)定义一个方法get_country(),对字符串进行切割,取出国家部分,中国香港返回中国,法国戛纳返回法国。
(3)取出上映时间及地点(pub_time)一列数据。
(4)分别进行get_country操作。存储为新的一列country。
(5)使用groupby对country这一列按照国家进行分组,并统计次数。
(6)数据的index转化为列表作为水平轴数据,数据转化为list作为垂直轴数据。
(7)使用matplotlib的pyplot绘制饼图,设置title,xlabel,ylabel。
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
datas = pd.read_csv('maoyan.csv', encoding='utf-8')
def get_country(s):
country = s.split('(')
if len(country) == 1:
return '中国'
else:
temp = country[1].strip(')')
if temp == '中国香港':
return '中国'
elif temp == '法国戛纳':
return '法国'
else:
return temp
datas['country'] = datas['pub_time'].map(get_country)
# print(datas['country'])
country = datas.groupby('country')['country'].count()
# print(country)
# print(list(country))
# print(list(country.index))
explods = [0, 0.2, 0, 0, 0, 0, 0, 0, 0]
plt.pie(list(country), labels=list(country.index), autopct='%1.1f%%', explode=explods)
plt.title('电影的国家分布情况')
plt.show()
运行结果:
- 电影的时长分布情况
(1)读取电影数据。
(2)取出电影时长(long_time)一列数据。
(3)按照10分钟为一个长度归类
(4)使用matplotlib的pyplot绘制柱状图,设置title,xlabel,ylabel。
import pandas as pd
from matplotlib import pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
datas = pd.read_csv('maoyan.csv', encoding='utf-8')
long_time = list(datas['long_time'])
# print(long_time)
d = 10
num_bins = int((max(long_time) - min(long_time)) / d)
plt.hist(long_time, range(min(long_time), max(long_time) + d, d), density=True)
plt.xticks(range(min(long_time), max(long_time) + d, d))
plt.grid(alpha=0.4)
plt.title('电影的时长分布情况')
plt.xlabel('电影时长')
plt.ylabel('比例')
plt.show()
运行结果:
【更多分析】
https://github.com/Tcrushes/crawler-analysis
【参考文献】
[1] matplotlib用户指南2020.04.08
[2] panluoluo. 猫眼电影爬虫及分析GitHub 2019.03.04