Python爬虫实战(1)requests爬取豆瓣电影TOP250

前言

  • 蛋肥是python小白,自学python两周多,纯属爱好,代码或思路比较稚嫩,文章主要用来记录和总结,还请代码大神一笑而过多多指教。
  • 豆瓣电影提供了api(现在似乎不能用了),总之尽量将爬取的数据先保存起来,避免过多请求,浪费服务器资源(反正也会被403)。

准备

爬取时间:2020/11/25
系统环境:Windows 10
所用工具:Jupyter Notebook\Python 3.0
涉及的库:requests\lxml\pandas\matplotlib\numpy

获取基础数据

蛋肥想法:先将电影名称、原名、评分、评价人数、分类信息从网站上爬取下来。

豆瓣电影TOP250网址
https://movie.douban.com/top250?start=0
参考资料
xPath用法总结整理
时下流行的浏览器User-Agent大全
常见的HTTP状态码(HTTP Status Code)
Chrome浏览器F12开发者工具简单使用

import requests
from lxml import etree

#写一个函数去爬取豆瓣TOP250的数据
def getinfo(list,xpath):
    list=[]
    #伪造请求头
    headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"}
    #循环解决翻页问题
    for i in range(0,10):
        link="https://movie.douban.com/top250?start="+str(i*25)
        r=requests.get(link,headers=headers,timeout=10)
        print(str(i+1),r.status_code)
        #爬取对应xpath下的数据并存入列表
        html=etree.HTML(r.text)
        list_transit=html.xpath(xpath+'/text()')
        list.extend(list_transit)
    return(list)

#通过函数爬取数据放入列表,依次为电影名称、原名、评分、评价人数、分类信息
film_title=getinfo(list,'//div[@class="hd"]/a/span[1]')
film_origin=getinfo(list,'//div[@class="hd"]/a/span[2]')
film_rate=getinfo(list,'//div[@class="star"]/span[2]')
film_num=getinfo(list,'//div[@class="star"]/span[4]')
film_sort=getinfo(list,'//div[@class="bd"]/p')

数据预处理

蛋肥想法:print数据列表后发现电影原名、分类信息等存在不需要的字符,需预先处理;同时因为后续想做一个豆瓣电影TOP250的维度分布图,而同一电影存在多个发行国家、类型(如“法国 美国 / 剧情 动作 犯罪”),为了简(偷)便(懒),这里均取第一个作为记入的数据;最后将数据保存为xlsx。

参考资料
python怎样去除列表中的空列表
python列表切片和嵌套列表取值操作详解

#新建列表分别保存原始数据,避免与豆瓣403后无法获取数据,也避免原始数据受到误操作的影响
film_title_save=film_title.copy()
film_origin_save=film_origin.copy()
film_rate_save=film_rate.copy()
film_num_save=film_num.copy()
film_sort_save=film_sort.copy()

#去除电影原名中不需要的字符
for i in range(len(film_origin_save)):
    film_origin_save[i]=film_origin_save[i].replace("\xa0","").replace("/","",1).replace(" ","")

#去除电影分类中不需要的字符、去除头尾空格、按"/"将字符串划分
for i in range(len(film_sort_save)):
    film_sort_save[i]=film_sort_save[i].replace("\xa0","").replace("\n","").strip().split("/",2)
#经观察,列表中['']的出现并无规律,所以先去掉['']后再切片
while [''] in film_sort_save:
    film_sort_save.remove([''])
film_sort_save=film_sort_save[1::2]
#取发行国家、电影类型的第一个
for i in range(len(film_sort_save)):
    film_sort_save[i][1]=film_sort_save[i][1].split(" ")[0]
    film_sort_save[i][2]=film_sort_save[i][2].split(" ")[0]
#['1961(中国大陆) ', '', ''], ['1983(中国大陆)', '中国大陆', '动画']这两条数据存在异常,再次处理
for i in range(len(film_sort_save)):
    if(film_sort_save[i][0]=="1983(中国大陆)"):
        film_sort_save[i][0]="1983"
    elif(film_sort_save[i][0]=="1961(中国大陆) "):
        film_sort_save[i][0]="1961"
        film_sort_save[i][1]="中国大陆"
        film_sort_save[i][2]="动画"

#现在将所有数据存入表中保存,先对分类信息做拆分
film_sort_save_time=[x[0] for x in film_sort_save]
film_sort_save_country=[x[1] for x in film_sort_save]
film_sort_save_type=[x[2] for x in film_sort_save]

#保存并导出数据为xlsx
import pandas as pd
df=pd.DataFrame([film_title_save,film_origin_save,film_rate_save,film_num_save,film_sort_save_time,film_sort_save_country,film_sort_save_type],
                index=["电影名称","电影原名","评分","评价人数","发行时间","发行国家","电影类型"])
df.T.to_excel(r"C:\Users\Archer\Desktop\爬取数据.xlsx",index=False)
保存到本地的部分数据

数据可视化

蛋肥想法:蛋肥想知道在豆瓣电影TOP250中年份、国家、类型的维度数据,为了练手,使用刚才保存成xlsx的数据,并分别画成雷达图、柱形图、扇形图。

参考资料
pandas数据类型转换
python正确复制列表的方法

#导入excel数据
import pandas as pd
df=pd.read_excel(r"C:\Users\Archer\Desktop\爬取数据.xlsx")

#发行国家,分类、计数、排序后取前10
country=df.groupby("发行国家").count().sort_values(by=["电影名称"],ascending=False)[:10]
#发行时间,转化int、按区间计数
df["发行时间"]=df["发行时间"].astype(int)
time_slice=["1930-1940","1940-1950","1950-1960","1960-1970","1970-1980","1980-1990","1990-2000","2000-2010","2010-2020"]
data_time=[]
for i in range(0,9):
    data=df[(df["发行时间"]>(1940+(i-1)*10))&(df["发行时间"]<=(1940+i*10))]["电影名称"].count()
    data_time.append(data)
#电影类型,分类、计数、排序
form=df.groupby("电影类型").count().sort_values(by=["电影名称"],ascending=False)
#直接用index做label画扇形图有重叠,稍微处理下
pie_label=list(form.index)
pie_label[-4:]=["","","",""]

import matplotlib.pyplot as plt
import numpy as np
#画图四件套:显示、矢量、中文、负号
%matplotlib inline
%config InlineBackend.figure_format="svg"
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

#绘制画布尺寸
plt.figure(figsize=(12,5))
#设置发行国家子画布(n行,n列,该画布位置)
plt.subplot(1,1,1)
#设置标题
plt.title("发行国家前10 柱形图")
#设置横纵坐标轴标签
plt.xlabel("发行国家")
plt.ylabel("电影数量")
#设置数据
x=list(range(0,10))
y=country["电影名称"]
plt.xticks(x,country.index)
#绘制柱形图
plt.bar(x,y)
#添加数据标签 plt.text(横坐标,纵坐标,值,水平对齐方式,垂直对齐方式,字号)
for a,b in zip(x,y):
    plt.text(a,b,b,ha="center",va="bottom",fontsize=10)
#导出图表
plt.savefig(r"C:\Users\Archer\Desktop\my_fig_1.png")

#绘制画布尺寸
plt.figure(figsize=(12,5))
#设置发行时间子画布(n行,n列,该画布位置,是否为极坐标系)
polar=plt.subplot(1,2,1,polar="true")
#设置标题
plt.title("发行时间 雷达图",va="bottom")
#在指定的间隔内返回均匀的角度
angles=np.linspace(0,2*np.pi,9,endpoint=False)
#完成数据拼接,实现闭环
angles=np.concatenate((angles,[angles[0]]))
data_time=np.concatenate((data_time,[data_time[0]]))
#设置横坐标轴
plt.xticks(angles,time_slice)
#设置y轴范围
plt.ylim(0,100)
#绘制雷达图
plt.polar(angles,data_time,marker="o",markersize=4,markerfacecolor='white')
#设置0°的位置及极坐标旋转方向
polar.set_theta_zero_location("N")
polar.set_theta_direction("clockwise")
#填充颜色
plt.fill(angles,data_time,color="#7bbfea")

#设置电影类型子画布(n行,n列,该画布位置,是否为极坐标系)
polar=plt.subplot(1,2,2)
#设置标题
plt.title("电影类型 扇形图")
#绘制扇形图
plt.pie(form["电影名称"],labels=pie_label)
#添加注释去解释设为空的label,annotate(注释文本,起点位置,文本位置,箭头设置)
plt.annotate("传记",xy=(0.9,-0.11),xytext=(1.5,-0.2),arrowprops=dict(arrowstyle="-"))
plt.annotate("冒险",xy=(0.9,-0.07),xytext=(1.5,-0.1),arrowprops=dict(arrowstyle="-"))
plt.annotate("儿童",xy=(0.9,-0.035),xytext=(1.5,-0.005),arrowprops=dict(arrowstyle="-"))
plt.annotate("爱情",xy=(0.9,-0.01),xytext=(1.5,0.1),arrowprops=dict(arrowstyle="-"))

#导出图表
plt.savefig(r"C:\Users\Archer\Desktop\my_fig_2.png")
my_fig_1.png
my_fig_2.png

数据分析

  • 发行国家上,美国电影的数量一骑绝尘,可以综合其评分、排名数据深入研究榜上美国电影的质量分布情况,同时,从柱形图上可以看出日韩位列前10,从蛋肥的观影经验上看,日韩电影自成一派,有着强烈的地域风格,但高评分的电影往往集中于这些风格中,很少有跳脱出来的,这点可以通过对数据的进一步分析去进行考证。
  • 发行时间上,1990-2020年间的电影几乎占据了榜单,不知道是否是因为1990年前(尤其是1980年前)的电影已经很难接触到了,蛋肥个人感觉还是有不少经典的影片没有上榜,比如《卡萨布兰卡》(1942年),同时,可以进一步探讨为什么从1990年起高质量的电影的数量陡增,结合电影产业、大众审美等的发展历程,应该是个有意思的论题。
  • 电影类型上,不得不说,一个高质量的电影往往有一个好的故事,蛋肥最近总觉得国内外的电影,特效越来越花哨、场景越来越精美,却很少有能认真地讲好一个故事的,不知道是否前人成就太高导致后人有点无从下手了。
  • 其他,蛋肥觉得可以从一个更长的时间区间上去研究豆瓣电影TOP250榜单,看是否能反映出大众电影审美的变化趋势;或是是否存在因为某部电影评分高,后续观看的人受到评分影响,导致该电影评分持续涨高,是否有指标可以来衡量其相关性;或是是否存在一个口碑的延后,某部电影在某一时刻评分一般,但在之后某一时刻开始却持续走高,导致变化的原因是什么等。

总结

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

推荐阅读更多精彩内容