网康上网行为管理审计策略配置(不做认证)
2026/7/18 4:52:39
Scrapy的架构遵循“高内聚、低耦合”的设计原则,将爬虫的核心流程拆分为7大核心组件,每个组件承担单一职责,通过引擎(Engine)统一调度协同工作。整体架构如下图(文字拆解):
[爬虫Spider] → 起始URL → [引擎Engine] → [调度器Scheduler] → [引擎Engine] → [下载器Downloader] ↓ [项目管道Item Pipeline] ← [爬虫Spider] ← [爬虫中间件Spider Middlewares] ← [下载中间件Downloader Middlewares]| 组件 | 核心职责 | 底层实现/设计亮点 |
|---|---|---|
| 引擎(Engine) | 核心调度中枢,负责触发、协调所有组件的交互,是框架的“大脑” | 基于Twisted的Reactor事件循环,通过信号(Signal)机制触发各组件的回调函数 |
| 调度器(Scheduler) | 管理请求队列,负责请求的去重、优先级排序、持久化 | 内置基于内存的优先级队列(PriorityQueue),支持自定义去重规则(如Redis分布式去重) |
| 下载器(Downloader) | 发送HTTP/HTTPS请求,获取网页响应,是框架的“网络请求模块” | 基于Twisted的AsyncHTTPClient实现异步非阻塞请求,支持连接池、重试、超时管控 |
| 爬虫(Spiders) | 定义爬取规则:起始URL、数据提取逻辑、链接跟进规则 | 基于类继承(scrapy.Spider),通过回调函数(parse)实现解析逻辑,支持多爬虫共存 |
| 项目管道(Item Pipeline) | 处理爬取到的数据:清洗、验证、去重、持久化(写入数据库/文件) | 流水线式处理(按优先级执行多个Pipeline),支持异步数据处理 |
| 下载中间件(Downloader Middlewares) | 拦截请求/响应:修改请求头、添加代理、处理Cookie、反反爬 | 基于“钩子函数”(process_request/process_response)实现请求/响应的拦截与修改 |
| 爬虫中间件(Spider Middlewares) | 处理爬虫的输入(响应)和输出(请求/数据):过滤无效请求、修改解析结果 | 介于引擎和爬虫之间,可全局干预爬虫的解析逻辑 |
每个组件仅通过引擎交互,无需关心其他组件的实现细节:
Scrapy的爬取过程是一个事件驱动的循环流程,从起始URL到数据落地,每一步都由引擎触发特定事件,调用对应组件的回调函数。以下是完整的核心流程(结合组件交互):
start_urls(起始URL),引擎触发start_requests事件;Request对象(包含URL、回调函数、请求头、元数据等),发送给调度器(Scheduler)。Request对象后,首先通过去重机制(默认基于请求指纹)判断是否为重复请求:Request对象交给下载器(Downloader);process_request钩子函数(如添加User-Agent、代理IP、Cookie);process_response钩子函数(如解压、修改响应内容、重试失败请求);process_spider_input钩子函数(过滤无效响应、修改响应内容);Request对象指定的回调函数(默认parse方法),解析响应:Item对象(Scrapy内置的数据容器),返回给引擎;Request对象(指定回调函数,如解析详情页的parse_detail),返回给引擎;process_spider_output钩子函数处理爬虫的输出(过滤无效请求/数据、修改Item)。Item对象交给项目管道(Item Pipeline),按优先级执行数据处理逻辑(清洗、去重、写入数据库/文件);Request对象再次发送给调度器,重复步骤2-5;spider_closed事件,爬取结束。调度器的去重核心是请求指纹(Request Fingerprint):
dont_filter=True(Request参数)跳过去重,或重写request_fingerprint函数修改指纹生成规则。Scrapy的高性能核心源于Twisted框架的异步非阻塞IO模型,这也是其与requests(同步)爬虫的本质区别。
Scrapy基于Twisted的Reactor(反应堆)实现异步调度,Reactor是一个无限循环,负责监听事件(如请求完成、响应返回)并触发对应的回调函数:
Scrapy的灵活性源于其钩子函数(Hook)和信号机制(Signal),允许开发者在核心流程的关键节点插入自定义逻辑,而无需修改框架源码。
中间件的本质是“钩子函数容器”,Scrapy在核心流程中预留了多个钩子点:
| 中间件类型 | 核心钩子函数 | 作用场景 |
|---|---|---|
| 下载中间件 | process_request | 修改请求(添加代理、UA、Cookie) |
| 下载中间件 | process_response | 修改响应(解压、重试、过滤) |
| 下载中间件 | process_exception | 处理下载器抛出的异常(如超时重试) |
| 爬虫中间件 | process_spider_input | 预处理响应(过滤无效响应) |
| 爬虫中间件 | process_spider_output | 处理爬虫输出(过滤请求/数据) |
| 爬虫中间件 | process_spider_exception | 处理爬虫解析时的异常 |
Scrapy内置了数十个信号,可监听爬取过程中的关键事件,例如:
spider_opened:爬虫启动时触发(可用于初始化数据库连接);item_scraped:Item被成功处理后触发(可用于统计数据);request_failed:请求失败时触发(可用于记录失败URL);crawler.signals.connect绑定自定义函数到指定信号:fromscrapyimportsignalsclassMySpider(scrapy.Spider):name='myspider'start_urls=['https://example.com']@classmethoddeffrom_crawler(cls,crawler,*args,**kwargs):spider=super().from_crawler(crawler,*args,**kwargs)# 绑定信号:爬虫启动时执行init_db函数crawler.signals.connect(spider.init_db,signal=signals.spider_opened)returnspiderdefinit_db(self):# 初始化数据库连接self.db_conn=pymysql.connect(host='localhost',user='root',password='123456',db='scrapy_data')defparse(self,response):yield{'title':response.xpath('//h1/text()').extract_first()}Request对象:不仅包含URL,还可携带callback(回调函数)、meta(元数据,用于传递数据)、dont_filter(是否去重)、priority(优先级)等参数,是请求的“完整描述”;Response对象:封装了HTTP响应的所有信息(状态码、响应头、响应体、编码),提供xpath()、css()等便捷方法用于数据提取,底层基于lxml实现高效解析。Item是Scrapy内置的字典子类,通过Field()定义字段,强制规范爬取数据的格式;Field的serializer参数定义数据序列化规则);importscrapyclassProductItem(scrapy.Item):name=scrapy.Field(serializer=str.strip)# 自动去除首尾空格price=scrapy.Field(serializer=float)# 自动转换为浮点数Scrapy通过以下参数控制并发,避免给目标服务器造成过大压力(配置在settings.py):
CONCURRENT_REQUESTS:全局最大并发请求数(默认16);CONCURRENT_REQUESTS_PER_DOMAIN:单域名最大并发请求数(默认8);CONCURRENT_REQUESTS_PER_IP:单IP最大并发请求数(默认0,即不限制);DOWNLOAD_DELAY:设置单域名下两次请求的最小间隔(默认0),用于降低爬取频率,避免被封IP;DOWNLOAD_DELAY,则通过twisted.internet.task.deferLater延迟发送请求;RANDOMIZE_DOWNLOAD_DELAY = True(默认True)添加随机偏移(延迟时间为DOWNLOAD_DELAY ± 50%),模拟人工访问。理解核心原理后,能快速定位并解决爬取中的常见问题:
request_fingerprint函数,将请求体、Cookie等关键参数纳入指纹生成逻辑。CONCURRENT_REQUESTS设置过小,或下载延迟过大;CONCURRENT_REQUESTS,同时调整DOWNLOAD_DELAY(如设为0.5)。ITEM_PIPELINES未启用,或爬虫未正确yield Item;settings.py中ITEM_PIPELINES的优先级配置,确保爬虫中通过yield item提交数据。DOWNLOAD_TIMEOUT(默认180秒),启用RETRY_TIMES和RETRY_HTTP_CODES,在下载中间件中处理重试逻辑。