scrapy爬取豆瓣电影top250榜单(学习笔记)

相关工具

  • Python 3.6.1
  • Scrapy 1.4.0
  • PyCharm (亲测VS Code无法运行、调试scrapy代码)

创建一个scrapy项目

在你的工作目录的文件夹下打开命令提示符窗口,输入:

scrapy startproject demo

如果出现下面的提示,则说明创建成功:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

使用PyCharm打开这个scrapy项目,它的目录结构是这样的:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

  • scrapy.cfg ——主要包含的是项目的相关设置。
  • demo ——是用于编写爬虫的目录。
  • items.py ——定义我们所要爬取的信息的相关属性。
  • middlewares.py ——爬虫中间件,这里可以用过自定义相关的方法,用来处理爬虫的响应和请求。
  • pipelines.py ——当数据被爬虫爬取下来后,它会被发送到item pipelines中,每个item pipelines组件(有时称为“项目管道”)是一个实现简单方法的Python类。他们收到一个项目并对其执行操作,还决定该项目是否应该继续通过管道或被丢弃并且不再被处理。
  • settings.py ——项目的设置文件。

编写代码

在spiders文件夹下创建douban_spider.py文件:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

这是一个空的.py文件,然后在这编写爬虫代码:

# 爬虫类需要继承scrapy下的Spider类。
import scrapy

class douban_movie_spider(scrapy.Spider):
    # 项目的启动名
    name = "douban_movie"
    # 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
    headler = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
                      'Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    }
    # 开始链接
    start_urls = [
        'https://movie.douban.com/top250'
    ]
    # start_requests方法为scrapy的方法,我们对它进行重写。
    def start_requests(self):
       # 将start_url中的链接通过for循环进行遍历。
       for url in self.start_urls:
             # 通过yield发送Request请求。
             # 这里的Reques注意是scrapy下的Request类。注意不要导错类了。
             # 这里的有3个参数:
             # 1、url为遍历后的链接
             # 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
             # 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。
            
           yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)

    # 重写parse对start_request()请求到的数据进行处理
    def parse(self, response):
       pass

页面分析

chrome浏览器打开https://movie.douban.com/top250,点击f12开发者工具,使用选取工具选取整个电影的信息,可以发现,所有的信息都是放在单独的一个li标签中的,而且在li下还有一个class为item的div包裹着所有的信息:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

parse方法

def parse(self, response):
    # 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item
    for quote in response.css('div.item'):
        # 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下
        yield {
            "电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
            "评分":quote.css('div.info div.bd div.star span.rating_num::text').extract(),
            "引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
        }

写完上面的代码,其实只是抓取一页的罢了,为了抓取完整的top250榜单,我们需要让爬虫跳转到下一页再进行循环抓取,因为每个页面的结构是一样的,所以不用担心会抓取不到。

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

next_url=response.css('div.paginator span.next a::attr(href)').extract()

然后,需要对next_url进行判断是否存在,然后再次发送Request请求。这样爬虫就会在爬完一个页面后点击下一页再继续爬去,往复循环,直到爬取完毕。

if next_url:
    next_url="https://movie.douban.com/top250"+next_url[0]
    print(next_url)
    yield scrapy.Request(next_url,headers=self.headler)

那么到这里,代码就写完了。

然后我们来运行一下这个爬虫,scrapy框架是通过命令来启动爬虫的,
在项目根目录下打开命令提示符,输入:

scrapy crawl douban_movie -o douban_movice.csv -t csv

保存信息的最简单的方法是通过Feed exports,主要有四种:JSON,JSON lines,CSV,XML。
为了方便直接查看内容,我们将结果用csv导出。
-o 后面是导出文件名,-t 后面是导出类型。

爬虫运行后,就会输出大量的日志信息和爬取的网页内容,且scrapy会把爬取到的结果保存到douban_movice.csv这个文件里:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png
《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png
《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

但是,有个问题,如果爬虫报错了怎么办?

因为是用命令启动的爬虫,所以爬虫的日志信息都是显示在cmd中的,这样日志信息阅读起来非常的不友好。且Scrapy默认是不能在IDE中调试的,我们可以在根目录中新建一个run.py文件,在里面写入以下内容:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

from scrapy import cmdline

name='douban_movie -o douban.csv -t csv'
cmd = 'scrapy crawl {0}'.format(name)
cmdline.execute(cmd.split())

运行这个文件后,所有的日志信息日志信息就会输出在IDE(PyCharm)下了,便于调试:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

在PyCharm中查看爬取结果:

《scrapy爬取豆瓣电影top250榜单(学习笔记)》 image.png

完整代码

# 爬虫类需要继承scrapy下的Spider类。
import scrapy


class douban_movie_spider(scrapy.Spider):
    # 项目的启动名
    name = "douban_movie"

    # 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
    headler = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
                      'Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
    }
    # 开始链接
    start_urls = ['https://movie.douban.com/top250']

    # start_requests方法为scrapy的方法,我们对它进行重写。
    def start_requests(self):
        # 将start_url中的链接通过for循环进行遍历。
        for url in self.start_urls:

            # 通过yield发送Request请求。
            # 这里的Reques注意是scrapy下的Request类。注意不到导错类了。
            # 这里的有3个参数:
            # 1、url为遍历后的链接
            # 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
            # 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。

            yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)

    # 重写parse对start_request()请求到的数据进行处理
    def parse(self, response):
        # 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item

        for quote in response.css('div.item'):
            # 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下

            yield {
                "电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
                "评分": quote.css('div.info div.bd div.star span.rating_num::text').extract(),
                "引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
            }

        next_url = response.css('div.paginator span.next a::attr(href)').extract()
        if next_url:
            next_url = "https://movie.douban.com/top250"+next_url[0]
            print(next_url)
            yield scrapy.Request(next_url, headers=self.headler)

        # 翻页
        next_page = response.xpath('//span[@class="next"]/a/@href')
        if next_page:
            url = response.urljoin(next_page[0].extract())
            yield scrapy.Request(url, self.parse)

参考文章:https://segmentfault.com/a/1190000009091789

    原文作者:呆呆冬
    原文地址: https://www.jianshu.com/p/c33a57b76b04
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞