scrapy-parse()方法的工作机制

本文深入探讨了Scrapy框架的解析机制,详细解释了如何通过yield而非return使用parse函数作为生成器,Scrapy如何处理不同类型的请求和item,以及调度器的工作流程。了解这些关键点对于掌握Scrapy的高效使用至关重要。

1. 因为使用的yield,而不是return。parse函数将会被当做一个生成器使用。scrapy会逐一获取parse方法中生成的结果,并判断该结果是一个什么样的类型;
2. 如果是request则加入爬取队列,如果是item类型则使用pipeline处理,其他类型则返回错误信息。
3. scrapy取到第一部分的request不会立马就去发送这个request,只是把这个request放到队列里,然后接着从生成器里获取;
4. 取尽第一部分的request,然后再获取第二部分的item,取到item了,就会放到对应的pipeline里处理;
5. parse()方法作为回调函数(callback)赋值给了Request,指定parse()方法来处理这些请求 scrapy.Request(url, callback=self.parse)
6. Request对象经过调度,执行生成 scrapy.http.response()的响应对象,并送回给parse()方法,直到调度器中没有Request(递归的思路)
7. 取尽之后,parse()工作结束,引擎再根据队列和pipelines中的内容去执行相应的操作;
8. 程序在取得各个页面的items前,会先处理完之前所有的request队列里的请求,然后再提取items。
7. 这一切的一切,Scrapy引擎和调度器将负责到底。

### ScrapyScrapy-Redis的功能特性对比 #### 功能差异 Scrapy是一个功能强大的网络爬虫框架,提供了丰富的接口用于开发复杂的网页抓取应用。其核心优势在于高度可定制性和高效的数据提取能力[^2]。 而Scrapy-Redis则是作为Scrapy的一个扩展模块存在,主要增强了Scrapy对于分布式环境的支持。借助于Redis这一高性能键值对存储系统的帮助,Scrapy-Redis可以实现跨多个节点的任务分配和数据共享,从而极大地提高了大规模并行处理的能力[^1]。 具体来说,在任务管理方面: - **Scrapy**: 使用本地内存中的队列来进行请求调度,默认情况下不具备持久化能力和多实例间的协调机制- **Scrapy-Redis**: 将待处理URL存入Redis数据库中形成全局统一的队列结构;不同机器上启动的Scrapy进程可以从同一个地方获取新的链接继续执行,即使某个worker失败也不会丢失未完成的工作项[^3]。 关于重复访问控制: - **Scrapy**: 提供了一个内置过滤器来防止同一页面被多次下载,但这仅限于单机版操作内有效。 - **Scrapy-Redis**: 借助Redis集合(set)类型的唯一性特点构建了分布式的去重表,确保在整个集群范围内不会发生冗余请求[^4]。 #### 安装与配置 为了使现有的Scrapy项目兼容Scrapy-Redis所提供的新特性,只需要做少量改动即可达成目的。以下是基本步骤概述(假设已安装好Python环境及相关依赖包): 1. 安装`scrapy_redis`库; 2. 修改项目的settings.py文件加入必要的设置参数; 3. 调整spider类定义以继承自特定基类或混合其他辅助工具; 4. 如果有必要的话还可以进一步调整pipeline逻辑以便更好地适应新的架构需求。 ```bash pip install scrapy_redis ``` 接着更新`settings.py`, 添加如下几行代码指定使用Redis作为中间件和服务端点地址等信息: ```python # 启用Redis调度器 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 不清理Redis队列/集 (允许暂停和恢复) SCHEDULER_PERSIST = True # 设置Redis连接参数 REDIS_HOST = 'localhost' REDIS_PORT = 6379 ``` 最后一步是在创建Spider时让其实现方式有所变化,比如采用`RedisMixin`混入模式简化某些场景下的编程复杂度: ```python from scrapy_redis.spiders import RedisCrawlSpider as CrawlSpider, RedisSpider as Spider class MySpider(CrawlSpider): name = 'example.com' allowed_domains = ['example.com'] start_urls = ['http://www.example.com'] rules = ( Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True), ) def parse_item(self, response): self.logger.info('Hi, this is an item page! %s', response.url) item = Item() ... return item ``` 上述例子展示了如何快速地将传统Spiders转换成支持远程协作版本的方法之一——即通过改变父级类别名称达到集成外部服务的效果。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值