Scrapling 四级递进抓取实战:从 FetcherSession 到 Spider 的官方示例全解
本篇以 Scrapling 官方 Agent Skill 中的 examples 目录为蓝本,完整讲解如何用同一个目标站点(quotes.toscrape.com,共 10 页 100 条语录)依次验证框架的四层抓取工具:FetcherSession、DynamicSession、StealthySession 与 Spider。读完后你将掌握:如何搭建示例环境、逐行理解四份可直接运行的示例脚本、每种工具背后的源码实现依据,以及“从最轻量方案逐级升级”的选型决策链。
环境准备与示例总览
四份示例代码位于 agent-skill/Scrapling-Skill/examples/ 目录,它们全部针对 quotes.toscrape.com 这个专为爬虫练习设计的沙箱站点,并采用统一的验收标准:收集全部 10 页、共 100 条语录。运行前需确保 Scrapling 已安装(当前仓库版本为 0.4.13,见 pyproject.toml):
pip install "scrapling[all]>=0.4.13"
scrapling install --force
其中 scrapling install --force 负责下载浏览器引擎(Playwright/Patchright)依赖,[all] 额外依赖组才会让 Dynamic/Stealthy 两类浏览器会话可用。
四份示例对应的工具矩阵如下(原文档表格完整保留):
| 文件 | 工具 | 类型 | 最佳适用场景 |
|---|---|---|---|
| 01_fetcher_session.py | FetcherSession |
Python 持久化 HTTP | API、高速多页抓取 |
| 02_dynamic_session.py | DynamicSession |
Python 浏览器自动化 | 动态页面 / SPA |
| 03_stealthy_session.py | StealthySession |
Python 隐身浏览器 | Cloudflare、指纹检测绕过 |
| 04_spider.py | Spider |
Python 自动爬取 | 多页爬取、整站抓取 |
示例一:FetcherSession —— 纯 HTTP 持久会话
from scrapling.fetchers import FetcherSession
all_quotes = []
with FetcherSession(impersonate="chrome") as session:
for i in range(1, 11):
page = session.get(
f"https://quotes.toscrape.com/page/{i}/",
stealthy_headers=True,
)
quotes = page.css(".quote .text::text").getall()
all_quotes.extend(quotes)
print(f"Page {i}: {len(quotes)} quotes (status {page.status})")
print(f"\nTotal: {len(all_quotes)} quotes\n")
for i, quote in enumerate(all_quotes, 1):
print(f"{i:>3}. {quote}")
该脚本不启动任何浏览器,全程只复用同一个 HTTP 会话对象完成 10 次请求,是最快最轻的方案。两个关键参数在源码中都有明确定义,位于 scrapling/engines/static.py:
impersonate="chrome":会话创建时写入self._default_impersonate(默认值就是"chrome",见 static.py 第 73 行)。从源码结构看,该值会被透传给curl_cffi,使请求携带与最新版 Chrome 一致的 TLS/JA3 指纹;当传入列表时,_select_random_browser会在每次请求时随机挑选一个浏览器指纹,用于进一步分散特征。stealthy_headers=True:在会话层面默认开启(self._stealth = kwargs.get("stealthy_headers", True)),用于补全真实浏览器风格的请求头。
FetcherSession 对外入口在 scrapling/fetchers/requests.py:模块从 scrapling.engines.static 直接重导出 FetcherSession,一次性请求则可用 Fetcher.get(...) 类方法(内部是模块级单例 __FetcherClientInstance__)。适用边界是文档注释给出的:静态或半静态站点、API、不需要 JavaScript 渲染的页面;一旦页面依赖 JS 生成内容,就升级到示例二。
示例二:DynamicSession —— Playwright 浏览器自动化
from scrapling.fetchers import DynamicSession
all_quotes = []
with DynamicSession(headless=False, disable_resources=True) as session:
for i in range(1, 11):
page = session.fetch(f"https://quotes.toscrape.com/page/{i}/")
quotes = page.css(".quote .text::text").getall()
all_quotes.extend(quotes)
print(f"Page {i}: {len(quotes)} quotes (status {page.status})")
print(f"\nTotal: {len(all_quotes)} quotes\n")
for i, quote in enumerate(all_quotes, 1):
print(f"{i:>3}. {quote}")
与示例一结构完全一致,唯一差异是 session.get() 换成了 session.fetch():浏览器在 with 块开始时启动一次,10 次 fetch 全部复用这个常驻浏览器窗口(headless=False 会弹出可见窗口便于观察),退出上下文时才关闭——这正是“会话”相对一次性 DynamicFetcher.fetch() 的效率优势。
参数语义可从 scrapling/fetchers/chrome.py 的参数注释得到印证:
headless:True为无头隐藏模式,False为可见模式(示例特意设为可见,方便调试观察每一页加载过程);disable_resources=True:丢弃图片、字体等无关资源请求以提速,对纯文本抽取场景几乎无副作用。
该方案面向 JavaScript 重度页面、SPA 与动态内容加载站点:凡是内容靠前端脚本渲染的,静态 HTTP 拿到的 HTML 都是“半成品”,必须交给真实浏览器。
示例三:StealthySession —— 隐身浏览器
from scrapling.fetchers import StealthySession
all_quotes = []
with StealthySession(headless=False) as session:
for i in range(1, 11):
page = session.fetch(f"https://quotes.toscrape.com/page/{i}/")
quotes = page.css(".quote .text::text").getall()
all_quotes.extend(quotes)
print(f"Page {i}: {len(quotes)} quotes (status {page.status})")
print(f"\nTotal: {len(all_quotes)} quotes\n")
for i, quote in enumerate(all_quotes, 1):
print(f"{i:>3}. {quote}")
脚本主体与前两个示例完全同构,区别在底层引擎:文件注释说明其基于 Patchright(对 Playwright 做了反检测补丁的隐身浏览器),用于绕过自动反机器人机制(Cloudflare Turnstile、指纹探测等)。scrapling/fetchers/stealth_chrome.py 中的参数注释进一步确认了两个关键开关:
headless:同样支持可见/无头两种模式;solve_cloudflare:开启后会在返回响应前自动解决 Cloudflare 的 Turnstile/Interstitial 各类质询——示例脚本未开启它,因为 quotes.toscrape.com 并非受保护站点,但该参数是应对真实受保护站点时唯一需要额外添加的选项。
该方案的定位是:受防护站点、被 Cloudflare 拦截、或能探测出 Playwright 特征的站点。
示例四:Spider —— 自动爬取框架
from scrapling.spiders import Spider, Response
class QuotesSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
concurrent_requests = 5 # Fetch up to 5 pages at once
async def parse(self, response: Response):
# Extract all quotes on the current page
for quote in response.css(".quote"):
yield {
"text": quote.css(".text::text").get(),
"author": quote.css(".author::text").get(),
"tags": quote.css(".tags .tag::text").getall(),
}
# Follow the "Next" button to the next page (if it exists)
next_page = response.css(".next a")
if next_page:
yield response.follow(next_page[0].attrib["href"])
if __name__ == "__main__":
result = QuotesSpider().start()
print(f"\n{'=' * 50}")
print(f"Scraped : {result.stats.items_scraped} quotes")
print(f"Requests: {result.stats.requests_count}")
print(f"Time : {result.stats.elapsed_seconds:.2f}s")
print(f"Speed : {result.stats.requests_per_second:.2f} req/s")
print(f"{'=' * 50}\n")
for i, item in enumerate(result.items, 1):
print(f"{i:>3}. [{item['author']}] {item['text']}")
if item["tags"]:
print(f" Tags: {', '.join(item['tags'])}")
# Export to JSON
result.items.to_json("quotes.json", indent=True)
print("\nExported to quotes.json")
这是质变的一步:不再手写 for i in range(1, 11) 翻页循环,而是让爬虫沿页面中的 “Next” 分页链接自动发现后续页面。要点拆解:
- 类属性即配置:
name、start_urls是必需项;concurrent_requests = 5表示同时最多抓取 5 个页面。对照 scrapling/spiders/spider.py,Spider基类默认concurrent_requests = 4、concurrent_requests_per_domain = 0(不限制单域名并发),本示例显式调高到 5。该值最终在 scrapling/spiders/engine.py 中落地为CapacityLimiter(spider.concurrent_requests)全局容量限制器,是并发的硬性天花板。 parse()生成器协议:yield字典即产出结构化条目(text/author/tags),yield response.follow(...)即向调度器提交一个新请求;引擎按响应自动回调parse,无需自己管理队列。- 统计与导出:
start()返回CrawlResult(见 spider.py 第 266-278 行),其stats字段(items_scraped、requests_count、elapsed_seconds、requests_per_second)由 engine.py 中的CrawlStats实时累加;result.items.to_json("quotes.json", indent=True)将全部条目导出为带缩进的 JSON 文件。
运行输出包括:爬取过程中的实时终端统计、结束时的汇总统计,以及当前目录下的 quotes.json。
运行方式与验收标准
按 examples/README.md 给出的执行方式,在 skill 包根目录下运行:
python examples/01_fetcher_session.py
python examples/02_dynamic_session.py # Opens a visible browser
python examples/03_stealthy_session.py # Opens a visible stealth browser
python examples/04_spider.py # Auto-crawls all pages, exports quotes.json
验收口径统一:脚本 01–03 应逐页打印 Page N: 10 quotes (status 200),最终输出 Total: 100 quotes 并编号列出 100 条语录;脚本 04 应打印 Scraped : 100 quotes 并生成 quotes.json。示例二、三默认打开可见浏览器,若要后台运行,把对应脚本里的 headless=False 改为 True 即可(各示例文件头部注释均已注明)。
升级决策链(Escalation Guide)
原文档给出的核心方法论是:从最快、最轻的方案起步,仅在必要时才逐级升级:
get / FetcherSession
└─ If JS required → fetch / DynamicSession
└─ If blocked → stealthy-fetch / StealthySession
└─ If multi-page → Spider
这条链与 Scrapling 官方 Skill(SKILL.md)中 CLI 命令的选择逻辑一一对应:scrapling extract get(HTTP)→ fetch(浏览器)→ stealthy-fetch(隐身浏览器),文档明确指出后两者的速度几乎相同,因此升级并不牺牲性能;而一旦涉及跨多页、需遵循链接关系的抓取,则应交给 Spider 框架而非手写循环。结合仓库文档,更细致的抓取方式选择可参阅 docs/fetching/choosing.md,蜘蛛框架的完整参考见 docs/spiders/getting-started.md。
适用前提与边界
- 版本前提:示例面向 Scrapling ≥ 0.4.13,且要求 Python 3.10+(SKILL.md 明确标注 Requires: Python 3.10+);Dynamic/Stealthy 示例必须先执行
scrapling install --force完成浏览器依赖下载。 - 目标站点前提:quotes.toscrape.com 是无防护的练习沙箱,因此示例一、二即可完整通过;示例三的
solve_cloudflare=True与 Spider 的robots_txt_obey、download_delay、autothrottle_enabled等选项在真实站点场景才需要启用。官方 Skill 的 Guardrails 也要求:只抓取有权限访问的内容、遵守 robots.txt 与站点条款、大规模爬取时加入延迟、不绕过付费墙、不抓取个人敏感数据。 - 代码可复现性:四份脚本均为独立完整文件,除
quotes.toscrape.com需可访问外,无其他外部依赖,可原样复制到本地 Python 环境中运行验证。
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 StartedRust0623
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