Scrapy: Spider

Spiders

spider 是一个类用来定义如何抓取某些网站(或是一组网站),包括怎样执行爬取(即跟进链接)和怎样从页面中提取结构化数据(即爬虫项目),也就是说,spider就是你定义抓取和页面解析行为的地方。

对于爬虫,爬取周期运行如下

  1. 从生成一个最初的请求来爬取第一个url开始,并指定一个回调函数来回调从这些请求下载来的响应

    第一个请求从start_requests()方法获得,这个方法默认生成定义在start_urls里的urls并且使用parse方法作为这个请求的回调函数。

  2. 在回调函数中,解析页面的请求并返回带有提取出来的数据的两种字典,item对象,request对象或者这些对象的生成器,这些请求将包含一个回调函数(可能是一样的),被scrapy下载然后通过这的指定的回调函数来处理他们的响应。

  3. 在回调函数中,你要解析页面的内容,通常是使用selectors(但是你也可以使用bs4 lxml 或其他你喜欢的机制)并且生成含有解析来的数据的items。

  4. 最后,从spider返回的items通常会被保存到一个数据库(在一些项目管道里)或者使用feed exports 来写入文件

尽管这个周期适用于任何种类的爬虫,但还是有一些不同种类的默认spiders捆绑在scrapy里,用于不同的目的。下面我们来瞅瞅,,

scrapy.Spider

  • class scrapy.spiders.Spider

这是最简单的爬虫,也是所有其他爬虫必须继承的(包括那些绑定在scrapy里和你自己写的),它不提供任何特别函数。它只提供一个默认的start_requests()实现,来发送start_urls的爬虫属性里的请求,并为每个响应的结果调用spider 的解析方法。

name

定义爬虫的名字,爬虫名是scrpay定位(和实例化)的方法,所有一定是唯一的。但没人阻止你对一个爬虫进行多个实例化。这是最重要也是需要的爬虫属性。

如果爬虫抓取单一的域名,通常的做法是使用域名来命名,无论有没有TLD。

allowed_domains

一个含有域名字符串的可选的列表,是允许爬虫可以抓取的域名。如果offsiteMiddleware 是可用的就不会跟进不属于指定在这个列表里的域名(或是他的子域名)的url 请求。如果你的目标是https://www.example.com/1.html, 增加 'example.com' 到你的列表里

start_urls

开始爬取的urls 的列表,如果没有特别指定,下载的第一个页面将被在这列出。随后的请求将从包含在开始urls里的数据连续生成。

custom_settings

当运行爬虫时来自全项目的配置将会覆盖设置字典,由于设置更新是再实例化之前,因此必须将其定义为类属性。

crawler

这个属性是通过from_crawler()类方法再初始化类后设置的,并连接到该spider实例绑定的crawler 对象。Crawlers 再项目里封装了很多组件,为了他们的单次访问(像 扩展,中间件,信号管理器等)。

settings

配置爬虫的运行,这是settins的实例化对象,

logger

使用爬虫名来创造python记录器。你可以使用它来发送日志的消息。

from_crawler(crawler, *args, **kwargs)[source]

这是scrapy用来创造你的爬虫的类方法

你可能不需要直接重写它,因为他的默认机制是充当_inti_()方法的代理,并使用给定参数args和命名参数kwargs对其调用。

尽管如此,这个方法再新实例中设置crawler settings属性,所以他们可以再spider代码中对其进行访问。

  • Parameters

    crawler 爬虫绑定的crawler对象

    args 传递给__init__()方法的参数

    kwargs 传递个关键字参数

start_requests()[source]

这个方法必须返回一个带有第一个请求的可迭代对象,为了爬虫的搜索,再爬虫开始爬取时调用。scrapy只调用一次,所以将start_requests()实现成一个生成器时安全的。

默认实现为start_urls中的每个URL生成Request(url,dont_filter = True)。

如果你想改变用来开始抓取一个域名的请求,这是重写的方法,例如:如果你需要通过使用POST请求登录来开始:

class MySpider(scrapy.Spider):
    name = 'myspider'

    def start_requests(self):
        return [scrapy.FormRequest("http://www.example.com/login",
                                   formdata={'user': 'john', 'pass': 'secret'},
                                   callback=self.logged_in)]

    def logged_in(self, response):
        # here you would extract links to follow and return Requests for
        # each of them, with another callback
        pass

parse(response)[source]

scrapy处理下载来的响应的默认回调函数,当请求没有指定回调函数时。

parse方法负责处理响应,返回爬取的数据,跟进的url。其他请求的回调函数与spider类有相同的需要。

这个方法也可以有其他的回调请求,必须返回一个可迭代的请求或是一个字典/item对象。

  • Parameters

    response (Response) – the response to parse

log(message**[, level, component]**)[source]

For more information see Logging from Spiders.# 包装通过爬虫日志发送的信息,保留向后兼容性。

closed(reason)

在爬虫关闭时调用,这个方法为spider_closed 信号提供了通往signals.connect()的捷径。

Let’s see an example:

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)

Return multiple Requests and items from a single callback:

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').getall():
            yield {"title": h3}

        for href in response.xpath('//a/@href').getall():
            yield scrapy.Request(response.urljoin(href), self.parse)

Instead of start_urls you can use start_requests() directly; to give data more structure you can use Items:

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').getall():
            yield MyItem(title=h3)

        for href in response.xpath('//a/@href').getall():
            yield scrapy.Request(response.urljoin(href), self.parse)

Spider arguments

爬虫能接受参数来修改他们的行为。通常用来定义开始的url 或 限制对页面爬取的部分,但是也可以用来配置爬虫的任何功能

爬虫参数通过 crawl 命令的-a 选项来传递。

scrapy crawl myspider -a category=electronics

爬虫会访问在__init__ 方法里的参数

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'

    def __init__(self, category=None, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.start_urls = ['http://www.example.com/categories/%s' % category]
        # ...

默认的_init_ 方法将获取爬虫参数然后复制进爬虫作为属性。上面的例子也可以这么写:

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'

    def start_requests(self):
        yield scrapy.Request('http://www.example.com/categories/%s' % self.category)

请记住爬虫参数只是一个字符串。爬虫自己不会进行任何解析。如果你想从命令行中设置start_urls 属性,你要使用ast.literal_eval()或json.loads()来解析它并放入一个列表然后将他设置为属性。否则,你会造成对一个start_urls 字符串进行迭代(python常见陷阱),造成每一个字符都被看成单独的url。

有效的例子就是设置http 认证证书通过httpauthmiddleware 或者用户代理使用 UserAgentMiddleware.

scrapy crawl myspider -a http_user=myuser -a http_pass=mypassword -a user_agent=mybot

Spider arguments can also be passed through the Scrapyd schedule.json API. See Scrapyd documentation.# 爬虫参数也可以通过scrapy的schedule.jsonAPI 来传递

Generic Spiders

scrapy 带有一些通用的爬虫模板,你可以让你的爬虫继承他们。他们的目的的为常用的爬取案例提供方便的功能,像跟进规则跟进所有的链接,从站点地图爬取,或解析一个xml/csv出口

For the examples used in the following spiders, we’ll assume you have a project with a TestItem declared in a myproject.items module:

import scrapy

class TestItem(scrapy.Item):
    id = scrapy.Field()
    name = scrapy.Field()
    description = scrapy.Field()

CrawlSpider

  • classscrapy.spiders.CrawlSpider

这是用来爬取常规网站最常用的方法,提供了的方便的机制用来定义跟进链接的规则。可能不是最适合用来爬取特定网站或项目的方法,但是它在大多情况下够用了。所以你可以从这个开始,并根据自己的需要来重写自定义功能,或仅仅来执行你的爬虫。

除了从spider继承来的属性(你必须指定)这个类支持一个新的属性:

rules

这是一个或多个Rule 对象的列表,每一个Rule 定义某个行为来爬取页面。如果多个规则匹配同一个链接,只有第一个有效。

这个爬虫也提供了一个可重写的方法

parse_start_url()[source]

为了start_urls 的响应调用,可以解析最初的响应并且必须返回一个 item 对象,或 请求对象,或他们的可迭代对象

Crawling rules
  • class scrapy.spiders. Rule(link_extractor=None, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None, errback=None)[source]

    link_extractor

    一个连接提取器对象,用来定义怎么从爬取的页面中提取链接。生成的链接将会生成一个请求对象,将再 meta 字典中包含链接的文本(再 Link_text关键字下)。如果省略,就是使用没有参数的连接提取器,所有的链接都会提取。

    callback

是一个可调用的或一个字符串(spider对象的方法名),被提取出来的链接调用。回调函数接受响应作为第一个参数,并必须返回一个单一的实例,或一个可迭代的item,字典或请求对象(或者是他们的子类)。上面说过,接受的响应对象将包含链接的文本,来自request的 meta 字典( link_text 关键字下)。

Warning

写爬虫规则时,不要使用parse 作为回调函数,因为crawlspider 要使用 parse 方法来实现自己的逻辑,如果你重写了parse方法,爬虫就不再工作。

cb_kwargs

传递给回调函数的关键字参数,是一个字典。

follow

一个布尔值来指定是否跟进根据规则从响应中提取来的链接。如果 callback 是 None,follow 默认是True,否则默认是False.

process_links

是一个可调用的或一个字符串(spider对象的方法名),被那些提取出来的链接调用,主要用来过滤。

process_request

由那些提取出来的请求使用。他将请求作为第一个参数,从这些请求来的响应作为第二个参数,必须返回一个请求对象或None(用来过滤请求)

errback

i 再出来请求的时候如果出现了错误,调用这个方法。它接收一个 Twisted Failure 实例作为第一个参数。

New in version 2.0: The errback parameter.

CrawlSpider example

Let’s now take a look at an example CrawlSpider with rules:

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 = (
        # Extract links matching 'category.php' (but not matching 'subsection.php')
        # and follow links from them (since no callback means follow=True by default).
        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

        # Extract links matching 'item.php' and parse them with the spider's method 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()').get()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').get()
        item['link_text'] = response.meta['link_text']
        return item

This spider would start crawling example.com’s home page, collecting category links, and item links, parsing the latter with the parse_item method. For each item response, some data will be extracted from the HTML using XPath, and an Item will be filled with it.

XMLFeedSpider

  • class scrapy.spiders.XMLFeedSpider

XMLFeedspider 用来解析XML 提要,通过对某个节点名进行迭代。迭代器可以从 iternodes,xml 和 html 选择。推荐使用iternodes 因为性能好,xml html迭代器为了解析要生成全部的DOM。然而使用html迭代器在解析错误的XML时更有用。

为了设置迭代器和标签名,你必须定义下面的类属性:

iterator

使用的迭代器的字符串,

  • 'iternodes' - 基于正则表达式的快速迭代器

  • 'html' - 使用selector 的迭代器。使用DOM解析,必须将所有的DOM 加载到内存中,这对大型的feeds 是一个问题。

  • 'xml' - 同上

It defaults to: 'iternodes'

  • itertag

    要迭代的节点(或元素)名。

    Example:itertag = 'product'

  • namespaces

(prefix,url)元组形式的列表,定义了与爬虫一起处理,在文档中可用的命名空间。prefix 和 url 将使用 register_namespace()方法自动寄存到命名空间。然后你可以在 itertag 属性中指定具有命名空间的节点。

Example:

class YourSpider(XMLFeedSpider):

    namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
    itertag = 'n:url'
    # ...

Apart from these new attributes, this spider has the following overrideable methods too:

这个方法接受响应,只要从中间件中发来,在爬虫开始解析之前,可以用来在解析之前修改响应体。接收一个响应并返回一个响应(可以时相同的也可以是不同的)

  • parse_node(response, selector)[source]

crapy.http.Request) object, or an iterable containing any of them.# 这个方法通过提供的标签名(itertag) 来匹配节点。接受响应和一个选择器,必须重写此方法,否则你的爬虫不会工作。这个方法必须返回一个 item 对象,或请求对象,或他们的迭代器。

  • process_results(response, results)[source]

    通过爬虫返回的每一个结果(item request)调用,作用是在将结果返回框架的核心前,执行需要的最后一次处理,例如设置项目 IDs。他接受结果的列表和产生这些结果的响应,必须返回一个结果的列表(item 或 request)

XMLFeedSpider example

These spiders are pretty easy to use, let’s have a look at one example:

from scrapy.spiders import XMLFeedSpider
from myproject.items import TestItem

class MySpider(XMLFeedSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/feed.xml']
    iterator = 'iternodes'  # This is actually unnecessary, since it's the default value
    itertag = 'item'

    def parse_node(self, response, node):
        self.logger.info('Hi, this is a <%s> node!: %s', self.itertag, ''.join(node.getall()))

        item = TestItem()
        item['id'] = node.xpath('@id').get()
        item['name'] = node.xpath('name').get()
        item['description'] = node.xpath('description').get()
        return item

基本上我们要做的就是创建一个爬虫,从给定的start_urls 来下载摘要,然后历遍每一个 item 标签,打印他们,然后将一些随记数据存储到item 中。

????我咋看不懂呢。。。。帮助文档不是给萌新看的嘛。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值