2019-11-08豆瓣网电影区信息爬取与数据分析

**

爬取豆瓣电影信息,分析近年电影行业的发展情况

**

好奇心爆棚的电影爱好者

平常的休闲娱乐中,肯定少不了看电影,每次想找找电影看的时候,都会到各大电影评分网站去搜高分、好评、热门的电影,防止自己踩坑,浪费时间、精力去熬一部烂片。电影评分较权威的豆瓣网是我日常求助的地方,出于对电影的热爱和对电影行业的发展状况和趋势,今天就尝试着通过爬虫爬取豆瓣网的电影数据,来分析一下不同的发展趋势。

爬虫区

import requests
from lxml import etree
import pandas as pd
import numpy as np
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
import time
import random
import re

由于豆瓣的电影区采用了Ajax技术来渲染页面信息,为方便爬取页面的电影信息,采用了selenium方法来模拟浏览器访问页面并对Ajax渲染操作,不断获取更新的电影信息。
另外还需requests、xpath、re、pandas、numpy处理爬取信息,再使用time、random作为辅助处理方法。

with open('user_agents.txt', 'r') as f:
    U=[]
    for line in f:
        U.append(f.readline())

user_agent.txt收集了大量不同的user-agent数据,用来编辑访问请求的请求头信息,模仿后期的浏览器浏览

url='https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0'
#豆瓣电影区,根据热门标签选电影的url
broser=webdriver.Chrome()
broser.get(url)
n=14	#每一次Ajax渲染出来20部电影信息,n是20次Ajax渲染,爬取电影数量为20*n
for i in range(n):
    wait=WebDriverWait(broser,20)
    button=wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'more')))
    button.click()
    time.sleep(1)
movie_photo=[item.get_attribute('src') for item in broser.find_elements_by_xpath('//div[@class="cover-wp"]/img')]
movie_url=[item.get_attribute('href') for item in broser.find_elements_by_class_name('item')]
broser.close()

通过selenium作n次Ajax渲染后,爬取页面源代码中电影的图片、url,并关闭浏览器,后续再对爬取到的信息过滤采集。

'''存储爬取电影图片可选'''
# for i in range(len(movie_photo)):
#     open('MoviePhoto\\'+str(i)+'.jpg','wb').write( requests.get(movie_photo[i],headers=headers).content )
output=[]	#用以整合所有类别的数据的列表
for i in range(len(movie_url)):
    useragent = U[random.randint(0, len(U)-1)].strip()
    #调用所有存储的user-agent头信息,加强每次访问电影地址时候的爬虫生命力
    headers = {
       # 设置请求头,如需建造更严谨、更安全的爬虫,可以设置多个User-Agent信息以便循环调用。
        'User-Agent': useragent
    }
    response=requests.get(movie_url[i],headers=headers)
    html=etree.HTML(response.text)	#将网页返回信息存储成html格式,允许xpath方法分析 
    name=html.xpath('//span[@property="v:itemreviewed"]/text()')#电影名
    director=html.xpath('//a[@rel="v:directedBy"]/text()')#导演
    #playwright=html.xpath('//span[@class="pl",contains(text(),"编剧")]//text()')
    actor=html.xpath('//span[@class="actor"]/span[@class="attrs"]//text()')#演员
    movie_class=html.xpath('//span[@property="v:genre"]//text()')#电影分类
    contry=re.compile('制片国家/地区:(.*?)
'
).findall(response.text)#制片国家\地区 releasedate=html.xpath('//span[@property="v:initialReleaseDate"]/@content')#上映日期 runtime=html.xpath('//span[@property="v:runtime"]/@content')#片长 grade=html.xpath('//strong[@class="ll rating_num"]/text()')#电影评分 try: #整合一部电影的所有信息 data=name+grade+[movie_class[0]]+[director[0]]+[actor[0]]+contry+[releasedate[0]]+runtime print(data) #便于运行程序时观察爬取的信息,便于后期修改 output.append(data) #整合入最终的输出列表 except: continue movie_data=pd.DataFrame(output,columns=['电影名','豆瓣分数','类别','导演','演员','制片国家/地区','上映日期','片长']) movie_data.to_csv('Douban_Movie.csv') #导出至目录下的Douban_Movie.csv文件

数据分析区

import pandas as pd
import numpy as np
import datetime
from matplotlib import pyplot as plt

movie=pd.read_csv('Douban_Movie.csv')
del movie['Unnamed: 0']	#删除第一列无意义列,是导出csv时的索引列
movie['片长']=movie['片长'].dropna()	#小部分电影唔片长信息

'''绘制电影片长分布图'''
plt.hist(movie['片长'],bins=np.arange(60,190,10))
plt.title('Histogram : The length of films')
plt.tight_layout()
plt.xlabel('The length of a film')
plt.ylabel('Numbers of films')
plt.show()

2019-11-08豆瓣网电影区信息爬取与数据分析_第1张图片

'''对数据集的 “上映日期” 列进行数据清洗,除去上映地点信息'''
def rebuild(x):
    x=x[:10]
    if '(' in x:
        start=x.index('(')
        x=x[:start]
    return x
movie['上映日期']=movie['上映日期'].apply(rebuild)
movie['上映日期']=pd.to_datetime(movie['上映日期'])	#修改类型datetime64[ns]
movie=movie.set_index('上映日期')	#将上映日期设置为索引
movie=movie.sort_index(ascending=False)
'''绘制不同制片国家\地区电影的平均分数'''
fig3=movie[['制片国家/地区','豆瓣分数']].groupby(by=movie['制片国家/地区']).mean()
#print(fig3)
# plt.hist(fig3.index)              #需要画出直方图,需要修正中文字体显示
# plt.xlabel('moviemaking country/district')
# plt.ylabel('Mean grade')
# plt.title('Histogram : films mean grade in different moviemaking country/district')
# plt.show()

此处尚未解决中文作图的报错,所以暂时缺图

print(fig3.describe())

count 58.000000
mean 6.740270
std 0.938747
min 3.600000
25% 6.300000
50% 6.687500
75% 7.375000
max 9.100000

'''绘制近年不同月份下上映电影的平均分'''
# mean_grade_month=movie.resample('MS').mean()      # 绘制近年不同月份上映电影的平均分数
# plt.plot(mean_grade_month['豆瓣分数'])
# plt.xlabel('Year-Month')
# plt.ylabel('Mean Grade')
# plt.title('The mean grade of films in recent years')
# plt.show()

2019-11-08豆瓣网电影区信息爬取与数据分析_第2张图片

print(movie[movie['豆瓣分数']>8].count())

豆瓣分数大于8分的电影数为22部,热门标签下爬取的电影总数为254部,占比8.67%。

数据分析

作为数据分析初学者,我会尽我所能尝试分析,【此篇文章的所有分析观点都仅代表文章原创者的现时观点,如有观点不同,欢迎评论,我也很愿意接受不同角度的分析观点。】
1、相比于以前电影片长集中在100分钟内,如今电影的发行,片长都集中在100分钟至200分钟区段,叙事时间的延长利于讲好、讲深每个故事,更加能够满足观影者对电影全景的展示的需求,也更能让故事的观点升华到更高的深度,触动观影者。
2、根据获取的不同制片国家\地区的电影平均分,发现电影工业发展也同样趋于全球化,多方合作制作电影是未来的大趋势,将各方的优势集中融合,能提升电影的视觉效果和叙事能力。各制片国家\地区的电影平均分在6.740270,分数集中在6.30~7.38区间,热门标签采集的电影数据下,最大评分9.1。高分电影还是占少数,只有8.67%。
3、根据热门标签下爬取的电影信息,发现电影平均分高的上映日期集中在年末年初。
【由于采集样本的数量还是很少,本文章分析的观点仍是很片面的,不是成熟的、专业的数据分析】
因为该文章只是初试数据分析,也是初始检验这个小项目成果的试验品,后期会重新整理修改爬取电影的数目,再从更多方面、角度来分析电影工业的发展状况。

你可能感兴趣的:(Python,爬虫,数据分析,Python)