Scrapling 实战指南:从单条请求到全量爬取的自适应 Web Scraping 框架
本文基于 Scrapling 仓库的官方项目说明文档 README_PT_BR.md(葡语版 README,内容与英文主 README 保持同步)整理而成,覆盖其三大核心能力——自适应解析器、多类型 Fetcher 与会话管理、Scrapy 风格的 Spider 框架——并结合同仓库源码逐条印证关键特性的实现位置。读完后你将能够独立完成:带 TLS 指纹仿冒的 HTTP 请求、可绕过 Cloudflare Turnstile 的隐身浏览器抓取、并发爬取与断点续传,以及不写代码的命令行快速提取。
框架定位与整体能力
Scrapling 是一个自适应的 Web Scraping 框架,官方定位是“从单条请求到大规模爬取全部搞定”(An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl)。其三大支柱在文档中表述非常明确:
- 自适应解析器:从源码结构看,解析器在首次提取时会记录元素特征并持久化(见 parser.py 中
adaptive/auto_save参数逻辑),当目标页面改版导致 CSS 选择器失效时,通过相似度算法重新定位元素,而无需重写选择器; - 隐身 Fetchers:内置
StealthyFetcher等浏览器自动化引擎,可原生绕过 Cloudflare Turnstile/Interstitial 等反爬机制; - Spider 框架:支持并发爬取、多会话路由、checkpoint 断点续传与自动代理轮换。
文档开头给出的最小示例展示了“一条请求 + 自适应提取”的完整闭环:
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 重新定位
核心特性解析
Spiders:完整的爬虫框架
文档将 Spider 子系统列为第一大特性板块,其能力点可归纳为以下八项,且均能在仓库源码中找到对应实现:
| 特性 | 说明 | 源码佐证 |
|---|---|---|
| Scrapy 风格 API | start_urls、异步 parse 回调、Request/Response 对象 |
spider.py、request.py |
| 并发控制 | 全局与按域名的并发上限、下载延迟 | concurrent_requests、concurrent_requests_per_domain、download_delay 类属性 |
| 多会话路由 | 单只 Spider 内混用 HTTP 与隐身浏览器会话,按 ID 分流请求 | session.py 中的 SessionManager |
| 暂停/续爬 | 基于 checkpoint 的持久化,Ctrl+C 优雅退出后从断点恢复 | checkpoint.py,构造参数 crawldir |
| 流式模式 | async for item in spider.stream() 实时消费提取项与统计 |
result.py 的 CrawlResult |
| 阻塞检测 | 自动识别被拦截请求并重试,策略可自定义 | spider.py 中 BLOCKED_CODES = {401, 403, 407, 429, 444, 500, 502, 503, 504} |
| AutoThrottle | 根据目标响应速度自动调节每域延迟;遇限流/封锁时加倍延迟或遵循 Retry-After,恢复后自动提速 |
autothrottle_* 系列类属性(见 spider.py) |
| robots.txt 合规 | 可选 robots_txt_obey 开关,尊重 Disallow、Crawl-delay、Request-rate,按域缓存 |
robotstxt.py |
从 spider.py 的类属性定义可以进一步确认若干文档未逐一列出的默认值:concurrent_requests = 4(默认并发 4)、max_blocked_retries = 3(被拦截请求最多重试 3 次)、autothrottle_start_delay = 5.0 秒、autothrottle_max_delay = 60.0 秒;Spider.__init__ 接受 crawldir(启用 checkpoint 持久化的目录)与 interval(周期性 checkpoint 保存间隔,默认 300 秒)。此外还有“开发模式”:development_mode 开启后首次运行的响应会被落盘缓存,后续迭代 parse() 逻辑时直接回放缓存,不再向目标服务器发请求。
Spider 模板库位于 templates/init.py,从源码确认了文档列出的四类模板全部可用:
CrawlSpider:按规则跟随链接;SitemapSpider:以 sitemap/robots.txt 驱动的爬取;XMLFeedSpider/CSVFeedSpider:迭代 XML/RSS/CSV 数据源;ShopifySpider:通过 Shopify 的 JSON API 抓取任意店铺的全部商品,一个 SKU 变体一个数据项。
配套还有独立原语 LinkExtractor(links.py),支持 allow/deny 正则、域名过滤、CSS/XPath 限定范围、扩展名过滤与 canonical 化,既可配合模板使用,也可单独使用。提取结果可通过钩子、自定义 pipeline 或原生导出器落盘:result.items.to_json()、to_jsonl()、to_csv()、to_xml()。
带会话的站点抓取:三类 Fetcher + 代理轮换
抓取层的类导出关系在 fetchers/init.py 中通过惰性导入映射定义,共三类引擎、每类都有同步/异步与一次性/会话两种形态:
Fetcher/AsyncFetcher/FetcherSession:基于curl_cffi的快速 HTTP 请求(见 pyproject.toml 中fetchers依赖),可仿冒浏览器 TLS 指纹、自定义请求头、启用 HTTP/3;DynamicFetcher/DynamicSession/AsyncDynamicSession:完整的 Playwright 浏览器自动化,兼容 Chromium 与 Google Chrome;StealthyFetcher/StealthySession/AsyncStealthySession:基于 Patchright 的隐身自动化,具备指纹伪装能力,可处理各类 Cloudflare Turnstile/Interstitial 拦截。
除三类引擎外,文档列出的会话级能力还包括:ProxyRotator 原生代理轮换(支持轮换策略或自定义策略,且支持单请求级 proxy 覆盖,实现位于 proxy_rotation.py);基于域名及其子域的请求拦截,以及内置约 3500 个广告/追踪域名的原生广告拦截(域表见 ad_domains.py);可选 DNS-over-HTTPS(走 Cloudflare DoH),在使用代理时避免 DNS 泄漏;通过 cdp_url 连接远端已运行浏览器(本地、异地或托管浏览器服务),或通过 executable_path 指向自定义 Chromium 构建;capture_xhr 参数传入 URL 模式后,页面加载期间所有匹配的 XHR/fetch 响应会被收集到 response.captured_xhr,等于免逆向直接拿到目标 API 数据;全部 Fetcher 均提供完整的 async 版本。
自适应解析与 AI 集成
解析层是 Scrapling 的核心差异化能力:
- 元素智能追踪:页面改版后依据相似度算法重新定位元素。从 parser.py 的源码看,
Selector构造时可用adaptive参数全局开启自适应,css()/xpath()等提取方法再分别接受adaptive=True(对已保存元素执行重定位)与auto_save=True(首次提取时保存元素特征)两个参数,且存在优先级约束:若实例未启用自适应,auto_save会被忽略并给出提示; - 多元选择方式:CSS 选择器、XPath、基于过滤器的查找、按文本查找、正则查找,以及
find_similar()自动发现相似元素、below_elements()等结构关系方法; - MCP 服务器:原生 MCP Server 面向 AI 辅助抓取场景(文档与 docs/ai/mcp-server.md 对应),支持在把内容交给 Claude/Cursor 等模型之前做定向提取以降低 token 消耗,还能在多次调用间保持浏览器会话、截图页面、经 CDP 控制远程浏览器;仓库同时提供了可直接安装的 Agent Skill(agent-skill/Scrapling-Skill/SKILL.md),让编码 Agent 按当前 API 而非猜测来生成 Scrapling 代码;
- 性能与质量:文档声明 JSON 序列化比标准库快 10 倍(底层使用
orjson,见 pyproject.toml 的依赖列表)、测试覆盖率 92% 且全量 type hints,整个 codebase 每次变更都会被 PyRight 与 MyPy 扫描(pyproject.toml 中可见两项静态检查配置)。
开发者体验
文档还列出了一组工程侧特性:基于 IPython 的交互式抓取 Shell(scrapling shell,内置 curl 转 Scrapling 请求、浏览器预览结果等工具);纯命令行不写代码直接提取 URL;丰富的 DOM 导航 API(父节点、兄弟节点、子节点遍历);原生正则/文本清洗方法;为任意元素自动生成稳健的 CSS/XPath 选择器;与 Scrapy/BeautifulSoup 风格一致的 API 和 Scrapy/Parsel 同款伪元素;通过 scrapling_response 装饰器把 Scrapy 回调的响应无缝切换为 Scrapling 解析(实现见 integrations/scrapy.py),以及每次 release 自动构建并发布带全部浏览器的 Docker 镜像(构建定义见 Dockerfile)。
快速上手
基础用法:三种抓取形态
带会话的 HTTP 请求:
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()
隐身模式(Cloudflare 绕过):
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()
完整浏览器自动化:
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()
Spiders:并发、多会话与断点续传
构建一个带分页跟随的并发爬虫:
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"Extraídas {len(result.items)} citações")
result.items.to_json("quotes.json")
在单只 Spider 中混合使用多种会话,通过 sid 把不同链接路由到不同抓取引擎:
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) # 显式回调
暂停/续爬只需把 checkpoint 目录传给 start() 的构造参数:
QuotesSpider(crawldir="./crawl_data").start()
按 Ctrl+C 优雅暂停,进度自动保存;再次启动时传入相同 crawldir 即从断点继续。结合上文源码分析,checkpoint 默认每 300 秒自动落盘一次,退出时再保存一次。
用模板跳过爬虫样板代码,例如直接抓取整站 Shopify 商品:
from scrapling.spiders import ShopifySpider
class MyStore(ShopifySpider):
target_website = "example.com"
result = MyStore().start() # 店铺全部商品,一个变体一个 item
高级解析与导航
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()
不抓取网站时也可直接使用解析器,行为与抓取结果完全一致:
from scrapling.parser import Selector
page = Selector("<html>...</html>")
异步会话示例
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 with AsyncStealthySession(max_pages=2) as session:
tasks = []
urls = ['https://example.com/page1', 'https://example.com/page2']
for url in urls:
tasks.append(session.fetch(url))
print(session.get_pool_stats()) # 可选:查看浏览器标签池状态(占用/空闲/错误)
results = await asyncio.gather(*tasks)
print(session.get_pool_stats())
CLI 与交互式 Shell
Scrapling 自带命令行入口(pyproject.toml 注册了 scrapling 与 scrapling-mcp 两个可执行命令,实现位于 cli.py),完整命令说明见 docs/cli/overview.md。
启动交互式抓取 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
extract get 走纯 HTTP 引擎,extract fetch 走浏览器自动化引擎,extract stealthy-fetch 走隐身引擎并可加 --solve-cloudflare 过 Cloudflare 验证,--css-selector 可把提取范围限定到指定选择器。
性能基准
文档内置两组基准数据(均为 100 次以上运行的平均值,方法论见 benchmarks.py)。
文本提取速度(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 |
安装与环境要求
Scrapling 要求 Python 3.10 及以上(pyproject.toml 中 requires-python = ">=3.10"),基础安装:
pip install scrapling
需要注意官方给出的重要提示:默认安装只包含解析引擎及其依赖,不包含 fetchers 与 CLI 依赖。因此若像上文示例那样导入 scrapling.fetchers 或 scrapling.spiders,在仅安装基础包的环境下会抛出 ModuleNotFoundError。从 pyproject.toml 可确认基础依赖仅有 lxml、cssselect、orjson、tld、w3lib、typing_extensions,而 curl_cffi、playwright、patchright 等抓取依赖全部位于 fetchers 可选组中。
抓取与浏览器依赖(使用任何 Fetcher/Spider 功能前必须执行):
pip install "scrapling[fetchers]"
scrapling install # 正常安装浏览器及系统依赖
scrapling install --force # 强制重新安装
scrapling install 会下载全部浏览器、系统依赖与指纹处理依赖。也可以从代码中安装而不走命令行:
from scrapling.cli import install
install([], standalone_mode=False) # 正常安装
install(["--force"], standalone_mode=False) # 强制重装
其他可选扩展:
pip install "scrapling[ai]" # MCP 服务器功能
pip install "scrapling[shell]" # 交互式 Shell 与 extract 命令
pip install "scrapling[all]" # 全部功能
安装任一扩展后,若尚未执行过,仍需运行 scrapling install 补齐浏览器依赖。
Docker:官方镜像包含全部扩展与浏览器,从 DockerHub 或 GitHub 容器注册表拉取:
docker pull pyd4vinci/scrapling
# 或
docker pull ghcr.io/d4vinci/scrapling:latest
该镜像基于仓库主分支由 CI 自动构建发布,构建配置见 Dockerfile。
合规声明、引用与许可
文档中的法律声明值得抓取实践者留意:本库仅提供用于教育与研究目的;使用者须遵守当地及国际数据抓取与隐私法律;作者与贡献者不对软件的不当使用承担责任;应始终尊重目标网站的条款与 robots.txt 文件。这与 Spider 框架内置的 robots_txt_obey 合规开关(robotstxt.py)形成呼应。
若将 Scrapling 用于学术研究,文档建议采用如下引用:
@misc{scrapling,
author = {Karim Shoair},
title = {Scrapling},
year = {2024},
note = {An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!}
}
项目以 BSD-3-Clause 许可证发布(见 LICENSE),文档致谢部分说明其 translator 模块 改编自 Parsel(BSD 许可)。贡献规范见 CONTRIBUTING.md。
小结
Scrapling 将“请求—解析—爬取”三个层级的能力整合进单一库:解析层通过 adaptive/auto_save 机制让选择器在页面改版后自动重定位;抓取层提供纯 HTTP、标准浏览器、隐身浏览器三档引擎并统一了同步/异步与会话/一次性四种使用形态;爬取层以 Scrapy 风格 API 提供了并发、多会话路由、AutoThrottle、断点续传与模板库。结合本文给出的源码文件位置,读者可从 spider.py、parser.py 与 fetchers/init.py 出发,继续深入任意一层的具体实现。
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
