作业来源:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/3159
最近做了一个豆瓣电影的爬虫并且进行了简单的数据分析。
主要是对豆瓣电影选取豆瓣高分,按评价排序的顺序进行电影信息的爬取。
需要对该页面的电影信息进行爬取,获得电影名称,评分,地区,语言,导演,演员,时长,评价人数,电影类型等信息。这只是一个索引页,完整的电影信息在每一个电影链接里面。我们需要通过获取该索引页,然后解析索引页获取每个电影的详细链接,然后再从详细链接中获取电影信息。首先分析索引页。
在索引页我们按F12打开开发者工具,点击XHR标签,因为他是通过ajax加载获取更多的电影信息的。在开发者工具中我们可以看到索引页中的信息是一个json格式的数据。里面包含了每部电影详情的链接。所以先获取这些链接。
# 获取索引页
def get_index_page(html):
try:
response = requests.get(url=html, headers=headers, cookies=cookies)
response.encoding = 'utf-8'
if response.status_code == 200:
return response.text
return None
except RequestException:
print('获取索引页错误')
time.sleep(3)
return get_index_page(html)
# 解析索引页
def parse_index_page(html):
html = get_index_page(html)
html = html[12:-1]
data = json.loads(html)
id_list = []
if data:
for item in data:
id_list.append(item['url'])
return id_list
获得了电影详情链接之后,即可进行解析详情页信息。详情页我们需要的信息都在网页源码中,我们只需要对网页源码使用正则提取我们需要的信息即可。
# 获取详情页
def get_detail_page(html):
try:
response = requests.get(url=html, headers=headers, cookies=cookies)
response.encoding = 'utf-8'
if response.status_code == 200:
return response.text
return None
except RequestException:
print('获取详情页错误')
time.sleep(3)
return get_detail_page(html)
# 解析详情页
def parse_detail_page(data):
html = get_detail_page(data)
info = []
# 获取电影名称
name_pattern = re.compile('<span property="v:itemreviewed">(.*?)</span>')
name = re.findall(name_pattern, html)
info.append(name[0])
# 获取评分
score_pattern = re.compile('rating_num" property="v:average">(.*?)</strong>')
score = re.findall(score_pattern, html)
info.append(score[0])
# 获取导演
director_pattern = re.compile('rel="v:directedBy">(.*?)</a>')
director = re.findall(director_pattern, html)
info.append(director)
# 获取演员
actor_pattern = re.compile('rel="v:starring">(.*?)</a>')
actor = re.findall(actor_pattern, html)
info.append(actor)
# 获取年份
year_pattern = re.compile('<span class="year">((.*?))</span>')
year = re.findall(year_pattern, html)
info.append(year[0])
# 获取类型
type_pattern = re.compile('property="v:genre">(.*?)</span>')
type = re.findall(type_pattern, html)
info.append(type[0].split(' /')[0])
# 获取时长
try:
time_pattern = re.compile('property="v:runtime" content="(.*?)"')
time = re.findall(time_pattern, html)
info.append(time[0])
except:
info.append('1')
# 获取语言
language_pattern = re.compile('pl">语言:</span>(.*?)<br/>')
language = re.findall(language_pattern, html)
info.append(language[0].split(' /')[0])
# 获取评价人数
comment_pattern = re.compile('property="v:votes">(.*?)</span>')
comment = re.findall(comment_pattern, html)
info.append(comment[0])
# 获取地区
area_pattern = re.compile(' class="pl">制片国家/地区:</span>(.*?)<br/>')
area = re.findall(area_pattern, html)
info.append(area[0].split(' /')[0])
return info
在进行数据分析之前我把之前输出的CSV文件另存为了EXCEL文件,并且加了一列名次信息。数据展示如下图
了解评分与排名的关系
plt.figure(figsize=(14,6))
plt.subplot(1,2,1) #一行两列第一个图
plt.scatter(score,num)
plt.xlabel('score')
plt.ylabel('num')
plt.subplot(1,2,2)
plt.hist(score,bins = 15) #bins指定有几条柱状
plt.xlabel('score')
plt.show()
了解评论人数与排名的关系
plt.figure(figsize=(14,6))
plt.subplot(1,2,1) #一行两列第一个图
plt.scatter(comment,num)
plt.xlabel('comment')
plt.ylabel('num')
plt.subplot(1,2,2)
plt.hist(comment)
plt.xlabel('comment')
plt.show()
了解电影时长与排名的关系
for i in range(len(time)):
if time[i] == 60: #数据中有一个时长1分钟的,是错误数据需要剔除
del time[i]
del num[i]
plt.figure(figsize=(14,6))
plt.subplot(1,2,1) #一行两列第一个图
plt.scatter(time,num)
plt.xlabel('time')
plt.ylabel('num')
plt.subplot(1,2,2)
plt.hist(time)
plt.xlabel('time')
plt.show()
了解上映年份与排名的关系
plt.figure(figsize=(14,6))
plt.subplot(1,2,1) #一行两列第一个图
plt.scatter(year,num)
plt.xlabel('year')
plt.ylabel('num')
plt.subplot(1,2,2)
plt.hist(year)
plt.xlabel('year')
plt.show()
了解上映地区影片数量
area = area.apply(pd.value_counts).fillna('0')
area = area.astype(int)
area = area.apply(lambda x: x.sum(),axis = 1)
area_c = pd.DataFrame(area, columns = ['counts'])
area_c.sort_values(by = 'counts',ascending = False).plot(kind ='bar', figsize = (10,10))
plt.show()
了解语言影片数量
language = language.apply(pd.value_counts).fillna('0')
language = language.astype(int)
language = language.apply(lambda x: x.sum(),axis = 1)
language = pd.DataFrame(language, columns = ['counts'])
language.sort_values(by = 'counts',ascending = False).plot(kind ='bar', figsize = (10,10))
plt.show()
了解类型影片数量
categroy = categroy.apply(pd.value_counts).fillna('0')
categroy = categroy.astype(int)
categroy = categroy.apply(lambda x: x.sum(),axis = 1)
categroy = pd.DataFrame(categroy, columns = ['counts'])
categroy.sort_values(by = 'counts',ascending = False).plot(kind ='bar', figsize = (10,10))
plt.show()
将地区,语言,类型三类信息加起来制作词云
from wordcloud import WordCloud
language = language.to_string(header=False, )
area = area.to_string(header=False, )
categroy = categroy.to_string(header=False, )
data = language+area+categroy
wordcloud = WordCloud(font_path='./fonts/simhei.ttf',background_color='white',width=5000, height=3000, margin=2).generate(data)
plt.figure(figsize=(16,8))
plt.imshow(wordcloud)
plt.axis('off')
plt.show()
数据分析图片如下: