2. Scrapy 核心组件


文档摘要

Scrapy 核心组件 Scrapy 核心组件详解与实践 Scrapy 架构概览 首先,我们使用 Mermaid 图表来展示 Scrapy 的整体架构: 图表解释: Scrapy Engine: 引擎是 Scrapy 的核心,负责控制数据流在所有组件之间的流动。 Scheduler: 调度器接收引擎发来的请求,并将其放入队列中,以便稍后由下载器下载。 Downloader: 下载器负责下载网页,并将响应传递给 Spider。 Spider: Spider 定义了如何抓取特定的网站,并从页面中提取结构化数据。 Item Pipeline: Item Pipeline 负责处理 Spider 提取的 Items,例如清洗、验证和存储数据。

2. Scrapy 核心组件

Scrapy 核心组件详解与实践

1. Scrapy 架构概览

首先,我们使用 Mermaid 图表来展示 Scrapy 的整体架构:

图表解释:

  • Scrapy Engine: 引擎是 Scrapy 的核心,负责控制数据流在所有组件之间的流动。

  • Scheduler: 调度器接收引擎发来的请求,并将其放入队列中,以便稍后由下载器下载。

  • Downloader: 下载器负责下载网页,并将响应传递给 Spider。

  • Spider: Spider 定义了如何抓取特定的网站,并从页面中提取结构化数据。

  • Item Pipeline: Item Pipeline 负责处理 Spider 提取的 Items,例如清洗、验证和存储数据。

  • Spider Middleware: Spider 中间件可以修改进入 Spider 的请求和离开 Spider 的响应。

  • Downloader Middleware: 下载器中间件可以修改发送给下载器的请求和下载器接收到的响应。

2. 核心组件详解

现在,让我们深入了解每个核心组件,并提供代码示例。

2.1 Scrapy Engine (引擎)

引擎是 Scrapy 的核心,它负责控制所有组件之间的数据流。 你无需直接编写代码来操作引擎,因为它在 Scrapy 框架内部运行。 引擎负责启动爬虫、调度请求、处理响应和 Item,以及在组件之间传递信号。

2.2 Scheduler (调度器)

调度器负责接收引擎发送的请求,并将它们放入队列中。 它还负责去重,确保同一个 URL 不会被多次抓取。 Scrapy 默认使用 scrapy.dupefilters.RFPDupeFilter 进行去重,它基于请求指纹(request fingerprint)来判断请求是否重复。

代码示例 (自定义调度器 - 仅供演示,不推荐直接替换默认调度器):

# my_scheduler.py from scrapy.dupefilters import RFPDupeFilter from scrapy.utils.request import request_fingerprint class CustomScheduler: def __init__(self, dupefilter): self.dupefilter = dupefilter self.queue = [] @classmethod def from_crawler(cls, crawler): return cls(RFPDupeFilter()) def enqueue_request(self, request): if not self.dupefilter.request_seen(request): self.queue.append(request) return True return False def next_request(self): if self.queue: return self.queue.pop(0) def has_pending_requests(self): return bool(self.queue) def close(self, reason): self.dupefilter.close(reason) def __len__(self): return len(self.queue)

配置自定义调度器 (settings.py):

# settings.py SCHEDULER = 'my_project.my_scheduler.CustomScheduler'

解释:

  • CustomScheduler 类实现了自定义调度器。

  • enqueue_request 方法将请求添加到队列中,并使用 RFPDupeFilter 进行去重。

  • next_request 方法从队列中获取下一个请求。

  • has_pending_requests 方法检查队列是否为空。

  • from_crawler 是一个类方法,用于从 Crawler 对象创建调度器实例。

注意: 通常情况下,不需要自定义调度器。 Scrapy 默认的调度器已经足够强大和灵活。

2.3 Downloader (下载器)

下载器负责下载网页。 Scrapy 默认使用 Twisted 异步网络库来处理下载。 下载器中间件可以用来修改请求头、设置代理、处理重定向等。

代码示例 (自定义下载器中间件 - 设置 User-Agent):

# my_middleware.py class CustomUserAgentMiddleware: def process_request(self, request, spider): request.headers['User-Agent'] = 'My Custom User Agent' def process_response(self, request, response, spider): return response def process_exception(self, request, exception, spider): return None

配置下载器中间件 (settings.py):

# settings.py DOWNLOADER_MIDDLEWARES = { 'my_project.my_middleware.CustomUserAgentMiddleware': 543, }

解释:

  • CustomUserAgentMiddleware 类实现了自定义下载器中间件。

  • process_request 方法在请求发送给下载器之前被调用,可以修改请求头。

  • process_response 方法在下载器收到响应之后被调用,可以修改响应。

  • process_exception 方法在下载过程中发生异常时被调用,可以处理异常。

  • DOWNLOADER_MIDDLEWARES 设置指定了要启用的下载器中间件及其优先级。

2.4 Spider (爬虫)

Spider 定义了如何抓取特定的网站,并从页面中提取结构化数据。 你需要编写 Spider 类来指定起始 URL、解析网页和提取数据。

代码示例 (一个简单的 Spider):

# my_spider.py import scrapy class MySpider(scrapy.Spider): name = 'my_spider' start_urls = ['http://quotes.toscrape.com/'] def parse(self, response): for quote in response.css('.quote'): yield { 'text': quote.css('.text::text').get(), 'author': quote.css('.author::text').get(), 'tags': quote.css('.tag::text').getall(), } next_page = response.css('.next a::attr(href)').get() if next_page is not None: yield response.follow(next_page, self.parse)

解释:

  • MySpider 类继承自 scrapy.Spider

  • name 属性指定了 Spider 的名称。

  • start_urls 属性指定了起始 URL。

  • parse 方法是 Spider 的核心,它负责解析网页并提取数据。

  • response.css 方法使用 CSS 选择器来选择元素。

  • yield 语句用于返回提取的数据或新的请求。

  • response.follow 方法用于创建新的请求,并指定回调函数。

2.5 Item Pipeline (Item 管道)

Item Pipeline 负责处理 Spider 提取的 Items。 你可以使用 Item Pipeline 来清洗、验证和存储数据。

代码示例 (一个简单的 Item Pipeline):

# my_pipeline.py class MyPipeline: def process_item(self, item, spider): item['text'] = item['text'].strip() return item

配置 Item Pipeline (settings.py):

# settings.py ITEM_PIPELINES = { 'my_project.my_pipeline.MyPipeline': 300, }

解释:

  • MyPipeline 类实现了自定义 Item Pipeline。

  • process_item 方法在 Item 被传递给 Item Pipeline 时被调用,可以修改 Item。

  • ITEM_PIPELINES 设置指定了要启用的 Item Pipeline 及其优先级。

2.6 Spider Middleware (Spider 中间件)

Spider 中间件可以修改进入 Spider 的请求和离开 Spider 的响应。 你可以使用 Spider 中间件来实现重试、代理、User-Agent 轮换等功能。

代码示例 (一个简单的 Spider 中间件):

# my_middleware.py class MySpiderMiddleware: def process_spider_input(self, response, spider): return None def process_spider_output(self, response, result, spider): for i in result: yield i def process_spider_exception(self, response, exception, spider): return None def process_start_requests(self, start_requests, spider): for r in start_requests: yield r

配置 Spider 中间件 (settings.py):

# settings.py SPIDER_MIDDLEWARES = { 'my_project.my_middleware.MySpiderMiddleware': 543, }

解释:

  • MySpiderMiddleware 类实现了自定义 Spider 中间件。

  • process_spider_input 方法在响应进入 Spider 之前被调用。

  • process_spider_output 方法在 Spider 产生 Item 或 Request 之后被调用。

  • process_spider_exception 方法在 Spider 发生异常时被调用。

  • process_start_requests 方法在 Spider 启动时被调用。

  • SPIDER_MIDDLEWARES 设置指定了要启用的 Spider 中间件及其优先级。

2.7 Downloader Middleware (下载器中间件)

Downloader 中间件可以修改发送给下载器的请求和下载器接收到的响应。 你可以使用 Downloader 中间件来实现代理、User-Agent 轮换、重试等功能。

(Downloader Middleware 的代码示例已经在 2.3 Downloader 中提供)

3. 总结

Scrapy 的核心组件共同协作,构建了一个强大而灵活的爬虫框架。 理解每个组件的作用以及如何自定义它们,对于构建高效、可维护的爬虫至关重要。 通过本文提供的代码示例和详细解释,你应该能够更好地理解 Scrapy 的核心组件,并能够根据自己的需求进行定制。

希望这篇文章对你有所帮助!


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U