📜  Scrapy-后续链接(1)

📅  最后修改于: 2023-12-03 15:05:06.036000             🧑  作者: Mango

Scrapy-后续链接

Scrapy 是一个快速高效的 Python 爬虫框架,它的设计目标是尽可能地降低代码复杂度,使得各个部分之间的耦合度尽可能地小。通过简单的配置和灵活的扩展机制,Scrapy 可以轻松地处理各种各样的爬虫任务,从简单的网页抓取到复杂的数据抽取。

在 Scrapy 中,后续链接 (Follow Links) 是一个非常重要的概念。它指的是在爬取一个页面的时候,如果该页面中包含了链接,那么 Scrapy 就可以将这些链接加入到待爬取的队列中,然后继续爬取这些链接指向的页面。这样一来,我们就可以使用 Scrapy 快速地爬取整个网站的数据了。

后续链接的实现

Scrapy 的后续链接功能是通过 Request 对象来实现的。在爬虫代码中,我们通过调用 response.follow(link) 方法来创建一个新的 Request 对象,并将其加入到待爬取的队列中。response.follow 方法的作用是对 link 进行解析,生成一个新的 Request 对象,并且将当前页面的一些信息 (如 Cookie,Referer 等) 传递给新的 Request 对象。

下面是一个简单的例子,展示了如何在 Scrapy 中使用后续链接:

import scrapy

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

    def start_requests(self):
        urls = [
            'http://www.example.com/page1.html',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        # 提取当前页面的数据
        yield {
            'title': response.css('title::text').get(),
            'body': response.css('body::text').get(),
        }

        # 提取当前页面的后续链接,并将其加入到待爬取的队列中
        for link in response.css('a'):
            yield response.follow(link, self.parse)

在这个例子中,我们定义了一个名为 myspider 的爬虫。在 start_requests 方法中,我们创建了一个待爬取的 URL 列表,并使用一个 for 循环将其全部加入到待爬取的队列中。

parse 方法中,我们首先提取了当前页面的数据,并且使用 yield 关键字将其返回。然后,我们通过 response.css('a') 提取了当前页面中的所有链接,并将它们一个一个地加入到待爬取的队列中,使用的关键字是 response.follow

由于 Scrapy 采用了异步非阻塞的爬虫机制,因此在加入链接到待爬取队列中时,我们并不必担心它们的查询顺序。Scrapy 会自动地对链接进行排序和去重,并且会优先爬取响应速度最快的那些链接。

后续链接的参数设置

在 Scrapy 中,我们可以通过 response.follow 方法的参数设置来控制爬取后续链接的行为。下面是一些常用的参数设置:

  1. callback:指定链接的响应处理函数。如果不指定该参数,Scrapy 就会使用默认的处理函数 self.parse

  2. method:指定链接请求的 HTTP 方法。默认值是 GET,也可以设置为 POST 等其他值。

  3. body:指定链接请求的参数。如果 method 参数设置为 POST,那么就可以通过该参数传递 POST 请求的参数。

  4. headers:指定链接请求的 HTTP 头信息。

  5. meta:指定一个字典对象,用于传递爬虫状态信息。这个是比较重要的,后面我们会用一个例子来详细介绍。

下面是一个例子,展示了如何使用这些参数设置:

import scrapy

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

    def start_requests(self):
        urls = [
            'http://www.example.com/page1.html',
        ]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        # 提取当前页面的数据
        yield {
            'title': response.css('title::text').get(),
            'body': response.css('body::text').get(),
        }

        # 提取当前页面的后续链接,并将其加入到待爬取的队列中
        for link in response.css('a'):
            yield response.follow(link,
                                  callback=self.parse_detail,
                                  meta={'url': link.url})

    def parse_detail(self, response):
        # 提取详情页面的数据和状态信息
        yield {
            'title': response.css('title::text').get(),
            'body': response.css('body::text').get(),
            'url': response.meta['url'],
        }

在这个例子中,我们首先在 parse 方法中提取当前页面的数据,并使用 response.follow 方法将所有的后续链接加入到待爬取的队列中。在 response.follow 方法的第二个参数中,我们指定了一个新的响应处理函数 parse_detail,并且使用了 meta 参数将链接的 URL 传递了进去。这个 URL 会在后面的 parse_detail 方法中用到。

parse_detail 方法中,我们再次调用了 response.css 方法,提取详情页面的数据,并且使用之前传递的 meta 参数获取了链接的 URL。这些数据会被使用 yield 关键字返回。在这个例子中,我们没有再次去爬取后续链接,因为我们只是想演示参数设置的用法。

需要注意的是,在这个例子中我们使用了一个非常重要的技巧,这个技巧就是使用 meta 参数保存爬虫状态信息。由于 Scrapy 使用的是异步非阻塞的爬虫机制,因此在爬虫过程中,数据的处理可能会被打断,而此时传递状态信息就变得非常重要。在这个例子中,我们将链接的 URL 保存到了 meta 参数中,并在后面的 parse_detail 方法中使用了它,这种技巧可以极大地方便我们的爬虫编写工作。