Scrapling 自适应 Web 爬虫框架:从单请求到大规模爬取的完整技术指南
本文基于 Scrapling 仓库中的官方 README(西班牙语版 docs/README_ES.md)撰写,系统讲解这套“自适应 Web 抓取框架”的三大核心——自适应解析器(Parser)、多引擎抓取器(Fetchers)与并发爬虫框架(Spiders),并结合仓库源码逐一印证其特性、安装方式、命令行工具与性能基准。读完后,你将能够独立完成安装配置、选择合适 Fetcher 发起请求、编写支持断点续爬的 Spider,以及使用 CLI 零代码提取页面内容。
Scrapling 官方定位是:“一个自适应的 Web 抓取框架,能够处理从单个请求到大规模爬取的一切(An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl)”。其两大核心卖点在 README 开篇即有明确表述:
- 解析器会“学习”网站变化:当页面结构更新后,能够自动重新定位(relocate)你之前保存的元素;
- Fetcher 原生具备反爬规避能力:可以直接处理 Cloudflare Turnstile/Interstitial 等反机器人系统;
- Spider 框架支持并发、多会话、Pause & Resume 与自动 Proxy 轮换,全部只用少量 Python 代码完成。
仓库中一段最精炼的入门代码即展示了“抓取 + 自适应解析”的主线用法(继承自 README):
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
StealthyFetcher.adaptive = True
p = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # 低姿态抓取网页
products = p.css('.product', auto_save=True) # 提取能“存活”于站点改版的数据
products = p.css('.product', adaptive=True) # 站点结构变化后,传 adaptive=True 即可重新找到元素
核心特性总览
README(docs/README_ES.md)将特性划分为五大板块:Spiders 爬虫框架、高级 Fetch 能力(含 Session)、自适应抓取与 AI 集成、高性能架构、以及开发者体验。下面逐一展开,并给出仓库中的实现位置作为佐证。
Spiders:完整的 Scrapy 风格爬取框架
官方特性列表包括(以下条目均出自 README,路径已转换为仓库相对路径以便查证):
- Scrapy 风格 API:用
start_urls、异步parse回调、Request/Response对象定义 Spider,实现位于 scrapling/spiders/spider.py; - 并发爬取:可配置并发上限、按域限速与下载延迟(对应 scrapling/spiders/throttle.py);
- 多会话(Multi-Session):在同一个 Spider 中统一使用 HTTP 请求与隐身浏览器会话,按会话 ID 路由请求到不同 Session;
- Pause & Resume:基于 Checkpoint 的爬取持久化,按
Ctrl+C可优雅停机,再次启动时从上次进度继续。源码中Spider.__init__接受crawldir参数,注释明确写着 “Directory for checkpoint files. If provided, enables pause/resume”(见 scrapling/spiders/spider.py#L106-L138); - 流式模式(Streaming):通过
async for item in spider.stream()在元素产生时即时消费,并附带实时统计,适合 UI、管道与长时爬取; - 被拦截请求检测:自动检测被拦截的请求并重试,重试逻辑可自定义;
- AutoThrottle:Spider 根据站点响应速度自动调整每个域的延迟,被限流/拦截时自动加倍延迟(或遵循
Retry-After响应头),恢复后再加速; - robots.txt 合规:可选
robots_txt_obey标志,尊重Disallow、Crawl-delay、Request-rate指令并按域缓存(实现见 scrapling/spiders/robotstxt.py); - 开发模式:首次运行时把响应落盘,后续运行直接回放,让你反复调试
parse()逻辑而不必反复访问目标服务器; - 即用型 Spider 模板:
CrawlSpider(按规则追链)、SitemapSpider(sitemap/robots 引导式爬取)、XMLFeedSpider/CSVFeedSpider(迭代 XML/RSS 与 CSV 源)、ShopifySpider(通过 Shopify JSON API 按变体粒度导出全部商品)。这些模板分别实现在 scrapling/spiders/templates/crawler.py、scrapling/spiders/templates/sitemap.py、scrapling/spiders/templates/feed.py 与 scrapling/spiders/templates/shopify.py,并从 scrapling/spiders/init.py 统一导出; - 链接提取原语:独立的
LinkExtractor,支持 allow/deny 模式、域名过滤、CSS/XPath 边界、扩展名过滤与规范化(实现见 scrapling/spiders/links.py); - 结果导出:除自带 hook/管道外,还提供内置导出方法。源码 scrapling/spiders/result.py 中可以看到
ItemsResult的四个导出方法签名:to_json(path, *, indent=False)、to_jsonl(path)、to_csv(path, *, fields=None, delimiter=",")、to_xml(path, *, root_tag="items", item_tag="item", indent=True)。
高级 Fetch 能力与 Session 体系
README 列出的高级抓取能力包括:
- HTTP 请求:
Fetcher提供快速的 HTTP 请求,可模仿浏览器 TLS 指纹、自定义请求头,并支持 HTTP/3; - 动态加载:
DynamicFetcher基于 Playwright 的 Chromium/Chrome 提供完整浏览器自动化; - 反爬规避:
StealthyFetcher具备更深入的隐身能力与指纹伪造,可自动处理各类 Cloudflare Turnstile/Interstitial 质询。在 scrapling/fetchers/stealth_chrome.py 的参数文档中可以看到:network_idle表示“等待页面直到至少 500 ms 没有网络活动”;solve_cloudflare表示“在返回响应前解决所有类型的 Cloudflare Turnstile/Interstitial 质询”;google_search默认启用,会设置 Google 来源 Referer; - 会话管理:
FetcherSession、StealthySession、DynamicSession三类持久会话类,用于跨请求维持 Cookie 与状态; - Proxy 轮换:内置
ProxyRotator,支持顺序(cyclic)或自定义轮换策略,可用于所有会话类型,并支持按请求覆盖 Proxy(实现见 scrapling/engines/toolbelt/proxy_rotation.py); - 域名/广告拦截:可拦截特定域名(含子域)的请求,或启用内置广告拦截(约 3500 个已知广告/追踪域名,见 scrapling/engines/toolbelt/ad_domains.py);
- DNS 泄漏防护:可选 DNS-over-HTTPS,将 DNS 查询经 Cloudflare DoH 路由,避免使用代理时发生 DNS 泄漏;
- 远程浏览器:通过
cdp_url用 CDP 连接已在运行的浏览器(本机、远程主机或托管浏览器服务);也可用executable_path让任意浏览器 Fetcher 指向你自己的 Chromium 构建; - 后台 API 捕获:给
capture_xhr传入 URL 模式,页面加载期间所有匹配的 XHR/fetch 响应会被收集为Response对象存入response.captured_xhr——无需逆向工程即可拿到站点 API 数据; - 完整 Async 支持:所有 fetcher 均有对应的 async 类与会话类。
从源码结构看,scrapling/fetchers/init.py 采用了惰性导入(_LAZY_IMPORTS 映射 + 模块级 __getattr__):Fetcher/AsyncFetcher/FetcherSession 来自 scrapling.fetchers.requests,DynamicFetcher/DynamicSession/AsyncDynamicSession 来自 scrapling.fetchers.chrome,StealthyFetcher/StealthySession/AsyncStealthySession 来自 scrapling.fetchers.stealth_chrome。这也解释了为什么只装基础包时导入 scrapling.fetchers 里的任何类会抛出 ModuleNotFoundError——底层依赖(如 curl_cffi、Playwright)属于可选依赖组。
自适应抓取与 AI 集成
- 智能元素追踪:基于相似度算法在网站改版后重新定位元素。解析器入口 scrapling/parser.py 中
Selector的构造参数包含adaptive: Optional[bool] = False,文档注释说明该参数是“全局关闭自适应功能”的总开关,且优先级高于所有 adaptive 相关方法/参数——即 adaptive 能力默认关闭,需要显式开启; - 灵活的选择方式:CSS 选择器、XPath、基于过滤器的查找、文本查找、正则查找等(详见 docs/parsing/selection.md);
- 相似元素查找:自动定位与已找到元素相似的其他元素(
find_similar()); - MCP 服务器:内置 Model Context Protocol 服务器,用于 AI 辅助的 Web 抓取与数据提取;它先利用 Scrapling 提取目标内容再交给 AI(Claude/Cursor 等),以减少 token 消耗,还支持跨调用保持浏览器会话、页面截图与 CDP 远程浏览器控制(说明文档见 docs/ai/mcp-server.md);
- Agent Skill:仓库内提供开箱即用的 agent-skill 目录(含
SKILL.md与完整的参考文档),教编程 Agent 使用与当前 API 一致的 Scrapling 写法,避免“靠猜”生成代码。
高性能架构与开发体验
README 的性能主张(均以仓库官方表述为准):解析速度超过大多数 Python Web 抓取库、内存占用优化(惰性加载)、JSON 序列化比标准库快约 10 倍、测试覆盖率 92% 且具备完整类型提示(每次变更用 PyRight 与 MyPy 扫描全量源码)。
开发者体验方面的特性包括:可选的 IPython 交互 Shell(含 curl 转 Scrapling 请求、在浏览器中查看请求结果等快捷工具)、直接通过终端命令抓取 URL 而无需写代码、丰富的 DOM 导航 API(父/兄弟/子元素)、内置 regex 与字符串清洗方法、CSS/XPath 选择器自动生成、与 Scrapy/BeautifulSoup 相似且兼容 Scrapy/Parsel 伪元素(::text、::attr() 等)的 API,以及与 Scrapy 的直接集成——用 scrapling_response 装饰器即可把 Scrapy 回调里已有的响应交给 Scrapling 解析器(集成代码见 scrapling/integrations/scrapy.py)。
快速上手
基础用法:三种 Fetcher + 对应会话
以下示例完整继承自 README(docs/README_ES.md 的“Primeros Pasos”一节)。
HTTP 请求(带会话支持)——Fetcher 可模仿 Chrome 最新 TLS 指纹:
from scrapling.fetchers import Fetcher, FetcherSession
with FetcherSession(impersonate='chrome') as session: # 使用最新版 Chrome TLS 指纹
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
quotes = page.css('.quote .text::text').getall()
# 或者使用一次性请求
page = Fetcher.get('https://quotes.toscrape.com/')
quotes = page.css('.quote .text::text').getall()
高级隐身模式——solve_cloudflare=True 会在返回前自动通过 Cloudflare 质询;StealthySession 会保持浏览器打开直到你结束所有请求:
from scrapling.fetchers import StealthyFetcher, StealthySession
with StealthySession(headless=True, solve_cloudflare=True) as session:
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
data = page.css('#padded_content a').getall()
# 或者用一次性请求风格:为此请求打开浏览器,完成后自动关闭
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
data = page.css('#padded_content a').getall()
完整浏览器自动化——DynamicFetcher 走标准 Playwright 路线,也支持 XPath:
from scrapling.fetchers import DynamicFetcher, DynamicSession
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session:
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
data = page.xpath('//span[@class="text"]/text()').getall() # 如果你喜欢 XPath
# 或者一次性请求风格
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
data = page.css('.quote .text::text').getall()
三者如何取舍,仓库有专门文档给出速度、隐身性、反爬选项、JS 加载能力、内存占用等维度的对比表,见 docs/fetching/choosing.md。简言之:纯 HTTP 就能搞定的场景用 Fetcher;动态加载、小自动化与中小防护用 DynamicFetcher;更复杂的防护与 Cloudflare 质询用 StealthyFetcher。
按请求或全局配置解析器
所有 Fetcher 共享同一套解析器配置接口(来自 docs/fetching/choosing.md)。先于请求调用 configure,或直接设置类属性:
from scrapling.fetchers import Fetcher
Fetcher.configure(adaptive=True, keep_comments=False, keep_cdata=False) # 其余参数同
# 或者
Fetcher.adaptive = True
Fetcher.keep_comments = False
Fetcher.keep_cdata = False
可用配置参数为:adaptive、adaptive_domain、huge_tree、keep_comments、keep_cdata、storage、storage_args——与 Selector 类 的构造参数一致。任意时刻可用 <fetcher_class>.display_config() 打印当前配置。如前所述,adaptive 参数在 scrapling/parser.py#L89 中默认为 False,必须显式开启。
Spiders:并发爬取、多会话与断点续爬
基础并发爬虫(完整继承自 README):
from scrapling.spiders import Spider, Request, Response
class QuotesSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
concurrent_requests = 10
async def parse(self, response: Response):
for quote in response.css('.quote'):
yield {
"text": quote.css('.text::text').get(),
"author": quote.css('.author::text').get(),
}
next_page = response.css('.next a')
if next_page:
yield response.follow(next_page[0].attrib['href'])
result = QuotesSpider().start()
print(f"Se extrajeron {len(result.items)} citas") # 打印提取条数
result.items.to_json("quotes.json")
单个 Spider 内混用多种会话类型——受保护页面走隐身会话,其余走快速 HTTP 会话,sid 即会话路由 ID:
from scrapling.spiders import Spider, Request, Response
from scrapling.fetchers import FetcherSession, AsyncStealthySession
class MultiSessionSpider(Spider):
name = "multi"
start_urls = ["https://example.com/"]
def configure_sessions(self, manager):
manager.add("fast", FetcherSession(impersonate="chrome"))
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
async def parse(self, response: Response):
for link in response.css('a::attr(href)').getall():
# 受保护页面路由到隐身会话
if "protected" in link:
yield Request(link, sid="stealth")
else:
yield Request(link, sid="fast", callback=self.parse) # 显式 callback
Pause & Resume:给 Spider 传入 crawldir 即启用 Checkpoint 持久化:
QuotesSpider(crawldir="./crawl_data").start()
按 Ctrl+C 会优雅暂停并自动保存进度;再次启动同一 crawldir 时从断点继续。这与源码中 crawldir “If provided, enables pause/resume” 的注释(scrapling/spiders/spider.py#L106)一致。
直接用模板——例如抓取任意 Shopify 商店全部商品(每变体一条):
from scrapling.spiders import ShopifySpider
class MyStore(ShopifySpider):
target_website = "example.com"
result = MyStore().start() # 商店全部商品,一个变体一个条目
高级解析与 DOM 导航
不抓取网页时也可直接使用解析器:from scrapling.parser import Selector; page = Selector("<html>...</html>"),用法与 Fetcher 返回的页面完全一致。README 给出的完整解析示例:
from scrapling.fetchers import Fetcher
page = Fetcher.get('https://quotes.toscrape.com/')
# 多种选择方式
quotes = page.css('.quote') # CSS 选择器
quotes = page.xpath('//div[@class="quote"]') # XPath
quotes = page.find_all('div', {'class': 'quote'}) # BeautifulSoup 风格
# 等价写法
quotes = page.find_all('div', class_='quote')
quotes = page.find_all(['div'], class_='quote')
quotes = page.find_all(class_='quote') # 以此类推...
# 按文本内容查找
quotes = page.find_by_text('quote', tag='div')
# 高级导航
quote_text = page.css('.quote')[0].css('.text::text').get()
quote_text = page.css('.quote').css('.text::text').getall() # 链式选择器
first_quote = page.css('.quote')[0]
author = first_quote.next_sibling.css('.author::text')
parent_container = first_quote.parent
# 元素关系与相似度
similar_elements = first_quote.find_similar()
below_elements = first_quote.below_elements()
Async 会话管理示例
FetcherSession 同时兼容 sync/async 上下文;AsyncStealthySession 支持多标签页池并发,可用 get_pool_stats() 查看标签页池状态(占用/空闲/错误):
import asyncio
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
async with FetcherSession(http3=True) as session: # 上下文感知,sync/async 模式均可用
page1 = session.get('https://quotes.toscrape.com/')
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
# 使用 async 会话
async with AsyncStealthySession(max_pages=2) as session:
tasks = []
urls = ['https://example.com/page1', 'https://example.com/page2']
for url in urls:
task = session.fetch(url)
tasks.append(task)
print(session.get_pool_stats()) # 可选 - 浏览器标签页池状态(占用/空闲/错误)
results = await asyncio.gather(*tasks)
print(session.get_pool_stats())
CLI 与交互式 Shell
Scrapling 自带命令行界面(命令注册见 scrapling/cli.py:install、shell、extract、mcp 四个子命令),文档见 docs/cli/overview.md。
启动 Web 抓取交互式 Shell:
scrapling shell
不写任何代码直接提取页面到文件:默认提取 <body> 内容,输出格式由扩展名决定——.txt 输出纯文本,.md 输出 Markdown 表示,.html 输出 HTML 本体:
scrapling extract get 'https://example.com' content.md
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome'
scrapling extract fetch 'https://example.com' content.md --css-selector '#fromSkipToProducts' --no-headless
scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.html --css-selector '#padded_content a' --solve-cloudflare
性能基准
README 引用了仓库官方基准(数据见 docs/benchmarks.md,方法学脚本为 benchmarks.py,均为 100 次以上运行的平均值)。
文本提取速度(5000 个嵌套元素):
| # | 库 | 耗时 (ms) | 相对 Scrapling |
|---|---|---|---|
| 1 | Scrapling | 1.99 | 1.0x |
| 2 | Parsel/Scrapy | 2.06 | 1.035 |
| 3 | Raw Lxml | 2.56 | 1.286 |
| 4 | PyQuery | 23.98 | ~12x |
| 5 | Selectolax | 197.02 | ~99x |
| 6 | MechanicalSoup | 1545.15 | ~776.5x |
| 7 | BS4 + Lxml | 1562.1 | ~785.0x |
| 8 | BS4 + html5lib | 3412.73 | ~1714.9x |
自适应元素查找 / 文本搜索:
| 库 | 耗时 (ms) | 相对 Scrapling |
|---|---|---|
| Scrapling | 2.3 | 1.0x |
| AutoScraper | 12.58 | 5.47x |
注意:以上为仓库官方文档公布的对比数据,复现时以 benchmarks.py 中的方法学为准;实际表现会随运行环境、库版本变化。
安装与部署
Scrapling 要求 Python 3.10 或更高版本(pyproject.toml 中 requires-python = ">=3.10")。
1. 基础安装(仅解析引擎)
pip install scrapling
重要:基础安装只包含解析引擎及其依赖,不含任何 Fetcher 与命令行依赖。此时从
scrapling.fetchers或scrapling.spiders导入任何内容都会抛出ModuleNotFoundError。如需使用 Fetcher 或 Spider,必须先安装 fetchers 依赖组。
2. 安装 Fetchers 与浏览器依赖
pip install "scrapling[fetchers]"
scrapling install # 常规安装
scrapling install --force # 强制重装
这会在本地下载所有浏览器及其系统依赖与指纹处理依赖。也可以从代码中安装:
from scrapling.cli import install
install([], standalone_mode=False) # 常规安装
install(["--force"], standalone_mode=False) # 强制重装
从 scrapling/cli.py#L120-L142 的 install 实现可以看到,它实际执行了三件事:python -m playwright install chromium、python -m playwright install-deps chromium,以及更新 tld 域名数据,完成后写入 .scrapling_dependencies_installed 标记文件——标记已存在且未加 --force 时直接提示 “The dependencies are already installed”。
3. 可选依赖组(对应 pyproject.toml#L72-L96 中的 optional-dependencies 定义):
pip install "scrapling[ai]" # MCP 服务器功能
pip install "scrapling[shell]" # Web 抓取 Shell 与 extract 命令
pip install "scrapling[all]" # 全部功能
其中 [fetchers] 依赖组包含 click、curl_cffi、playwright、patchright、browserforge、apify-fingerprint-datapoints、msgspec、anyio、protego;[ai] 额外需要 mcp 与 markdownify 并自动带入 [fetchers];[shell] 依赖 IPython>=8.37(最后一个支持 Python 3.10 的版本线)、markdownify 与 [fetchers]。无论装哪个 extra,只要用到浏览器 Fetcher,都别忘了再执行一次 scrapling install。
4. Docker 方式(每个 release 会自动构建并推送包含全部 extras 与浏览器的镜像):
docker pull pyd4vinci/scrapling
# 或从 GitHub 容器注册表:
docker pull ghcr.io/d4vinci/scrapling:latest
使用须知与延伸阅读
- 合规声明(继承自 README 的免责声明):本库仅供教育与研究用途,使用者需遵守当地及国际上的数据抓取与隐私法律,并始终尊重目标网站的服务条款与 robots.txt 文件;
- 贡献:提交代码前请先阅读 CONTRIBUTING.md;
- 许可:BSD-3-Clause(见 LICENSE);
- 致谢:项目包含改编自 Parsel(BSD 许可)的代码,用于 scrapling/core/translator.py 子模块;
- 完整的主题文档在仓库内均有对应页面:选择方法、如何选择 Fetcher、Spider 架构、代理轮换与封锁、CLI 总览、MCP 服务器、自适应存储系统。
总结来说,Scrapling 的架构思路是“一个库、三种抽象”:Selector 负责会“自愈”的解析,Fetcher/DynamicFetcher/StealthyFetcher(及其 Session 变体)负责从纯 HTTP 到反爬规避的抓取,Spider 框架负责把前两者放大为可断点续爬、可流式消费、可多会话路由的并发爬取任务。理解这三层及它们之间 Response 对象的衔接,就掌握了使用整套框架的关键。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
