Python爬取豆瓣电影TOP250

爬取目标

爬取豆瓣电影TOP250信息并简单分析

网络请求及解析库

Requests 【中文使用文档】
Beautiful Soup 4.2.0 【中文使用文档】

加载所需工具包

import re #用于传入正则表达式作为参数
import numpy as np 
import pandas as pd 
from bs4 import BeautifulSoup 
import requests
import time 

查看网页

由于豆瓣某些电影链接需要登录后才能查看,所以我用自己的账号登录豆瓣后,获取网站的cookie,将cookie添加到requests的session中,将cookie持久化,这样每次访问网站都会带上这个cookie。

Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。

按F12进入调试模式在Network中,F5刷新后一般在左侧第一个网址内的Requset Headers可以查到看网站的cookie。

获取cookie

查看https://movie.douban.com/top250下方页码条,可看到该网址共有10个页面,点击第2页,显示网址为https://movie.douban.com/top250?start=25&filter=,根据网址结构,可以看出只需修改start=末尾的数值,不断访问新的页面就可以爬取到所有页面信息。

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)'}
#模拟浏览器访问网页
http_session = requests.session()
#定义了http_session用来作为我们的session
cookie = 'll="118254"; bid=JSyRhtte0VA; __yadk_uid=0kfCKOtzBXvPqtiMypgQ0uK5r2055OMk; ct=y; viewed="24862771_7056708_3595095_25775696_25833225_20429677"; gr_user_id=000a52d9-7093-4cdc-902d-452ba224da82; ps=y; ue="29288849@qq.com"; dbcl2="182571279:h94qNxNP398"; ck=kT5x; _pk_ref.100001.4cf6=%5B%22%22%2C%22%22%2C1533818089%2C%22https%3A%2F%2Fwww.douban.com%2Faccounts%2Flogin%3Fredir%3Dhttps%253A%252F%252Fmovie.douban.com%252F%22%5D; _vwo_uuid_v2=D5BD0897E8A4014E0136ABC56424C8BF4|96af10151a86ee46b335061264ea143a; ap=1; _pk_id.100001.4cf6=fdb804e89a884d46.1533703967.11.1533818851.1533806907.; _pk_ses.100001.4cf6=*; __utma=30149280.642519294.1533296417.1533806807.1533817228.17; __utmb=30149280.6.10.1533817228; __utmc=30149280; __utmz=30149280.1533817228.17.7.utmcsr=accounts.douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/safety/unlock_sms/resetpassword; __utmv=30149280.18257; __utma=223695111.1629547352.1533703967.1533806807.1533818089.12; __utmb=223695111.0.10.1533818089; __utmc=223695111; __utmz=223695111.1533818089.12.3.utmcsr=douban.com|utmccn=(referral)|utmcmd=referral|utmcct=/accounts/login; push_noty_num=0; push_doumail_num=0'
#从浏览器中获取的cookie
cookies = {i.split('=')[0]:i.split('=')[1] for i in cookie.split(';')}
#将cookies转换成requests能够接受的字典格式
requests.utils.add_dict_to_cookiejar(http_session.cookies,cookies)
#将cookie添加到requests提供的http_session里面
urls = ['https://movie.douban.com/top250?start=%i' %i for i in range(0,250,25)]
#需爬取所有页面列表

点击https://movie.douban.com/top250内排名第一的电影肖申克的救赎进入网址https://movie.douban.com/subject/1292052/里面就有我们所需的电影信息

所需爬取的电影信息

怎么获取这个网址呢?

通过鼠标移动到页面超链接上,右键点选检查,进入调试模式后,会自动定位到该内容所在节点,查看其他电影超链接,发现每一个电影的超链接网址都在<li>节点下的<div class='hd'>子节点下的第一个<a>标签的href属性。使用BeautifulSoup里.find方法搜索符合调节的标签tag

也可以通过BeautifulSoup里.select方法,传入字符串参数,即可使用CSS选择器的语法找到标签tag,CSS选择器是一种单独的文档搜索语法,参考文档

查找内容所在tag

页面电影的链接
#抓取每一个电影条目的网址链接
movie_hrefs=[]
def get_movie_href(u):
    response = http_session.get(u,headers = headers)
    soup = BeautifulSoup(response.text,'lxml')
    movie_href = soup.find_all('div',class_='hd')
    for i in movie_href:
        movie_hrefs.append(i.find('a')['href'])

for url in urls:
    get_movie_href(url)

提取所需电影信息

#提取每一部电影的所需信息,保存成字典格式,存储在all_movie列表中
all_movie=[]
def get_movie_info(url):
    response = http_session.get(url,headers = headers)
    soup = BeautifulSoup(response.text,'lxml')
    movie = {}
    info = soup.find('div',id='info').get_text()
    for data in info.split('\n')[1:9]:
        movie[data.split(':')[0]] = data.split(':')[1]
    movie['电影名称']=soup.find('span',property="v:itemreviewed").text
    movie['豆瓣评分']=float(soup.find('strong',property="v:average").text)
    movie['豆瓣评论数']=int(soup.find('span',property="v:votes").text)
    movie["r1"]=float(soup.find(text = re.compile('1星')).find_next(text = re.compile('%'))[:-1])*0.001
    #找到包含‘1星’字符文档的所在节点之后包含‘%’字符的文档TEXT,示例为0.2%,将其转换成浮点型数字
    movie["r2"]=float(soup.find(text = re.compile('2星')).find_next(text = re.compile('%'))[:-1])*0.001
    movie["r3"]=float(soup.find(text = re.compile('3星')).find_next(text = re.compile('%'))[:-1])*0.001
    movie["r4"]=float(soup.find(text = re.compile('4星')).find_next(text = re.compile('%'))[:-1])*0.001
    movie["r5"]=float(soup.find(text = re.compile('5星')).find_next(text = re.compile('%'))[:-1])*0.001
    all_movie.append(movie)

for href in movie_hrefs:
    get_movie_info(href)
    time.sleep(2)

将爬取到的信息保存至桌面存为CSV文件

df = pd.DataFrame(all_movie)
#转换成DataFrame格式以便后面分析
import os
os.chdir('C:\\Users\\Administrator\\Desktop')
df.to_csv('豆瓣TOP250电影信息.csv')
爬取信息用Excel文件打开

对爬取的信息进行分析

分析各地区TOP250电影数占比,哪个国家的电影最受欢迎
分析各电影类型TOP250电影数占比,哪个类型的电影最欢迎
分析top250电影,哪些导演的电影最多,评分较高

数据处理
  • 由于爬取时已经筛选过数据,保证数据完整性,此处省略了数据清洗过程(缺失值处理,去除异常值)
    首先提取每个地区的电影数量,由于有些电影是联合拍摄,同一部电影有多个地区参与。同理,同一部电影也有多种类型及多个导演。
#将爬取电影所有地区,类型,导演去重后导入列表
county_lst = []
for i in df['制片国家/地区'].str.replace(' ','').str.split('/'):
    county_lst.extend(i)
county_lst = list(set(county_lst))

type_lst = []
for i in df['类型'].str.replace(' ','').str.split('/'):
    type_lst.extend(i)
type_lst = list(set(type_lst))

dir_lst = []
for i in df['导演'].str.replace(' ','').str.split('/'):
    dir_lst.extend(i)
dir_lst = list(set(dir_lst))
#判断各地区,各类型,各导演 影片个数,最高分影片及豆瓣评分
def f1(col,i):
    data = {}
    dfi = df[df[col].str.contains(i)]
    data[col] = i
    data['个数'] = len(dfi)
    data['豆瓣最高分'] = dfi['豆瓣评分'].max()
    data['最高分影片'] = dfi[dfi['豆瓣评分'] == dfi['豆瓣评分'].max()].iloc[0]['电影名称']
    return(data)

data_county = []
for i in county_lst:
    data_county.append(f1('制片国家/地区',i))
df_county = pd.DataFrame(data_county)
df_county.sort_values(by='个数',ascending = False,inplace = True)

data_type = []
for i in type_lst:
    data_type.append(f1('类型',i))
df_type = pd.DataFrame(data_type)
df_type.sort_values(by='个数',ascending = False,inplace = True)

data_dir = []
for i in dir_lst:
    data_dir.append(f1('导演',i))
df_dir = pd.DataFrame(data_dir)
df_dir.sort_values(by=['个数','豆瓣最高分'],ascending = False,inplace = True)
df_dir = df_dir[0:30]

#上映日期因为有不同地区的上映日期,已最早的上映日期为电影的实际上映年限
year = []
pattern = re.compile(r'\d{4}')
for i in df['上映日期'].str.findall(pattern):
    year.append(min(i))
df['上映年限'] = year

绘制表格
  • 各类型评分最高影片,看看和你心目中的榜单是否和豆瓣网友一致
各类型最高评分影片
  • 各类型占比,可以看出大家基本偏爱剧情片,其次是爱情和喜剧


    各类型占比
  • 榜单上的导演都符合大家对知名导演的预期,豆瓣网友比较偏爱宫崎骏的动画片


    各导演最高评分影片
  • 刘镇伟导演的这3部影片,由于在国内影响深远,导致刘镇伟也在榜单中,其实他拍了许多烂片(笑)


    image.png
  • 各地区排行,可以看出美国所占比例遥遥领先,也由于其电影工业实力强大和起步早,其次是英国和日本


    各地区占比
  • 神作(好电影最多)频出的几年为1994,2010,2004,2010


    各年限电影数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 207,248评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,681评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,443评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,475评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,458评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,185评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,451评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,112评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,609评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,083评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,163评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,803评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,357评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,357评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,590评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,636评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,925评论 2 344

推荐阅读更多精彩内容