Python 爬虫之爬豆瓣TOP250电影 爬虫超详细讲解 零基础入门

先看后赞,养成习惯!!!

点赞收藏,人生辉煌!!!

讲解我们的爬虫之前,先概述关于爬虫的简单概念(毕竟是零基础教程)

爬虫

网络爬虫(又被称为网页蜘蛛,网络机器人)就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。

原则上,只要是浏览器(客户端)能做的事情,爬虫都能够做。

为什么我们要使用爬虫

互联网大数据时代,给予我们的是生活的便利以及海量数据爆炸式的出现在网络中。

过去,我们通过书籍、报纸、电视、广播或许信息,这些信息数量有限,且是经过一定的筛选,信息相对而言比较有效,但是缺点则是信息面太过于狭窄了。不对称的信息传导,以致于我们视野受限,无法了解到更多的信息和知识。

互联网大数据时代,我们突然间,信息获取自由了,我们得到了海量的信息,但是大多数都是无效的垃圾信息。

例如新浪微博,一天产生数亿条的状态更新,而在百度搜索引擎中,随意搜一条——减肥100,000,000条信息。

在如此海量的信息碎片中,我们如何获取对自己有用的信息呢?

答案是筛选!

通过某项技术将相关的内容收集起来,在分析删选才能得到我们真正需要的信息。

这个信息收集分析整合的工作,可应用的范畴非常的广泛,无论是生活服务、出行旅行、金融投资、各类制造业的产品市场需求等等……都能够借助这个技术获取更精准有效的信息加以利用。

网络爬虫技术,虽说有个诡异的名字,让能第一反应是那种软软的蠕动的生物,但它却是一个可以在虚拟世界里,无往不前的利器。

爬虫准备工作

我们平时都说Python爬虫,其实这里可能有个误解,爬虫并不是Python独有的,可以做爬虫的语言有很多例如:PHP,JAVA,C#,C++,Python,选择Python做爬虫是因为Python相对来说比较简单,而且功能比较齐全。

首先我们需要下载python,我下载的是官方最新的版本 PyCharm 2020.3 (Community Edition)

其次我们需要一个运行Python的环境,我用的是pychram

PyCharm: the Python IDE for data science and web development    这个是pycharm的官网

下面根据代码,从下到下给大家讲解分析一遍

-- codeing = utf-8 --,开头的这个是设置编码为utf-8 ,写在开头,防止乱码。

然后下面 import就是导入一些库,做做准备工作,

正则表达式用到 re 库

大体流程分三步走:

基本开发环境

Python 3.9

Pycharm

相关模块的使用

from bs4 import BeautifulSoup            # 网页解析,获取数据
import re                                # 正则表达式,进行文字匹配
import xlwt                              # 进行excel操作
import requests                          # 网络

安装Python并添加到环境变量,pip安装需要的相关模块即可。

一、明确需求

爬取豆瓣Top250排行电影信息

电影详情

电影图片

电影名字

导演、主演

年份、国家、类型

评分、评价人数

电影简介

二、发送请求

Python中的大量开源的模块使得编码变的特别简单,我们写爬虫第一个要了解的模块就是requests。

请求url地址,使用get请求,添加headers请求头,模拟浏览器请求,网页会给你返回response对象

heads = {  # 模拟头
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'
    }

#id = i * 25                                                                            
urls = 'https://movie.douban.com/top250?start=0&filter='          # ID 是网页数据由多少开始  一页有25个 第一个从0开始 总数据250条 因为总共有250条数据,刚开始 就写死,写成0,后面会详细解答
r = requests.get(urls, headers=heads)                                         # GET 获取数据方式

这样就可以请求成功了’

这个urls就是用来向网页发送请求用的,那么这里就有老铁问了,为什么这里要写个head呢?

这是因为我们要是不写的话,访问某些网站的时候会被认出来爬虫,显示错误,错误代码

418

这是一个梗大家可以百度下

418 I’m a teapot



The HTTP 418 I’m a teapot client error response code indicates that

the server refuses to brew coffee because it is a teapot. This error

is a reference to Hyper Text Coffee Pot Control Protocol which was an

April Fools’ joke in 1998.

三、获取数据

urls = 'https://movie.douban.com/top250?start=0&filter='  # ID 是网页数据由多少开始  一页有25个 第一个从0开始 总数据250条 因为总共有250条数据,刚开始 就写死,写成0,后面会详细解答
r = requests.get(urls, headers=heads)  # GET 获取数据方式
print(r.text)
heads = {  # 模拟头

    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'

}

#id = i * 25                                                                            

#urls = 'https://movie.douban.com/top250?start=%d&filter=' % id               # ID 是网页数据由多少开始  一页有25个 第一个从0开始 总数据250条

urls = 'https://movie.douban.com/top250?start=0&filter=                       # 因为总共有250条数据,刚开始 就写死,写成0,后面会详细解答

r = requests.get(urls, headers=heads)                                         # GET 获取数据方式

print(r.text)

下面是输出结果

<div class="item">

<div class="pic">

<em class="">1</em>

<a href="https://movie.douban.com/subject/1292052/">

<img alt="肖申克的救赎" class="" src="https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" width="100"/>

</a>

</div>

<div class="info">

<div class="hd">

<a class="" href="https://movie.douban.com/subject/1292052/">

<span class="title">肖申克的救赎</span>

<span class="title"> / The Shawshank Redemption</span>

<span class="other"> / 月黑高飞(港)  /  刺激1995(台)</span>

</a>

<span class="playable">[可播放]</span>

</div>

<div class="bd">

<p class="">

                    导演: 弗兰克·德拉邦特 Frank Darabont   主演: 蒂姆·罗宾斯 Tim Robbins /...<br/>

                    1994 / 美国 / 犯罪 剧情

                </p>

<div class="star">

<span class="rating5-t"></span>

<span class="rating_num" property="v:average">9.7</span>

<span content="10.0" property="v:best"></span>

<span>2296266人评价</span>

</div>

<p class="quote">

<span class="inq">希望让人自由。</span>

</p>

</div>

</div>

</div>

'''

四、解析数据

常用解析数据方法: 正则表达式、css选择器、xpath、lxml…

常用解析模块:bs4、parsel…

我经常使用的是 bs4

bs4 是第三方模块,pip install BS4 安装即可

一般爬网页内的内容需要用到正则表达式解析 提前放上来

#=============================正则表达式==================================

#=============================获取网页解析时候用的==========================

detiais = re.compile(r'<a href="(.*?)">')                                                     # 详情页正则

banderImage = re.compile(r'<img.*src="(.*?)">', re.S)                                         # 图片正则

conter = re.compile(r'<span class="title">(.*?)</span>')                                      # 名字1

conter1 = re.compile(r'<span class="other">(.*?)</span>')                                     # 名字1

directors = re.compile(r'<p class="">(.*?)</p>', re.S)                                        # 导演

evaluation = re.compile(r'<span>(\d*)人评价</span>')                                           # 评论人数

score = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')             # 评分

probably = re.compile(r'<span class="inq">(.*?)</span>')                                      # 大概什么内容

开打豆瓣TOP排行 可以 然后右击第一个 比如我这 肖生克的救赎   点检查 就可以看到下面这东西了

 

因为所有的电影信息都包含在 li 标签当中。

逐一解析数据

解析数据这里我们用到了 BeautifulSoup(靓汤) 这个库,这个库是几乎是做爬虫必备的库,无论你是什么写法。

下面就开始查找符合我们要求的数据,用BeautifulSoup的方法以及 re 库的

正则表达式去匹配,

for conters in bsou:

    temporaryData = []                                                        # 一个临时空数组

    webConters = str(conters)                                                 # 把网页获取的数据转为 string 类型

    #==========================================这里下面就获取到数据了!!!=========================

    #==========================================这里用正则表达式 获取解析数据    具体看最上面

    #findal

    detisiss = detiais.findall(webConters)                                    # 详情

    bandersImage = banderImage.findall(webConters)                            # 图片

    # ==========================================电影名字转义 后期优化==================================

    movieName = conter.findall(webConters)                                    # 电影名字

    moveiEscape = movieName[0].replace(" ", "")                               # 消除转义

    movieName1 = conter1.findall(webConters)                                  # 名字1

    moveiEscape1 = movieName1[0].replace("/", "")                             # 消除转义

    #============================================导演名字转义=======================================

    directorName = directors.findall(webConters)                              # 导演

    bd = directorName[0]

    bd = re.sub('<br(\s+)?/>(\s+)?', "", bd)

    bd = re.sub('/', "", bd)

    # =============================================================================================

    evaluations = evaluation.findall(webConters)  # 评论人数

    scores = score.findall(webConters)  # 评分

    probalys = probably.findall(webConters)  # 大概什么内容

打印结果:

下面的打印结果是因为我放到字典里面了 这样方便看 你也可以

{

    '详情': ['https://movie.douban.com/subject/1292052/'], 

    '图片': ['https://img2.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg" width="100"/>\n</a>\n</div>\n<div class="info'], 

    '名字': '肖申克的救赎', '名字1': '\xa0\xa0月黑高飞(港)    刺激1995(台)', 

    '导演': '\n导演: 弗兰克·德拉邦特 Frank Darabont\xa0\xa0\xa0主演: 蒂姆·罗宾斯 Tim Robbins ...1994\xa0\xa0美国\xa0\xa0犯罪 剧情\n', 

    '评论人数': ['2298262'], 

    '评分': ['9.7'], 

    '大概': ['希望让人自由。']

}

这样一条数据就解析出来了,当然 我们获取的数据不是一条,而是250条

这样就嵌套一个for循环,循环10次 一次25条 这就是前面我为什么注释那个URL

heads = {  # 模拟头

    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'

}

for i in range(0,10):

    id = i * 25

    urls = 'https://movie.douban.com/top250?start=%d&filter=' % id                # ID 是网页数据由多少开始  一页有25个 第一个从0开始 总数据250条

    r = requests.get(urls, headers=heads)                                         # GET 获取数据方式

这样就是可以循环把250条电影都拉出来了

五、存储数据

存数据我用的是xls表,一般可以用的还有有sqlite,视自己情况而定

xls表需要支持库 (import xlwt)

第一次先循环8次, 循环8次创建表头

下面 i j

因为是TOP 250 只有250条数据 其实是可以写死的,但是还是没必要

上面不是存了两次数组吗,一次25条 10次就是250条 i相当于循环10次 每次取一次数组出来

输出取出来 在在 j 里面循环 在取出每条数据来

book = xlwt.Workbook(encoding="utf-8", style_compression=0)                         # 创建workbook对象

sheet = book.add_sheet('文件夹操作',cell_overwrite_ok=True)                           # 创建工作表  如果对同一单元格重复操作会发生overwrite Exception,cell_overwrite_ok为可覆盖

col = ("电影详情链接", "图片链接", "影片名", "影片外国名", "导演", "评论人数", "评分", "大概")

for i in range(0, 8):

    sheet.write(0, i, col[i])                                                       # 列名  行,列,属性值 (1,1)为B2元素,从0开始计数

for i in range(0,len(array)):

    data = array[i]

    for j in range(0,8):

        sheet.write(i+1, j, data[j])                                                # 列名  行,列,属性值 (1,1)为B2元素,从0开始计数

book.save(filename_or_stream='豆瓣电影Top250数据.xls')                                # 保存

print('数据存入成功')

  

运行会出现这个

打开

OK完成

 

下面付完整代码

#    Pycharm Python on  爬豆瓣TOP250

#

#    爬豆瓣TOP250.py

#

#    If you have any questions

#

#    please contact me liuliuliuyadong@gmail.com

#

#    Create by 果冻 on 2021/3/4

#

#    Copyright  © 2021 果冻·All rights reserved.





from bs4 import BeautifulSoup            # 网页解析,获取数据

import re                                # 正则表达式,进行文字匹配

import xlwt                              # 进行excel操作

import requests                          # 网络





#=============================正则表达式==================================

#=============================获取网页解析时候用的==========================

detiais = re.compile(r'<a href="(.*?)">')                                                     # 详情页正则

banderImage = re.compile(r'<img.*src="(.*?)">', re.S)                                         # 图片正则

conter = re.compile(r'<span class="title">(.*?)</span>')                                      # 名字1

conter1 = re.compile(r'<span class="other">(.*?)</span>')                                     # 名字1

directors = re.compile(r'<p class="">(.*?)</p>', re.S)                                        # 导演

evaluation = re.compile(r'<span>(\d*)人评价</span>')                                           # 评论人数

score = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')             # 评分

probably = re.compile(r'<span class="inq">(.*?)</span>')                                      # 大概什么内容





totalData = []                                                                    #把所有数据放入这个数组

def urlDetails(head):

    id = i * 25

    urls = 'https://movie.douban.com/top250?start=%d&filter=' % id                # ID 是网页数据由多少开始  一页有25个 第一个从0开始 总数据250条

    r = requests.get(urls, headers=heads)                                         # GET 获取数据方式

    bsou = BeautifulSoup(r.text, 'lxml').find_all('div', class_='item')           # 把网页解析为LXML 数据   然后 查找为 <div> class_ = 'item'  里面的数据  因为 它影评详情都在这里div里面





    for conters in bsou:

        temporaryData = []                                                        # 一个临时空数组

        webConters = str(conters)                                                 # 把网页获取的数据转为 string 类型

        #==========================================这里下面就获取到数据了!!!=========================

        #==========================================这里用正则表达式 获取解析数据    具体看最上面

        #findal

        detisiss = detiais.findall(webConters)                                    # 详情

        bandersImage = banderImage.findall(webConters)                            # 图片

        # ==========================================电影名字转义 后期优化==================================

        movieName = conter.findall(webConters)                                    # 电影名字

        moveiEscape = movieName[0].replace(" ", "")                               # 消除转义

        movieName1 = conter1.findall(webConters)                                  # 名字1

        moveiEscape1 = movieName1[0].replace("/", "")                             # 消除转义

        #============================================导演名字转义=======================================

        directorName = directors.findall(webConters)                              # 导演

        bd = directorName[0]

        bd = re.sub('<br(\s+)?/>(\s+)?', "", bd)

        bd = re.sub('/', "", bd)

        # =============================================================================================

        evaluations = evaluation.findall(webConters)  # 评论人数

        scores = score.findall(webConters)  # 评分

        probalys = probably.findall(webConters)  # 大概什么内容

        #===========================================把数据依次传入空数组===================================

        temporaryData.append(detisiss)

        temporaryData.append(bandersImage)

        temporaryData.append(moveiEscape)

        temporaryData.append(moveiEscape1)

        temporaryData.append(bd)

        temporaryData.append(evaluations)

        temporaryData.append(scores)

        temporaryData.append(probalys)

        totalData.append(temporaryData)                                             # 把临时数据放入数组

        #========================================下面这个字典是给自己看的,如果做后台可以传入这个字典进去======

        contDic = {'详情': detisiss,

                   '图片': bandersImage,

                   '名字': moveiEscape,

                   '名字1': moveiEscape1,

                   '导演': bd,

                   '评论人数': evaluations,

                   '评分': scores,

                   '大概': probalys}

        dicContDetails(contDic)

    saveIntoFile(totalData)





def saveIntoFile(array):

    print(len(array))

    #========================================下面这个地方开始存入数据======

    book = xlwt.Workbook(encoding="utf-8", style_compression=0)                         # 创建workbook对象

    sheet = book.add_sheet('文件夹操作',cell_overwrite_ok=True)                           # 创建工作表  如果对同一单元格重复操作会发生overwrite Exception,cell_overwrite_ok为可覆盖

    col = ("电影详情链接", "图片链接", "影片名", "影片外国名", "导演", "评论人数", "评分", "大概")

    '''

    第一次先循环8次, 循环8次创建表头

    下面 i j

    因为是TOP 250  只有250条数据 其实是可以写死的,但是还是没必要

    上面不是存了两次数组吗,一次25条 10次就是250条 i相当于循环10次 每次取一次数组出来

    输出取出来 在在 j 里面循环 在取出每条数据来

    '''

    for i in range(0, 8):

        sheet.write(0, i, col[i])                                                       # 列名  行,列,属性值 (1,1)为B2元素,从0开始计数

    for i in range(0,len(array)):

        data = array[i]

        for j in range(0,8):

            sheet.write(i+1, j, data[j])                                                # 列名  行,列,属性值 (1,1)为B2元素,从0开始计数

    book.save(filename_or_stream='豆瓣电影Top250数据.xls')                                # 保存

    print('数据存入成功')

def dicContDetails(dic):

    '''

    传入的电影详情

    :param dic: 电影内容

    :return:

    '''



    print(dic)



if __name__ == '__main__':

    heads = {  # 模拟头

        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36'

    }

    for i in range(0,10):

        urlDetails(heads)

    print('爬取完毕')

  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值