开场白:本文中使用的语言为 Python 3
,其中主要用了 BeautifulSoup、Numpy、Pandas、Matplotlib和WordCloud
等几个数据分析常用库,过程尽量写的详(luo)细(suo)些,希望能给和我一样的数据分析初学者一些思路,如果文中有错误请告诉我。同时欢迎各种关于代码、分析思路、语言组织、排版等等的意见建议。非常感谢!文章很长,如果只看部分内容请戳目录。
豆瓣电影Top250数据分析
不知道看什么电影时,就会习惯性的看看豆瓣,但落伍的我直到最近才发现还有个神奇的豆瓣电影Top250榜单!它是根据每部影片看过的人数以及该影片所得的评论等综合数据排名的,同时还考虑了人群的广泛适应性和持续关注度。好高大上的算法!
那么得出的这个排行榜和电影评分及评论人数有怎样的关系?
和上映时间关系大不大?
哪种类型的电影上榜最多呢?
哪些国家、导演、主演最受欢迎?
片长多长时间最合适?
带着这些疑问,不妨进行一下数据分析。
数据收集
先来看一下页面:
我们抓取排名、电影名、导演、主演、上映日期、制片国家/地区、类型,评分、评论数量、一句话评价以及电影链接,其中导演和主演分别取一位。
用开发者工具看一下源代码:
大部分信息比较好抓取,只有电影信息在标签 <p>
中都写在了一起,可通过 strip()
函数去除两侧空格, split()
函数分裂字符串来取得具体信息。
选用Python 3,引入 url.request
和 BeautifulSoup
库来抓取页面信息。代码如下:
import urllib.request as urlrequest
from bs4 import BeautifulSoup
top250_url = "https://movie.douban.com/top250?start={}&filter="
with open('top250_f1.csv','w',encoding='utf8') as outputfile:
outputfile.write("num#title#director#role#init_year#area#genre#rating_num#comment_num#comment#url\n")
for i in range(10):
start = i*25
url_visit = top250_url.format(start)
crawl_content = urlrequest.urlopen(url_visit).read()
http_content = crawl_content.decode('utf8')
soup = BeautifulSoup(http_content,'html.parser')
all_item_divs = soup.find_all(class_='item')
for each_item_div in all_item_divs:
pic_div = each_item_div.find(class_='pic')
num = pic_div.find('em').get_text() #排名
href = pic_div.find('a')['href'] #电影链接
title = pic_div.find('img')['alt'] #电影名称
bd_div = each_item_div.find(class_='bd')
infos = bd_div.find('p').get_text().strip().split('\n')
infos_1 = infos[0].split('\xa0\xa0\xa0')
director = infos_1[0][4:].rstrip('...').rstrip('/').split('/')[0] #导演
role = str(infos_1[1:])[6:].split('/')[0] #主演
infos_2 = infos[1].lstrip().split('\xa0/\xa0')
year = infos_2[0] #上映时间
area = infos_2[1] #国家/地区
genre = infos_2[2:] #电影类型
star_div = each_item_div.find(class_='star')
rating_num = star_div.find(class_='rating_num').get_text() #评分
comment_num = star_div.find_all('span')[3].get_text()[:-3] #评价数量
quote = each_item_div.find(class_='quote')
inq = quote.find(class_='inq').get_text() #一句话评价
outputfile.write('{}#{}#{}#{}#{}#{}#{}#{}#{}#{}#{}\n'.format(num,title,director,role,year,area,
genre,rating_num,comment_num,inq,href))
本来只打算抓这些数据,分析时发现有些主演名字显示的不完全,看来还要再抓一下每个电影页面。在上面抓取的url信息中截取出id编号,用豆瓣API接口。
import urllib
import urllib.request as urlrequest
import json
import time
import random
import pandas as pd
df = pd.read_csv("top250_f1.csv",sep = "#", encoding = 'utf8')
urlsplit = df.url.str.split('/').apply(pd.Series)
id_list = list(urlsplit[4])
num=0
IP_list = [ ] #这里写几个可用的IP地址和端口号,只抓250个页面,有两三个IP就够了。
IP = random.chioce(IP_list)
with open('top250_f2.csv', 'w',encoding='utf8') as outputfile:
outputfile.write("num#rank#alt_title#title#pubdate#language#writer#director#cast#movie_duration#year#movie_type#tags#image\n")
proxy = urlrequest.ProxyHandler({
'https': 'IP'})
opener = urlrequest.build_opener(proxy)
opener.addheaders = [('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4)
AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.1 Safari/603.1.30')]
urlrequest.install_opener(opener)
for id in id_list:
url_visit = 'https://api.douban.com/v2/movie/{}'.format(id)
crawl_content = urlrequest.urlopen(url_visit).read()
json_content = json.loads(crawl_content.decode('utf-8'))
rank = json_content['rating']['average']
alt_title = json_content['alt_title']
image = json_content['image']
title = json_content['title']
pubdate = json_content['attrs']['pubdate']
language = json_content['attrs']['language']
try:
writer = json_content['attrs']['writer']
except:
writer = 'None'
director = json_content['attrs']['director']
cast = json_content['attrs']['cast']
movie_duration = json_content['attrs']['movie_duration']
year = json_content['attrs']['year']
movie_type = json_content['attrs']['movie_type']
tags = json_content['tags']
num = num +1
outputfile.write("{}#{}#{}#{}#{}#{}#{}#{}#{}#{}#{}#{}#{}#{}\n".format(num,rank,alt_title,title,pubdate,language,writer,
director,cast,movie_duration,year,movie_type,tags,image))
time.sleep(1)
OK,数据抓取完毕,看一下抓取结果。先来看爬取Top250页面的信息:
import numpy as ny
import pandas as pd
df_1 = pd.read_csv("top250_f1.csv",sep = "#", encoding = 'utf8')
df_1.head()
num | title | director | role | init_year | area | genre | rating_num | comment_num | comment | url | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 肖申克的救赎 | 弗兰克·德拉邦特 Frank Darabont | 蒂姆·罗宾斯 Tim Robbins | 1994 | 美国 | [‘犯罪 剧情’] | 9.6 | 861343 | 希望让人自由。 | https://movie.douban.com/subject/1292052/ |
1 | 2 | 霸王别姬 | 陈凯歌 Kaige Chen | 张国荣 Leslie Cheung | 1993 | 中国大陆 香港 | [‘剧情 爱情 同性’] | 9.5 | 618349 | 风华绝代。 | https://movie.douban.com/subject/1291546/ |
2 | 3 | 这个杀手不太冷 | 吕克·贝松 Luc Besson | 让·雷诺 Jean Reno | 1994 | 法国 | [‘剧情 动作 犯罪’] | 9.4 | 824694 | 怪蜀黍和小萝莉不得不说的故事。 | https://movie.douban.com/subject/1295644/ |
3 | 4 | 阿甘正传 | Robert Zemeckis | Tom Hanks | 1994 | 美国 | [‘剧情 爱情’] | 9.4 | 703838 | 一部美国近现代史。 | https://movie.douban.com/subject/1292720/ |
4 | 5 | 美丽人生 | 罗伯托·贝尼尼 Roberto Benigni | 罗伯托·贝尼尼 Roberto Beni…’] | 1997 | 意大利 | [‘剧情 喜剧 爱情 战争’] | 9.5 | 410615 | 最美的谎言。 | https://movie.douban.com/subject/1292063/ |
再看一下抓取单个页面的信息:
df_2 = pd.read_csv("top250_f2.csv",sep = "#", encoding = 'utf8')
df_2.head()
num | rank | alt_title | title | pubdate | language | writer | director | cast | movie_duration | year | movie_type | tags | image | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 9.6 | 肖申克的救赎 / 月黑高飞(港) | The Shawshank Redemption | [‘1994-09-10(多伦多电影节)’, ‘1994-10-14(美国)’] | [‘英语’] | [‘弗兰克·德拉邦特 Frank Darabont’, ‘斯蒂芬·金 Stephen King’] | [‘弗兰克·德拉邦特 Frank Darabont’] | [‘蒂姆·罗宾斯 Tim Robbins’, ‘摩根·弗里曼 Morgan Freeman’… | [‘142 分钟’] | [‘1994’] | [‘犯罪’, ‘剧情’] | [{‘count’: 178370, ‘name’: ‘经典’}, {‘count’: 15… | https://img3.doubanio.com/view/movie_poster_co… |
1 | 2 | 9.5 | 再见,我的妾 | 霸王别姬 | [‘1993-01-01(香港)’] | [‘汉语普通话’] | [‘芦苇 Wei Lu’, ‘李碧华 Lillian Lee’] | [‘陈凯歌 Kaige Chen’] | [‘张国荣 Leslie Cheung’, ‘张丰毅 Fengyi Zhang’, ‘ |