Scrapy 重构新选择:scrapy_cffi 快速上手教程

作者:两只好日期:2025/10/2

随着爬虫场景的不断升级,Scrapy 虽然成熟稳定,但在异步支持、WebSocket 和现代请求库等方面有一些局限。

scrapy_cffi 是在 Scrapy 风格基础上重构的异步爬虫框架,支持更现代的请求库、扩展机制和异步 DB/MQ 管理。

通过这篇教程,你可以快速创建自己的异步爬虫项目,并体验框架的核心特性。


1.为什么要重构 Scrapy

Scrapy 本身虽然功能强大,但存在一些痛点:

  • IDE 提示有限:代码提示和补全不够友好
  • 异步支持弱:asyncio 协程能力有限,WebSocket 支持缺失
  • 不支持 TLS/JA3 指纹等高级特性

重构目标

  • 保留 Scrapy 风格,降低学习成本
  • 使用现代请求库 curl_cffi 替代 twisted
  • 支持自定义扩展、异步数据库和消息队列管理

💡如果你已经熟悉 Scrapy,上手 scrapy_cffi 非常快。


2.快速构建

2.1 安装框架

1pip install scrapy_cffi
2

2.1 创建项目

1# 新建项目
2scrapy-cffi startproject <project_name>
3 
4cd <project_name>
5 
6# 生成爬虫
7scrapy-cffi genspider <spider_name> <domain>
8"""
9genspider 后可选参数:
10    -r    创建 redis 爬虫
11    -m    创建 rabbitmq 爬虫
12    -k    启用 kafka 日志队列
13"""
14 
15# 运行爬虫
16python runner.py
17

3.配置

框架的配置基于 pydantic,支持类型校验和 IDE 自动补全。大部分简单请求参数(如并发数、延迟、重试、UA 等)开箱即用,下面是一些配置注意事项:

  • MAX_GLOBAL_CONCURRENT_TASKS
    未配置可能触发 fd 上限,尤其是 Windows。
  • QUEUE_NAME
    只在 run_spider 模式下有效;在 run_all_spiders 或分布式 WebSocket 爬虫下必须单独配置,否则会抢队列。
  • 数据库/消息队列(Redis / RabbitMQ / Kafka)
    只需配置 URL 和集群相关选项,框架会自动维护连接。
  • .envsettings.py
    支持自动转换,部署更方便,不用担心配置冲突。

更多配置见 docs


4.爬虫

框架完全异步,但爬虫层可以灵活编写:

  • 支持异步/同步方法
  • 支持 yield 或直接 return 请求和数据项
  • 保持 Scrapy 风格
1async def parse(self, response):
2    # 异步请求示例
3    yield HttpRequest(url="https://example.com")
4    yield Item(name="demo")
5

核心逻辑:定义函数产出请求和 Item,其余由框架管理。


5.拦截器与管道

  • 延续 Scrapy 风格,middlewares 改名为 interceptors
  • 支持自定义下载器中间件、拦截器、Item Pipeline 和扩展组件
  • 使用习惯几乎与 Scrapy 一致

6.其他扩展

6.1 json 提取

  • 支持 Scrapy 同款 xpath/css/re 选择器
  • 自动解析嵌入或异常 JSON
  • 直接提取指定 key 的 value
  • 适合抓取 API、页面嵌入数据或日志文本等

6.2 protobuf 编码解码

  • 使用 bbpb 支持 Protobuf 编码与解码
  • 直接操作 Python 对象,无需 scheme
  • 适合处理二进制接口数据

6.3 支持 C 扩展注入

  • 将性能关键任务通过 C 扩展加速
  • 框架支持全局注入,任意代码中直接使用
  • 避免模块重名即可

推荐项目结构:

1/project
2|
3|- cpy_resources
4|    |- module1_dir
5|    |     |- build_dir
6|    |     |     |- libmodule1.dll      # Windows 编译的C扩展二进制文件
7|    |     |     |- libmodule1.so       # Linux 编译的 C 扩展二进制文件
8|    |     |     |- libmodule1.dylib    # macOS 编译的 C 扩展二进制文件
9|    |     |
10|    |     |- module1.pyi               # 可选,用于 ide 代码提示
11|    |     |- fallback.py               # C 扩展加载失败后可以尝试加载的纯 python 实现
12|    |     |- wrapper.py                # 通过 ctypes 加载 C 扩展的核心实现
13|    |
14|    |- module2_dir
15|    |- ...
16|
17|- extensions
18|- interceptors
19|- items
20|- pipelines
21|- spiders
22|- settings.py
23|- runner.py
24

然后在配置 settings.py 中定义:

1settings.CPY_EXTENSIONS.DIR = "cpy_extensions"
2
3from scrapy_cffi.models import CPYExtension
4settings.CPY_EXTENSIONS.RESOURCES = [
5    CPYExtension(module_name="module1_dir")
6]
7

框架会将扩展程序注入全局(应当避免和某些模块重名),在任意代码中直接使用

1import module1_dir
2

6.4 hook 插件

  • 通过各组件 hooks 提供核心功能
  • 不暴露所有方法,确保框架稳定性

6.5 模块化设计

  • 数据库/消息队列管理类及工具类可单独使用
  • 可组合为完整爬虫程序或独立爬虫工具库

7.快速 demo

通过 CLI 可以直接生成可运行 demo 项目:

1scrapy-cffi demo
2"""
3可选参数:
4    -r    创建 redis demo
5    -m    创建 rabbitmq demo
6    -k    启用 kafka 日志队列
7

Scrapy 重构新选择:scrapy_cffi 快速上手教程》 是转载文章,点击查看原文


相关推荐


云原生周刊:K8s 故障排查秘籍
KubeSphere 云原生2025/10/2

云原生热点 Perses v0.52.0 发布 Perses 是一个面向可观测性(observability)的开源仪表盘 / 可视化工具,作为 CNCF 的 Sandbox 级别项目。 近日,Perses 宣布了其 0.52.0 版本的发布,带来了多个重大特性与增强,其中包括:对持续性能剖析(continuous profiling)的支持(新增 Pyroscope 数据源插件与 Flame Chart 可视化面板)、日志探索能力(Loki 数据源插件 + 日志面板)、Prometheu


分布式计数器系统完整解决方案
nlog3n10/2/2025

多级缓存架构:本地缓存 + Redis集群 + 数据库,实现性能与可靠性平衡智能分片策略:根据热度动态调整分片数量,解决热点key问题异步数据同步:通过消息队列实现最终一致性,提升写入性能完善的限流防刷:多维度限流 + 用户行为校验,防止恶意攻击强大的容灾能力:自动故障检测、优雅降级、数据恢复机制系统可支持百万级并发,响应时间控制在10ms以内,可用性达到99.99%以上,完全满足大型互联网产品的需求。关键创新点基于访问频率的智能分片算法多级缓存的优雅降级机制操作日志的数据恢复方案。


iOS 26 能耗检测实战指南,升级后电池掉速是否正常 + KeyMob + Instruments 实时监控 + 优化策略
程序员不说人话10/1/2025

本文聚焦 iOS 26 能耗检测,分析系统升级初期耗电风险、Liquid Glass 视觉效果对电池的额外负荷、Adaptive Power 模式机制,介绍如何用 KeyMob + Instruments 记录电量曲线 /功率峰值 /负载指标,定位高耗电模块并优化方案。


Redisson和Zookeeper实现的分布式锁
getdu9/30/2025

可以使用红锁来解决不一致问题,建立多个主节点当获取锁成功的数量n/2+1及以上才算获取锁成功。我觉得就是一个排队,创建节点后看自己是不是最小,不是最小就监听前一个节点,是最小就获取锁成功,锁释放以后,zookeeper会通过Watcher通知当前客户端。客户端获取 /locks/my_lock 目录下所有的子节点,并按节点序号排序。客户端被唤醒后,回到第 2 步,重新检查自己是否变成了最小节点。如果自己不是最小节点,客户端就找到比自己序号小的前一个节点。如果自己创建的节点是序号最小的那个,则成功获取锁。


使用Claude Code Router轻松切换各种高性价比模型
小溪彼岸2025/10/3

前言 前段时间随着Claude Code CLI的爆火也随之火了一款Claude Code CLI扩展Claude Code Router,该扩展工具可以很方便的将各大主流模型接入到Claude Code CLI中使用(那段时间国内各大模型还没有支持Claude Code CLI,Claude Code CLI只能使用Claude Code模型),今天我们也来了解一下这款神奇的工具。对往期内容感兴趣的小伙伴也可以看往期内容: Claude Code CLI初体验 不习惯终端黑窗口?Claude


重新定义创意边界:Seedream 4.0深度测评——从个人创作到企业级生产的AI图像革命
一个天蝎座白勺程序猿2025/10/4

一、引言:AI图像创作的“奇点时刻”” 2025年的AI赛道,图像生成领域正经历一场“效率革命”。从Midjourney的写实风格到DALL·E 3的语义理解,技术迭代速度远超行业预期。然而,用户痛点始终存在: 创作流程割裂:生成、编辑、排版需切换多个工具,设计师日均耗时超3小时在“导出-导入”的重复操作中;一致性失控:多图合成时,人物比例、光影逻辑、风格统一性常需手动修正,电商海报批量生产效率低下;企业部署门槛高:私有化部署成本高昂,API调用缺乏行业适配方案,中小团队难以规模化应用。


Vue2 动态添加属性导致页面不更新的原因与解决方案
excel2025/10/6

在 Vue2 开发中,经常会遇到这样一个问题:对象新增属性后,数据虽然更新了,但页面并没有随之更新。本文将通过一个例子来说明原因,并给出解决方案。 一、问题示例 我们先来看一个简单的例子: <div id="app"> <p v-for="(value, key) in item" :key="key"> {{ value }} </p> <button @click="addProperty">动态添加新属性</button> </div> Vue 实例代码如下: co


【Node】单线程的Node.js为什么可以实现多线程?
你的人类朋友2025/10/7

前言 很多刚接触 Node.js 的开发者都会有一个疑问:既然 Node.js 是单线程的,为什么又能使用 Worker Threads 这样的多线程模块呢? 今天我们就来解开这个看似矛盾的技术谜题。 👀 脑海里先有个印象:【Node.js 主线程】是单线程的,但【可以通过其他方式】实现并行处理 什么是 Node.js 的"单线程"? 事件循环(Event Loop)机制 // 这是一个简单的 Node.js 程序 console.log('开始执行') setTimeout(() =>


第8章:定时任务与触发器——让 Bot 主动服务
芝麻开门-新起点2025/10/8

8.1 什么是定时任务? 在之前的章节中,我们的 Bot 都是被动响应用户的输入。用户提问,Bot 回答。但很多时候,我们希望 Bot 能够主动在特定时间执行任务,例如每天早上发送天气预报、定时提醒用户喝水、或者定期从网站抓取数据并汇报。这就是定时任务 (Scheduled Task) 的用武之地。 Coze 中的定时任务功能,允许你设置一个触发器 (Trigger),当满足预设的时间条件时,自动运行指定的 Bot 或工作流。这极大地扩展了 Bot 的应用场景,使其从一个问答工具变成了一个可以


突破速度障碍:非阻塞启动画面如何将Android 应用启动时间缩短90%
稀有猿诉2025/10/10

本文译自「Breaking the Speed Barrier: How Non-Blocking Splash Screens Cut Android App Launch Time by 90%」,原文链接sankalpchauhan.com/breaking-th…,由Sankalp Chauhan发布于2025年9月28日。 概述 正值佳节期间,我们在每个应用上都能看到精美的启动画面和自定义徽标。在开发这些应用时,每个 Android 开发者都会面临启动画面的困境:用户期望获得美观且品

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0