Scrapy-2.Spiders

本文地址:https://www.jianshu.com/p/b69d1303336f

Scrapy中,Spider负责的是网页的抓取逻辑,以及数据的解析逻辑。所以SpiderScrapy爬虫中相对核心的部分。

Spider用法

命令

在上一章的简介中,我们提到,一般来说我们需要使用Scrapy的命令行生成一个Spider模板。命令的语法是这样的:

scrapy genspider [options] <name> <domain>

这里有两个必写的参数,name指的是这个Spider的名称,而且这个名称必须是唯一的,不能有其他的Spider重名。而domain指的是这个Spider爬取的域名。

除此之外,这个命令还有以下可选的options:

Options
=======
--help, -h              show this help message and exit
--list, -l              List available templates
--edit, -e              Edit spider after creating it
--dump=TEMPLATE, -d TEMPLATE
                        Dump template to standard output
--template=TEMPLATE, -t TEMPLATE
                        Uses a custom template.
--force                 If the spider already exists, overwrite it with the
                        template

如果使用的是最基础的模板,将会创建出以下格式的模板:

# -*- coding: utf-8 -*-
import scrapy


class SpidernameSpider(scrapy.Spider):
    name = 'spidername'
    allowed_domains = ['mydomain.com']
    start_urls = ['http://mydomain.com/']

    def parse(self, response):
        pass

可以看到,这个模版的主体为一个SpidernameSpider类,继承自scrapy.Spider,这个类的名称与文件名基本保持一致。

scrapy.Spider类

这个类是Spider最基础的类,里面只定义两三个默认的方法,非常的简单。其他的种类的Spider都是继承自这个Spider的。而我们的Spider也都需要继承这个类。

这个爬虫的抓取规则与数据提取规则都将定义在这个类中。

运行流程

首先,在Scrapy中,只要我们按照规则定义好了相应的代码,那么很多时候Scrapy会自动的帮我们调度运行程序。

  1. 生成的模板中有一个start_urls参数,这是这个Spider的运行入口,Scrapy会自动的将这个参数中的url发送到Downloader进行下载,并且自动的调用parse方法来处理获得的response

    如果希望自定义爬虫的开始方式,那么删除这个参数,并自定义一个start_urls方法即可。

  2. parse方法处理response的过程中,我们一般会有可能获取两种对象,一个是最终我们从网页上提取的数据,这种数据我们会将其保存为item对象。另一种是我们获取的接下来要访问的url,这一种我们会将其生成为一个Request对象。

    这两种获得的对象,我们都会使用yield将其返回出去。Scrapy会自动检测对象的类型,如果是item,则会将其发送到item pipeline进行存储等处理,如果是Request对象,则会再次往Downloader发送进行访问。

  3. 每一个Request对象,都会在生成的时候绑定一个回调函数,用来处理这个请求返回的响应结果。

通过以上这几个步骤一直循环往复,则可以将我们想要抓取的数据抓取完毕。

属性与方法

  • name

    一个定义了Spider名称的字符串,Scrapy会通过这个属性来定位Spider,所以这个name必须是唯一的。

    如果Spider抓取的是单个域名的内容,那么通常的做法是使用域名来对Spider命名。例如,一个抓取mywebsite.comSpider应该命名为mywebsite

  • allowed_domains

    一个可选的列表,定义了允许访问的域名。不包含在此域名列表中的URL将不会被跟进爬取。

  • start_urls

    一个爬虫开始爬取的起始URL列表,也是一个可选项。爬虫启动后,将首先从这些URL开始爬取。

  • custom_settings

    配置Spider自定义设置的字典,会在运行这个Spider时覆盖项目级别的设置。这个属性需要被设置为一个类属性,因为它需要在实例化之前被定义好。

  • crawler

    这个属性将会在类实例化之后,由from_crawler()设置,并且连接到绑定的Crawler对象。Crawler对象在项目中封装了许多组件,供单独对应访问。

  • settings

    运行此Spider的配置,是一个Settings对象。

  • logger

    这是一个由Spider的名称创建的Python logger对象,可以使用它来输出信息。

  • start_requests()

    这个方法会返回一个可迭代对象,里面包含着Spider启动时首先抓取的RequestScrapy会在这个爬虫启动时默认调用此方法一次,默认的实现是将start_urls中的每一个url生成一个Request

    如果你希望改变Spider抓取起始url的逻辑,那么你需要重写此方法。

  • parse(response)

    Request没有指定回调函数时,会Scrapy默认的调用这个方法来处理response。这个方法的通常作用是从response中提取出需要的数据,或者是生成更多接下来要爬取的URL。

    这个方法跟其他的Request回调函数一样,需要至少返回Requestdictitem中的一种。

  • log(message, [, level, component])

    通过Spiderlogger输出信息。

  • closed(reason)

    Spider关闭时调用此方法。

  • *from_crawler(crawler, args, **kwargs)

    这是Scrapy用来创建你的Spiders的方法。

    一般来说你不需要直接的重写这个方法,因为它扮演着__init__方法的代理。这个方法会在新实例中设置crawlersettings,这样你才能在Spider中访问这两个属性。

例子

以下是一些简单使用Spider的例子:

import scrapy


class MySpider(scrapy.Spider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = [
        'http://www.example.com/1.html',
        'http://www.example.com/2.html',
        'http://www.example.com/3.html',
    ]

    def parse(self, response):
        self.logger.info('A response from %s just arrived!', response.url)

在单个回调函数中返回多个RequestItem

import scrapy

class MySpider(scrapy.Spider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = [
        'http://www.example.com/1.html',
        'http://www.example.com/2.html',
        'http://www.example.com/3.html',
    ]

    def parse(self, response):
        for h3 in response.xpath('//h3').extract():
            yield {"title": h3}

        for url in response.xpath('//a/@href').extract():
            yield scrapy.Request(url, callback=self.parse)

使用start_requests()替代start_urls

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = 'example.com'
    allowed_domains = ['example.com']

    def start_requests(self):
        yield scrapy.Request('http://www.example.com/1.html', self.parse)
        yield scrapy.Request('http://www.example.com/2.html', self.parse)
        yield scrapy.Request('http://www.example.com/3.html', self.parse)

    def parse(self, response):
        for h3 in response.xpath('//h3').extract():
            yield MyItem(title=h3)

        for url in response.xpath('//a/@href').extract():
            yield scrapy.Request(url, callback=self.parse)

CrawlSpider

Scrapy提供了一些有用的通用爬虫,可以用来实现某些特定功能,例如CrawlSpider,这些通用爬虫都是继承自Spider的子类。

CrawlSpider的主要用处是通过一条或者多条固定的规则(rules),来抓取页面上所有的连接。这常常被用来做整站爬取。

CrawlSpider类

class scrapy.spiders.CrawlSpider

这种通用爬虫主要用来抓取常见的网站,对于一些特定的网站可能不是非常适合,但是更具有通用性。它可以通过定义规则来跟踪连接。

除了那些继承自Spider的属性和方法,这个类支持以下的新属性和方法:

  • rules

    这是由一个或者多个Rule对象组成的列表。每一个Rule对象定义了一种抓取网页的行为。如果多个Rule匹配到了同一个连接,那么在列表中位置靠前的将会被使用。

  • parse_start_url(response)

    这个方法是用来处理start_urls返回的响应。这个方法需要至少返回Item对象,Request对象,或者一个包含前两种对象的可迭代对象。

Rule

class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None)

参数:

  • link_exractor – 一个定义了如何从页面上提取连接的Link Extractor对象。

  • callback – 用来处理返回的Response的回调函数。这个回调函数需要接收Response作为第一个参数,并且需要返回一个包含Item或者Request的列表

    注意:不能使用parse()方法作为回调函数,CrawlSpider是通过parse()方法来实现逻辑的,所以如果重写了parse()方法,CrawlSpider将无法运行。

  • cb_kwargs – 包含关键字参数的字典,可以传递给回调函数。

  • follow – 是否跟踪访问那些使用Rule提取出来的连接。当callback为None时,follow默认为True。除此以外,follow默认为False。

    也就是说,在没有指定callback时,CrawlSpider会默认继续访问从response中使用Rule提取的连接。如果指定了callback,那么response将会教给回调函数处理。

  • process_links – 用来处理从response中提取出的连接的函数。主要的作用是用来筛选目标。

  • process_request – 用来处理从response中提取出来的每一个request。需要返回一个Request对象,或者None(用来筛选request)。

CrawlSpider例子

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

class MySpider(CrawlSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com']

    rules = (
        # allow表示将会访问的连接,deny表示不会访问的连接。
        # 没有指定callback,表明会继续跟踪访问下去
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

        # 提取匹配'item.php'的连接,并将返回的response交给parse_item处理。
        Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
    )

    def parse_item(self, response):
        self.logger.info('Hi, this is an item page! %s', response.url)
        item = scrapy.Item()
        item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')
        item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()
        return item

系列文章:

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