首页
/ Scrapling 四级递进抓取实战:从 FetcherSession 到 Spider 的官方示例全解

Scrapling 四级递进抓取实战:从 FetcherSession 到 Spider 的官方示例全解

2026-09-03 16:17:06作者:晏闻田Solitary

本篇以 Scrapling 官方 Agent Skill 中的 examples 目录为蓝本,完整讲解如何用同一个目标站点(quotes.toscrape.com,共 10 页 100 条语录)依次验证框架的四层抓取工具:FetcherSessionDynamicSessionStealthySessionSpider。读完后你将掌握:如何搭建示例环境、逐行理解四份可直接运行的示例脚本、每种工具背后的源码实现依据,以及“从最轻量方案逐级升级”的选型决策链。

环境准备与示例总览

四份示例代码位于 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 的参数注释得到印证:

  • headlessTrue 为无头隐藏模式,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” 分页链接自动发现后续页面。要点拆解:

  • 类属性即配置namestart_urls 是必需项;concurrent_requests = 5 表示同时最多抓取 5 个页面。对照 scrapling/spiders/spider.pySpider 基类默认 concurrent_requests = 4concurrent_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_scrapedrequests_countelapsed_secondsrequests_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_obeydownload_delayautothrottle_enabled 等选项在真实站点场景才需要启用。官方 Skill 的 Guardrails 也要求:只抓取有权限访问的内容、遵守 robots.txt 与站点条款、大规模爬取时加入延迟、不绕过付费墙、不抓取个人敏感数据。
  • 代码可复现性:四份脚本均为独立完整文件,除 quotes.toscrape.com 需可访问外,无其他外部依赖,可原样复制到本地 Python 环境中运行验证。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384