scrapy中文指南 第二章 项目初始化和第一个小例子

经过了上一章的学习,我们已经在开发环境上安装好了scrapy的包,接下来我们就将初始化一个项目。

初始化项目

scrapy startproject tutorial

在开发环境中,使用命令行切换到项目将来想要存放的目录下执行上述命令,命令中的最后一个参数表示项目名称。运行结果如下所示:

在这里插入图片描述

项目目录介绍

经过上面的命令,将会在指定目录(命令行执行的目录)下创建一个项目,项目内的文件目录结构如下。

tutorial/
    scrapy.cfg            # 部署配置文件

    tutorial/             # 项目的 Python 模块,你将从这里导入你的代码
        __init__.py

        items.py          # 项目项定义文件

        middlewares.py    # 项目中间件文件

        pipelines.py      # 项目管道文件

        settings.py       # 项目设置文件

        spiders/          # 稍后您将放置spiders的目录
            __init__.py

目录结构的每部分功能都对应上一张基础知识中的流程图。

自定义爬虫类

spiders文件夹中有一个scrapy框架自动创建的文件__init__.py,我们不去理会。我们需要自己定义一个爬虫类,Scrapy将使用这个类从一个网站(或一组网站)中抓取信息。自定义的爬虫类必须继承 Spider ,并定义要发出的初始请求(即最开始请求的url),在类方法中可选择如何跟踪页面中的链接,以及如何解析下载的页面内容以提取数据。

自定义第一个爬虫

这是我们第一个自定义的 Spider 的类文件。将其保存在项目中的 tutorial/spider 目录下,一个名为quotes_spider.py 的文件中:

自定义第一个爬虫有两种方法:

  1. 通过命令行进行创建
    在项目的根目录下执行下面的命令,通过命令创建爬虫,命令行将自动地在tutorial/spider目录下创建一个.py文件。

    scrapy genspider quotes_spider quotes.toscrape.com
    
  2. 人工创建文件并初始化代码
    人工创建的方式,即人工在tutorial/spider 目录下创建一个.py文件。例如:quotes_spider.py

录入代码

创建好文件后,将下面地这些代码录入到文件中

import scrapy


class QuotesSpider(scrapy.Spider):
    name = "quotes"

    def start_requests(self):
        urls = [
            'http://quotes.toscrape.com/page/1/',
            'http://quotes.toscrape.com/page/2/',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = f'quotes-{page}.html'
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log(f'Saved file {filename}')

代码解释:

如您所见,我们的 自定义爬虫类继承了 scrapy.Spider ,并定义了一些属性和方法:

  • name:标识spiders。它在一个项目中必须是唯一的,即不能为不同的 Spider 设置相同的名称。

  • start_requests():必须返回一个可迭代的请求(您可以返回一个请求列表或编写一个函数生成器),spiders将从中开始爬行。后续请求将从这些初始请求中依次生成。

  • parse():该方法将被回调,用来处理每个请求下载的响应。 response 参数是 TextResponse 的一个实例,它保存页面内容并有更多有用的方法来处理它。

parse() 方法通常会解析响应,将抓取的数据提取为 dicts,并找到要遵循的新 URL 并从中创建新请求 (Request)

运行爬虫

想要运行刚才创建的spider,请将命令行切换到项目的根目录并运行以下命令:

scrapy crawl quotes

运行命令后会返回很多的运行信息,比如下面这样的:

在这里插入图片描述

运行结果

上述命令行执行后,在项目的根目录下会发现多了两个文件,quotes-1.html、quotes-2.html,而这两个文件正是我们爬虫类中所写的,发送了两个请求后的结果。

代码逐条分析

  1. 导入scrapy包
  2. 定义类并继承自scrapy.Spider
  3. 定义当前的爬虫名称为quotes
  4. 定义方法start_requests,该方法名有scrapy框架定死,并不能随意更改
  5. 定义一个list,并填充两个要访问的起始url
  6. 遍历列表并调用scrapy.Request去访问列表中的每一个url,并将结果yield(后续会详解)
  7. 定义方法parse,该方法由scrapy提供不可更改名称,并接受一个response作为参数
  8. 获取response的url地址用'/'进行截取获取最后倒数第二位,也就是url中的 1、2表示页码。
  9. 声明一个文件名,文件名的后半部分就是刚才获取的页码
  10. 以**wb**的凡是打开文件(不存在则创建)
  11. 将获取到的内容的body部分(url请求结果的html源码,后面会讲到),填充到文件中
  12. 打印一条日志。

由于起始发送的url为列表,两条。因此方法parse会被回调两遍。

刚才的代码执行过程都做了什么事情呢?

Scrapy 调度 Spider 的 start_requests 方法返回的 scrapy.Request 对象。收到每个响应后,它会实例化 Response 对象并调用与请求关联的回调方法(在本例中为 parse 方法),将响应作为参数传递。

简易版本

上述的代码有没有简易版本呢,当然是有的。因为scrapy其实已经内置了发送请求的部分,因此我们并不需要自己定义 start_requests方法,并调用 scrapy.Request(url=url, callback=self.parse)
去发送请求,scrapy会帮我们去发送请求,我们只需要告诉scrapy该去请求什么地址即可,完整代码如下:

import scrapy


class QuotesSpidersSpider(scrapy.Spider):
    name = 'quotes_spiders'
    allowed_domains = ['quotes.toscrape.com']
    start_urls = [
        'http://quotes.toscrape.com/page/1/',
        'http://quotes.toscrape.com/page/2/',
    ]

    def parse(self, response):
        page = response.url.split("/")[-2]
        filename = f'quotes-{page}.html'
        with open(filename, 'wb') as f:
            f.write(response.body)
        self.log(f'Saved file {filename}')

如上代码所示,只需要告知爬虫要爬取的地址集即可,地址集放在一个名为start_urls的变量中。
有没有发现这次的代码和上次的略有不同, 变量中多了一个allowed_domains,这个变量是在告诉爬虫我们定义了爬取地址的范围,只在这个域名下爬取,当获取到的地址不是该域名下则不会爬取。

注:Parse() 方法将被调用来处理对这些 URL 的每个请求,即使我们没有明确告诉 Scrapy 这样做。发生这种情况是因为 parse() 是 Scrapy 的默认回调方法,它在没有明确分配回调的请求时被调用。

至此我们的项目初始化和第一个爬虫小例子就结束了,我们学习该如何初始化项目和写了第一个爬虫小例。接下来我们将要学习如何配置scrapy,通过合理的配置,达到我们想要爬取任意不同目标的需求,并为下面的工作做准备。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值