当你需要采集的网站不止一两个,而是成百上千,且对数据质量、爬取速度、异常处理有工程化要求时,自己用 requests + BeautifulSoup 从头搭建爬虫就会变得吃力。Scrapy 正是为此而生——一个成熟、高性能、可扩展的企业级爬虫框架。
Scrapy 的核心架构
Scrapy 基于 Twisted 异步网络引擎,天生支持高并发请求。它的核心组件及数据流大致如下:
- 引擎(Engine):控制所有组件之间的数据流,触发事件。
- 调度器(Scheduler):接收引擎发来的请求,排入队列,并在引擎请求时返回下一个要抓取的请求。支持去重(默认根据 URL 指纹)。
- 下载器(Downloader):负责获取网页内容并返回给引擎,再由引擎交给 Spider。
- 爬虫(Spider):用户自定义的解析逻辑。从响应中提取数据和新的请求链接(跟进爬取)。
- 项目管道(Item Pipeline):处理由 Spider 提取的数据(Item),进行清洗、验证、去重、存储等。
- 下载器中间件(Downloader Middleware):在引擎与下载器之间,可以全局修改请求和响应。
- 爬虫中间件(Spider Middleware):在引擎与 Spider 之间,可以处理 Spider 的输入(响应)和输出(Item、请求)。
整个流程是:Spider → Engine → Scheduler → Engine → Downloader → Engine → Spider,形成一个闭环,直到队列中没有新的请求。
Spider:聚焦解析逻辑
你开发的 Spider 类只需要定义两个核心部分:
start_requests/start_urls:生成初始请求。parse方法:接收下载器返回的 Response 对象,用 CSS 选择器或 XPath 提取数据,构造成Item对象(或字典)yield给管道;同时可以yield scrapy.Request(url, callback=self.parse)继续抓取后续页面。
Scrapy 内建的 scrapy shell 是调试选择器的利器,你可以加载一个 URL 后直接在命令行里测试 CSS / XPath。
中间件:扩展与控制
中间件可以理解为“全局钩子”,让你通过最小代价实现爬虫的通用功能。
- 下载器中间件:主要用于处理请求/响应。典型应用:
- 设置随机 User-Agent、代理 IP
- 处理 Cookie、重定向
- 集成 Selenium 或 Playwright 处理动态渲染页面(如
scrapy-playwright) - 爬虫中间件:较少直接使用,主要处理异常、调整 Spider 的输出。
自定义中间件只需实现对应方法(如 process_request(self, request, spider)),在 settings.py 中配置激活即可。
Item Pipeline:数据清洗与存储
当 Spider 产出一个 Item(或字典)后,它会被依次传到所有开启的 Pipeline 类中。每个 Pipeline 必须实现 process_item(self, item, spider) 方法,在其中可以做:
- 数据清洗:去除空值、格式化日期、转换数字类型
- 去重验证:检查数据库中是否已存在,决定是否丢弃
- 存储入库:保存到 MySQL、MongoDB、CSV 文件等
- 触发后续动作:比如写入 Kafka、发送通知
示例:一个简单的 JSON 存储 Pipeline。
import json
class JsonWriterPipeline:
def open_spider(self, spider):
self.file = open('items.json', 'w')
def close_spider(self, spider):
self.file.close()
def process_item(self, item, spider):
line = json.dumps(dict(item), ensure_ascii=False) + "\n"
self.file.write(line)
return item
在 settings.py 中通过 ITEM_PIPELINES 字典注册并设置优先级(数字越小优先级越高)。
分布式爬虫:突破单机瓶颈
面对海量 URL,单机 Scrapy 会触及性能上限。分布式爬虫的思路是:共享请求队列和去重集合。
- 核心组件 Scrapy‑Redis:用 Redis 数据库替代 Scrapy 默认的调度器和去重器。所有爬虫节点都从同一个 Redis 队列中取请求,并将新请求推入同一个队列。
- 改造极简:只需让你的 Spider 继承
RedisSpider(或RedisCrawlSpider),并使用redis_key而不是start_urls。然后启动多个爬虫进程(甚至在不同机器上),它们会自动协调。 - 常见部署:结合 Scrapyd(Scrapy 守护进程管理)或者 Docker + Kubernetes 管理节点,形成一套可水平扩展的抓取集群。
生产实践要点
- 遵守
robots.txt:默认 Scrapy 会遵守,但在合法合规范围内可调整。 - 设置下载延迟:
DOWNLOAD_DELAY和AUTOTHROTTLE自动限速,既保护目标站点,也降低被封风险。 - 日志与监控:Scrapy 内置详细日志,搭配
scrapy‑logstash或其他扩展,可实时监控爬虫运行状态。 - 异常处理:利用
RetryMiddleware自动重试失败请求,配合代理池确保高可用。
Scrapy 的学习曲线略高于简单脚本,但一旦掌握,它便成为你手中处理大规模数据采集的利器,让爬虫工程从“能跑”进化到“稳定、可维护、可扩展”。