今天看啥  ›  专栏  ›  不温卜火

爬虫入门经典(四) | 如何爬取豆瓣电影Top250

不温卜火  · CSDN  ·  · 2020-10-21 16:15

大家好,我是不温卜火,是一名计算机学院大数据专业大三的学生,昵称来源于成语— 不温不火 ,本意是 希望自己性情温和 。作为一名互联网行业的小白,博主写博客一方面是为了记录自己的学习过程,另一方面是总结自己所犯的错误希望能够帮助到很多和自己一样处于起步阶段的萌新。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!暂时只在csdn这一个平台进行更新,博客主页: https://buwenbuhuo.blog.csdn.net/
1

PS:由于现在越来越多的人未经本人同意直接爬取博主本人文章,博主在此特别声明:未经本人允许,禁止转载!!!


2


博主早期其实写过一篇爬取豆瓣电影Top250的博文,当时由于刚开始学习,使用了urllib库进行爬取。现在看来,显的过于臃余。因此本片博文,博主带来了较为简洁的写法。使用xpath进行解,不得不说真香!!!
3
如果想看博主刚开始写的粗劣写法,博主在此给出传送门: 爬取豆瓣电影详细数据,保存为CSV文件

🆗,话不多说。进入正题。

一、项目分析

1.1 单页分析

目标网站: https://movie.douban.com/top250
4

我们打开网址,查看页面布局,可以看到有电影名称及别名、评分、引言等等,在此就以电影名称及别名、评分、引言为爬取目标。

我们打开开发者选项,发现这个网页为静态网页,这样就很好爬取了:
5

爬取部分所在位置
6

1、电影名称与其他名称
7
2、 URL
8
3、 评分
9
4、 引言
10
11
这个时候,你是否会感觉无从下手。没关系,本大师会为你排忧解惑!
12
网页大体结构已经分析完成,那么接下来就需要对我们所要爬取的内容进行xpath解析:

1、 电影名称解析
13
2、 其他名称解析
14
3、 链接解析
15
通过查看我们发现得到的是这一页中的所有链接,我们选取第一个即:

(//div[@class="hd"]/a/@href)[0]
  • 1
  • 1

这样就可以达到对应的URL链接了。

4、 评分解析
16
我们可以看到评分和链接一样,都是选取第一个即可:

(//div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text())[0]
  • 1
  • 1

5、 引言解析
17
引言解析和上述两个看着一样,但是如果直接和上面以上是会报错的,因为引言可能有的是没有的,比如说排名212的《九品芝麻官》,就没有引言。
18
这个时候就需要加上判断语句:

# 条件语句:如果有引言则写引言,若没有则不写
if quote:
    quote = quote[0]
else:
    quote = ''
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

1.2 翻页分析

在分析完单页爬取内容后,我们就需要继续分析分页,来完成循环爬取的功能。
19
我们先来分析下网页链接:

https://movie.douban.com/top250?start=0&filter=
https://movie.douban.com/top250?start=25&filter=
https://movie.douban.com/top250?start=50&filter=
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

通过查看对比,我们发现其网页变化仅为start=?以此可以判定,其是以25为分页。

我们再来看下总页数,这印证了我们的猜想是正确的。
20
分析完成了下面就可以来进行实现了:

doubanUrl = 'https://movie.douban.com/top250?start={}&filter='

# 一共10页,循环10次
for i in range(10):
    # 获取url
    pageLink = doubanUrl.format(i * 25)
    print(pageLink)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

下面我们来打印下拼接网址
21
打开其中一个网址,看是否成功
22
Respect,🆗分析到这里就完美结束了!

23

二、完整代码

# encoding: utf-8
'''
  @author 李华鑫
  @create 2020-10-14 8:30
  Mycsdn:https://buwenbuhuo.blog.csdn.net/
  @contact: 459804692@qq.com
  @software: Pycharm
  @file: 豆瓣.py
  @Version:1.0
  
'''
import requests
from lxml import etree
import csv

# 豆瓣top250网址
doubanUrl = 'https://movie.douban.com/top250?start={}&filter='


# 获取网页源码
def getSource(url):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36'
    }
    response = requests.get(url, headers=headers)
    # 以防出现乱码 设置编码格式
    response.encoding = 'utf-8'
    return response.text


# 引言 评分 网址 标题 ---> 网页源代码中
# 获取电影信息
def getEveryItem(source):
    # 生成一个Html对象
    selector = etree.HTML(source)
    # 通过selector对象来找到  电影信息
    movieItemList = selector.xpath('//div[@class="info"]')

    # 定义一个空列表
    movieList = []

    # 通过for循环来遍历
    for eachMovie in movieItemList:
        # 创建一个字典,向列表中存储数据[{电影一},{电影二}...]
        movieDict = {}

        title = eachMovie.xpath('div[@class="hd"]/a/span[@class="title"]/text()') # 电影名
        otherTitle = eachMovie.xpath('div[@class="hd"]/a/span[@class="other"]/text()')  # 其他名称
        link = eachMovie.xpath('div[@class="hd"]/a/@href')[0]  # 链接
        star = eachMovie.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')[0]  # 评分
        quote = eachMovie.xpath('div[@class="bd"]/p[@class="quote"]/span/text()')  # 引言

        # 条件语句:如果有引言则写引言,若没有则不写
        if quote:
            quote = quote[0]
        else:
            quote = ''

        # 保存数据
        movieDict['title'] = ''.join(title + otherTitle)
        movieDict['url'] = link
        movieDict['star'] = star
        movieDict['quote'] = quote
        print(movieDict)

        movieList.append(movieDict)

    return movieList


# 保存数据
def writeData(movieList):
    with open('douban_top250.csv', 'w', encoding='utf-8',newline='') as f:
        writer = csv.DictWriter(f, fieldnames=['title', 'star', 'quote', 'url'])
        writer.writeheader()  # 写入表头
        for each in movieList:
            # 逐行写入
            writer.writerow(each)


# 启动
if __name__ == "__main__":
    movieList = []

    # 一共10页,循环10次
    for i in range(10):
        # 获取url
        pageLink = doubanUrl.format(i * 25)
        print(pageLink)
        source = getSource(pageLink)
        movieList += getEveryItem(source)

    writeData(movieList)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

三、运行结果

24
25
美好的日子总是短暂的,虽然还想继续与大家畅谈,但是本篇博文到此已经结束了,如果还嫌不够过瘾,不用担心,我们下篇见!


12

好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论”“收藏” 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!

21
22




原文地址:访问原文地址
快照地址: 访问文章快照