5. Scrapy 生态与扩展


文档摘要

Scrapy 生态与扩展 Scrapy 生态与扩展 Scrapy 作为一个强大的爬虫框架,其魅力不仅在于其核心功能,还在于其丰富的生态系统和强大的扩展能力。通过利用这些生态和扩展机制,我们可以构建更加健壮、高效和定制化的爬虫应用。 5.1 Scrapy 生态系统概览 Scrapy 的生态系统围绕着核心框架,提供了各种各样的组件和工具,涵盖了数据处理、存储、部署和监控等多个方面。主要包括: Scrapy 官方库和中间件: Scrapy 官方维护的库和中间件,例如 、 等,提供了常用功能的实现。 第三方 Scrapy 扩展: 由社区贡献的各种扩展,例如 (分布式爬取)、 (JavaScript 渲染)、 (浏览器自动化)等,极大地扩展了 Scrapy 的能力。

5. Scrapy 生态与扩展

5. Scrapy 生态与扩展

Scrapy 作为一个强大的爬虫框架,其魅力不仅在于其核心功能,还在于其丰富的生态系统和强大的扩展能力。通过利用这些生态和扩展机制,我们可以构建更加健壮、高效和定制化的爬虫应用。

5.1 Scrapy 生态系统概览

Scrapy 的生态系统围绕着核心框架,提供了各种各样的组件和工具,涵盖了数据处理、存储、部署和监控等多个方面。主要包括:

  • Scrapy 官方库和中间件: Scrapy 官方维护的库和中间件,例如 scrapy.contrib.spiders.CrawlSpiderscrapy.downloadermiddlewares.useragent.UserAgentMiddleware 等,提供了常用功能的实现。

  • 第三方 Scrapy 扩展: 由社区贡献的各种扩展,例如 scrapy-redis(分布式爬取)、scrapy-splash(JavaScript 渲染)、scrapy-selenium(浏览器自动化)等,极大地扩展了 Scrapy 的能力。

  • 数据处理和存储库: 用于数据清洗、转换和存储的库,例如 pandasnumpypymongoSQLAlchemy 等,可以与 Scrapy 集成。

  • 部署和监控工具: 用于部署和监控 Scrapy 爬虫的工具,例如 ScrapydScrapy CloudGrafana 等,方便爬虫的管理和维护。

5.2 自定义中间件

中间件是 Scrapy 架构的核心组成部分,它允许你在请求和响应处理流程中插入自定义逻辑。通过自定义中间件,你可以实现诸如请求重试、User-Agent 轮换、代理设置、数据压缩等功能。

5.2.1 下载器中间件

下载器中间件位于 Scrapy 引擎和下载器之间,可以处理请求和响应。

代码示例:自定义 User-Agent 中间件

# myproject/middlewares.py import random class RandomUserAgentMiddleware: def __init__(self, user_agent_list): self.user_agent_list = user_agent_list @classmethod def from_crawler(cls, crawler): return cls(user_agent_list=crawler.settings.get('USER_AGENT_LIST')) def process_request(self, request, spider): ua = random.choice(self.user_agent_list) request.headers['User-Agent'] = ua # settings.py USER_AGENT_LIST = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15', # ... 更多 User-Agent ] DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.RandomUserAgentMiddleware': 543, }

代码详解:

  • RandomUserAgentMiddleware 类实现了自定义的 User-Agent 中间件。

  • from_crawler 方法是一个类方法,用于从 Scrapy 设置中获取 USER_AGENT_LIST

  • process_request 方法在每个请求发送之前被调用,它从 USER_AGENT_LIST 中随机选择一个 User-Agent,并将其添加到请求头中。

  • settings.py 中,我们定义了 USER_AGENT_LISTDOWNLOADER_MIDDLEWARES,并将自定义中间件添加到 DOWNLOADER_MIDDLEWARES 中,并指定了优先级(543)。

5.2.2 蜘蛛中间件

蜘蛛中间件位于 Scrapy 引擎和蜘蛛之间,可以处理蜘蛛的输入和输出。

代码示例:自定义 Item 过滤中间件

# myproject/middlewares.py class ItemFilterMiddleware: def process_spider_output(self, response, result, spider): for item in result: if isinstance(item, dict) and 'name' in item and item['name']: yield item else: continue # settings.py SPIDER_MIDDLEWARES = { 'myproject.middlewares.ItemFilterMiddleware': 543, }

代码详解:

  • ItemFilterMiddleware 类实现了自定义的 Item 过滤中间件。

  • process_spider_output 方法在蜘蛛产生 Item 后被调用,它过滤掉 name 字段为空的 Item。

  • settings.py 中,我们将自定义中间件添加到 SPIDER_MIDDLEWARES 中,并指定了优先级。

5.3 自定义 Pipeline

Pipeline 用于处理蜘蛛提取的 Item。通过自定义 Pipeline,你可以实现数据清洗、验证、存储等功能。

代码示例:将 Item 存储到 MongoDB

# myproject/pipelines.py import pymongo class MongoPipeline: def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] def close_spider(self, spider): self.client.close() def process_item(self, item, spider): self.db['items'].insert_one(dict(item)) return item # settings.py MONGO_URI = 'mongodb://localhost:27017/' MONGO_DATABASE = 'scrapy_db' ITEM_PIPELINES = { 'myproject.pipelines.MongoPipeline': 300, }

代码详解:

  • MongoPipeline 类实现了将 Item 存储到 MongoDB 的 Pipeline。

  • from_crawler 方法从 Scrapy 设置中获取 MongoDB 的 URI 和数据库名称。

  • open_spider 方法在蜘蛛启动时被调用,用于建立 MongoDB 连接。

  • close_spider 方法在蜘蛛关闭时被调用,用于关闭 MongoDB 连接。

  • process_item 方法在每个 Item 被蜘蛛提取后被调用,它将 Item 插入到 MongoDB 的 items 集合中。

  • settings.py 中,我们定义了 MONGO_URIMONGO_DATABASEITEM_PIPELINES,并将自定义 Pipeline 添加到 ITEM_PIPELINES 中,并指定了优先级(300)。

5.4 扩展 Scrapy 功能

Scrapy 提供了多种方式来扩展其功能,例如信号、扩展和自定义命令。

5.4.1 信号

Scrapy 信号允许你在特定的事件发生时执行自定义代码。例如,你可以在蜘蛛启动或关闭时发送通知,或者在 Item 被提取后执行数据验证。

代码示例:监听蜘蛛关闭信号

# myproject/extensions.py from scrapy import signals from scrapy.exceptions import NotConfigured class SpiderCloseExtension: def __init__(self, value): self.value = value @classmethod def from_crawler(cls, crawler): if not crawler.settings.getbool('MYEXT_ENABLED'): raise NotConfigured ext = cls(crawler.settings.get('MYEXT_VALUE')) crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed) return ext def spider_closed(self, spider): print(f"Spider {spider.name} closed with value: {self.value}") # settings.py MYEXT_ENABLED = True MYEXT_VALUE = "Example Value" EXTENSIONS = { 'myproject.extensions.SpiderCloseExtension': 500, }

代码详解:

  • SpiderCloseExtension 类实现了监听蜘蛛关闭信号的扩展。

  • from_crawler 方法从 Scrapy 设置中获取 MYEXT_ENABLEDMYEXT_VALUE,并连接 spider_closed 信号到 spider_closed 方法。

  • spider_closed 方法在蜘蛛关闭时被调用,它打印一条消息,包含蜘蛛的名称和 MYEXT_VALUE

  • settings.py 中,我们定义了 MYEXT_ENABLEDMYEXT_VALUEEXTENSIONS,并将自定义扩展添加到 EXTENSIONS 中,并指定了优先级(500)。

5.4.2 扩展 (Extensions)

扩展提供了一种机制来增强 Scrapy 的核心功能。它们可以监听 Scrapy 信号,执行周期性任务,或者修改 Scrapy 的行为。

上面的信号监听例子也展示了扩展的用法。

5.4.3 自定义命令

你可以通过自定义命令来扩展 Scrapy 的命令行工具。例如,你可以创建一个命令来启动多个蜘蛛,或者执行数据分析任务。

代码示例:自定义 "crawlall" 命令

# myproject/commands/crawlall.py from scrapy.commands import ScrapyCommand from scrapy.crawler import CrawlerProcess class Command(ScrapyCommand): requires_project = True def syntax(self): return "[options]" def short_desc(self): return "Crawl all spiders in the project" def run(self, args, opts): process = CrawlerProcess(self.settings) for spider_name in self.crawler_process.spider_loader.list(): process.crawl(spider_name) process.start() # scrapy.cfg [settings] default = myproject.settings [deploy] # ... [commands] crawlall = myproject.commands.crawlall

代码详解:

  • Command 类继承自 ScrapyCommand,实现了自定义的 crawlall 命令。

  • requires_project 属性设置为 True,表示该命令需要在 Scrapy 项目中运行。

  • syntax 方法返回命令的语法。

  • short_desc 方法返回命令的简短描述。

  • run 方法是命令的核心逻辑,它遍历项目中的所有蜘蛛,并使用 CrawlerProcess 启动它们。

  • scrapy.cfg 文件中,我们将自定义命令添加到 [commands] 节中。

5.5 常用的第三方 Scrapy 扩展

  • scrapy-redis: 用于实现分布式爬取,提高爬取效率。

  • scrapy-splash: 用于渲染 JavaScript 页面,解决动态内容抓取问题。

  • scrapy-selenium: 用于浏览器自动化,模拟用户行为。

  • scrapy-crawlera: 与 Crawlera 集成,提供代理服务和反爬虫解决方案。

5.6 图形化展示 Scrapy 架构

图表说明:

  • Scrapy Engine: Scrapy 的核心,负责控制数据流。

  • Scheduler: 调度器,负责管理请求队列。

  • Downloader: 下载器,负责下载网页内容。

  • Spiders: 蜘蛛,负责解析网页内容,提取数据。

  • Item Pipeline: Item 管道,负责处理提取的数据。

  • Downloader Middlewares: 下载器中间件,用于处理请求和响应。

  • Spider Middlewares: 蜘蛛中间件,用于处理蜘蛛的输入和输出。

  • Websites: 目标网站。

  • Data Storage: 数据存储,例如数据库、文件等。

5.7 总结

Scrapy 的生态系统和扩展能力为我们提供了无限的可能性。通过自定义中间件、Pipeline 和扩展,我们可以构建满足各种需求的爬虫应用。掌握这些技能对于成为一名优秀的 Scrapy 开发者至关重要。 通过学习和实践这些内容,你可以更好地利用 Scrapy 框架,构建更加强大和灵活的爬虫应用。


发布者: 作者: 转发
评论区 (0)
U