深入解读 Scrapy 框架原理与源码

server/2024/12/22 9:26:49/

🛠️ Scrapy 框架原理解读

Scrapy 是一个强大的 Python 爬虫框架,其设计理念基于事件驱动的异步编程,通过高度模块化的方式实现爬虫功能。Scrapy 框架的核心组成包括爬虫(Spider)、调度器(Scheduler)、下载器(Downloader)、管道(Pipeline)和中间件(Middleware)。每个组件在数据抓取的过程中扮演不同的角色,从请求的生成、处理到数据的存储,整个流程经过了多个阶段,每个阶段都可以通过中间件进行扩展和修改。
在这里插入图片描述

爬虫(Spider): 爬虫是 Scrapy 的核心,负责定义爬取逻辑,包括请求的生成和响应的解析。它通过回调函数处理响应,并提取数据或生成新的请求。

调度器(Scheduler): 调度器的主要职责是接收请求并将其排队,等待下载器处理。它会按照请求的优先级和调度策略管理请求队列。

下载器(Downloader): 下载器负责发送 HTTP 请求并接收响应。它将响应传递给爬虫爬虫再根据业务逻辑进行数据处理。

管道(Pipeline): 管道用于处理爬虫提取的数据。它可以进行数据清洗、验证、存储等操作。每个管道的优先级可以配置,以控制数据处理的顺序。

中间件(Middleware): 中间件在请求和响应处理的过程中插入自定义逻辑。它可以在请求发送前修改请求,在响应返回前处理响应,或者处理异常。

Scrapy 的这种设计使得爬虫的构建和维护变得更加灵活和可扩展。下面我们将深入解析 Scrapy 的运行原理和底层实现。


🚀 Scrapy 运行原理

Scrapy 的运行过程包括以下主要步骤:

  1. 请求生成: 爬虫定义的初始请求通过调度器(Scheduler)排队,等待下载器(Downloader)处理。

  2. 请求下载: 下载器从调度器中取出请求,发送 HTTP 请求,并获取响应数据。

  3. 响应处理: 下载器将响应传递给爬虫(Spider),爬虫解析响应数据,提取有用信息,并可能生成新的请求。

  4. 数据处理: 爬虫将提取的数据传递给管道(Pipeline),进行清洗、验证和存储操作。

  5. 数据存储: 数据处理完成后,管道将数据保存到数据库、文件系统或其他存储介质中。

请求生成: 爬虫通过定义 start_requests 方法或者 parse 回调函数生成初始请求。这些请求被传递到调度器中。

请求下载: 下载器会从调度器中取出请求,使用异步 I/O 技术(如 Twisted)发送请求,并获取响应。响应会被传递回爬虫

响应处理: 爬虫通过回调函数(如 parse 方法)处理响应数据。爬虫可以从响应中提取数据,并生成新的请求以继续抓取。

数据处理: 数据处理由管道完成。Scrapy 提供了默认管道(如 JsonItemExporter)和允许用户自定义管道。管道的优先级决定了数据处理的顺序。


📜 Scrapy 底层源码解析

Scrapy 的底层实现依赖于 Twisted 异步框架,主要通过以下核心类来实现其功能:

CrawlerProcess

CrawlerProcess 是 Scrapy 的一个高层接口,用于启动爬虫进程。它封装了爬虫的创建、启动和管理过程。下面是一个简单的示例:

python">from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settingsprocess = CrawlerProcess(get_project_settings())
process.crawl('my_spider')
process.start()

CrawlerRunner

CrawlerRunner 是一个较底层的类,用于在事件循环中管理多个爬虫。它允许同时运行多个爬虫并进行调度。

python">from scrapy.crawler import CrawlerRunner
from twisted.internet import reactorrunner = CrawlerRunner()
runner.crawl('my_spider')
runner.join().addCallback(lambda _: reactor.stop())
reactor.run()

Crawler

Crawler 是 Scrapy 的爬虫类,用于定义抓取逻辑。它包含了请求的生成和响应的处理逻辑。以下是一个自定义爬虫的示例:

python">import scrapyclass MySpider(scrapy.Spider):name = 'my_spider'def start_requests(self):urls = ['http://example.com/page1', 'http://example.com/page2']for url in urls:yield scrapy.Request(url=url, callback=self.parse)def parse(self, response):title = response.css('title::text').get()yield {'title': title}

🛡️ Scrapy 中间件原理解读

Scrapy 的中间件是一种强大的机制,允许用户在请求和响应的处理过程中插入自定义逻辑。中间件可以分为下载中间件和响应中间件,它们分别处理请求和响应的不同阶段。

🌐 下载和响应中间件

  • 下载中间件: 负责处理请求的发送和响应的接收。主要方法包括 process_requestprocess_responseprocess_request 在请求发送之前被调用,process_response 在响应返回之前被调用。

  • 响应中间件: 主要负责处理响应内容的进一步操作,如解析响应、处理重定向等。主要方法包括 process_exception,用于处理请求过程中发生的异常。

以下是一个自定义下载中间件的示例:

middlewares.py:

python">class CustomDownloaderMiddleware:def process_request(self, request, spider):# 在请求被发送之前修改请求头request.headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'return Nonedef process_response(self, request, response, spider):# 在响应返回之前处理if response.status == 404:spider.logger.error('Page not found: %s', request.url)return responsedef process_exception(self, request, exception, spider):# 处理请求异常spider.logger.error('Request failed: %s', request.url)return None

🔧 中间件优先级别

中间件的优先级通过 DOWNLOADER_MIDDLEWARESSPIDER_MIDDLEWARES 设置。优先级较高的中间件会先处理请求或响应。例如:

settings.py:

python">DOWNLOADER_MIDDLEWARES = {'myproject.middlewares.CustomDownloaderMiddleware': 543,
}

🛠️ 自定义下载中间件

自定义下载中间件允许开发者实现特定的功能,例如修改请求头、处理重定向、设置代理等。以下是一个更复杂的自定义下载中间件示例:

middlewares.py:

python">class ProxyMiddleware:def process_request(self, request, spider):# 设置代理request.meta['proxy'] = 'http://myproxy:port'return Nonedef process_response(self, request, response, spider):# 处理响应中的数据if response.status == 403:spider.logger.warning('Access denied: %s', request.url)return responsedef process_exception(self, request, exception, spider):# 处理请求异常spider.logger.error('Request exception: %s', exception)return None

settings.py 中启用自定义中间件:

python">DOWNLOADER_MIDDLEWARES = {'myproject.middlewares.ProxyMiddleware': 543,
}

📥 Scrapy 媒资下载器

Scrapy 媒资下载器用于处理图片、视频等媒体文件的下载。默认情况下,Scrapy 提供了一个 ImagesPipeline 用于下载和处理图片。以下是一个自定义的媒资下载器示例:

pipelines.py:

python">import scrapy
from scrapy.pipelines.images import ImagesPipelineclass MediaPipeline(ImagesPipeline):def get_media_requests(self, item, info):if 'image_urls' in item:for url in item['image_urls']:yield scrapy.Request(url)def file_path(self, request, response=None, info=None, *, item=None):return 'images/%s' % request.url.split('/')[-1]

settings.py 中启用媒体管道:

python">ITEM_PIPELINES = {'myproject.pipelines.MediaPipeline': 1,
}

📧 Scr

apy 邮件监听

Scrapy 允许通过扩展机制发送邮件通知。下面是一个示例,展示如何在爬虫结束后通过邮件发送通知:

extensions.py:

python">import smtplib
from scrapy import signalsclass EmailNotificationExtension:def __init__(self, smtp_server, smtp_port, from_email, to_email, password):self.smtp_server = smtp_serverself.smtp_port = smtp_portself.from_email = from_emailself.to_email = to_emailself.password = password@classmethoddef from_crawler(cls, crawler):settings = crawler.settingsreturn cls(smtp_server=settings.get('SMTP_SERVER'),smtp_port=settings.get('SMTP_PORT'),from_email=settings.get('FROM_EMAIL'),to_email=settings.get('TO_EMAIL'),password=settings.get('EMAIL_PASSWORD'))def open_spider(self, spider):self.spider = spiderdef close_spider(self, spider):self.send_email()def send_email(self):with smtplib.SMTP(self.smtp_server, self.smtp_port) as server:server.starttls()server.login(self.from_email, self.password)subject = 'Scrapy Spider Finished'body = 'Your Scrapy spider has finished running successfully!'msg = f'Subject: {subject}\n\n{body}'server.sendmail(self.from_email, self.to_email, msg)

settings.py 中启用邮件扩展:

python">EXTENSIONS = {'myproject.extensions.EmailNotificationExtension': 500,
}

以上内容详细解读了 Scrapy 框架的运行原理、底层源码、中间件和自定义功能,涵盖了从请求生成、响应处理到数据存储的完整流程。希望这些示例和讲解能够帮助你更好地理解和使用 Scrapy 框架,在实际开发中灵活应用。


http://www.ppmy.cn/server/96512.html

相关文章

IP SSL证书的具体申请方式

IP作为网络访问的基础,是日常访问网站中常用的访问方式。为了方便记忆很多IP都会额外绑定或指向某个域名,以数字字母的形式方便记忆。 但是IP确是基础访问的前提条件,类似于政务服务系统、高校内部的系统,在域名无法满足使用的情…

Langchain核心模块与实战[9]:RAG检索增强生成[文本向量化、实战ChatDoc智能文档助手]

Langchain核心模块与实战[9]:RAG检索增强生成[文本向量化、实战ChatDoc智能文档助手] 参考文章可以使用国产LLM进行下述项目复现: 初识langchain[1]:Langchain实战教学,利用qwen2.1与GLM-4大模型构建智能解决方案[含Agent、tavily面向AI搜索]langchain[2]:Langchain实战教…

C++速学day1

抽象 数据抽象 功能抽象 即抽象出对某些东西的共性,比如说人的名字,性别,年龄,人的行为,吃饭,走路,工作学习之类。用C的函数来表达。对同一个研究对象,由于研究的问题侧重点…

CSS3中的3D变换

CSS3中的3D变换(3D Transformations)允许我们在网页中创建3D效果的元素。它提供了一系列的属性和方法,可以将元素沿x、y和z轴进行移动、旋转、缩放和倾斜。 以下是CSS3中常用的3D变换属性: 1. transform-style:定义了…

HCIP笔记4-OSPF(2)

OSPF2: OSPF的不规则区域 1.远离骨干的非骨干区域 1)不连续骨干 由于区域水平分割(从一区域来的路由不能回到该区域)导致的两个骨干拿不到对方的路由 解决方案: 2)tunnel---点到点GRE 在合法与非合法ABR间建立隧道,然后将其…

tls.go中的流程梳理

文章目录 tls.go中的流程梳理b站博主的 tls 加密过程自己推理的过程(未完待续)发送ClientHello获取ServerHello tls.go中的流程梳理 b站博主的 tls 加密过程 客户端发送ClentHello(tls版本 加密套件 随机数1)服务器发送ServerHello(tls版本 加密套件 随机数2) 这个阶段之后&…

OpenHarmony网络请求库-httpclient

简介 HTTP是现代应用程序通过网络交换数据和媒体的的主要方式。httpclient是OpenHarmony 里一个高效执行的HTTP客户端,使用它可使您的内容加载更快,并节省您的流量。httpclient以人们耳熟能详的OKHTTP为基础,整合android-async-http&#xf…

OpenGL ES->工作机制

渲染流程 渲染目的:输入3D立体坐标,输出绘制后的2D平面像素工作流程:顶点着色器->图元装配->几何着色器->光栅化->片段着色器->测试与混合,整个工作流程被封装在GPU内部,无法改变。运行在CPU的代码调用…