欢迎光临
我们一直在努力

Scrapling:一个让反爬系统看不见你的 Python 爬虫框架

在这里插入图片描述

你写好的爬虫,三个月后还能用吗?

读完本文你将了解:自适应选择器如何对抗页面改版 | Scrapling 的三层架构设计 | 无感知绕过 Cloudflare 的技术细节 | 它和 Scrapy/Playwright 到底该怎么选


🎯 这个项目解决什么问题?

你有过这种经历吗——花了一下午写好爬虫,第二天网站改了个 class 名,全白费。或者更惨,Cloudflare 的五秒盾卡住一切请求,代理池都救不了。

Python 爬虫生态不缺工具:Scrapy 是全家桶但太重,BeautifulSoup 是解析器不是爬虫,Playwright 能绕反爬但写起来像在操作浏览器。缺的是一个「聪明」的中间层——既有轻量级 HTTP 请求的速度,又能在遇到 Cloudflare 时自动切到隐身浏览器模式;既能写 CSS 选择器提取数据,又能网站改版后自动找到那些元素。

Scrapling 干的就这事儿。58k star、日增 1486 star 不是没道理。


🔧 快速上手

pip install "scrapling[fetchers]"
scrapling install

安装完就能直接干活。先试个最简单的:

from scrapling.fetchers import Fetcher

page = Fetcher.get('https://quotes.toscrape.com/')
quotes = page.css('.quote .text::text').getall()
print(quotes)

看到没?API 几乎和 Scrapy 一模一样,但不需要创建 Project、写 Spider 类、配置 Pipeline——三行代码拿结果。

现在上个硬的。Cloudflare 拦截的网站:

from scrapling.fetchers import StealthyFetcher

StealthyFetcher.adaptive = True # 开启自适应模式
page = StealthyFetcher.fetch(
'https://nopecha.com/demo/cloudflare',
headless=True,
network_idle=True
)
data = page.css('#padded_content a').getall()

StealthyFetcher 会在后台启动隐身浏览器,伪造指纹、解决 Cloudflare Turnstile 挑战,拿到页面后自动关浏览器。对调用方来说,就是一个函数调用。

⚠️ 踩坑提示:StealthyFetcher 依赖 Playwright 的 Chromium,首次使用需要 scrapling install 下载浏览器。Docker 用户可以直接用 pyd4vinci/scrapling 镜像,浏览器已预装。

如果要爬整站,上 Spider:

from scrapling.spiders import Spider, 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()
result.items.to_json("quotes.json") # 直接导出 JSON

支持 Ctrl+C 暂停,下次运行自动续爬——长任务不用从头再来。


⚙️ 技术原理

Scrapling 的核心卖点不是「又一个浏览器自动化工具」,而是三层引擎 + 自适应选择器的组合设计。

三层 Fetcher 架构

#mermaid-svg-3qIAMiXpkuQXoajQ{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-3qIAMiXpkuQXoajQ .error-icon{fill:#552222;}#mermaid-svg-3qIAMiXpkuQXoajQ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3qIAMiXpkuQXoajQ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3qIAMiXpkuQXoajQ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3qIAMiXpkuQXoajQ .marker.cross{stroke:#333333;}#mermaid-svg-3qIAMiXpkuQXoajQ svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3qIAMiXpkuQXoajQ p{margin:0;}#mermaid-svg-3qIAMiXpkuQXoajQ .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster-label text{fill:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster-label span{color:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster-label span p{background-color:transparent;}#mermaid-svg-3qIAMiXpkuQXoajQ .label text,#mermaid-svg-3qIAMiXpkuQXoajQ span{fill:#333;color:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ .node rect,#mermaid-svg-3qIAMiXpkuQXoajQ .node circle,#mermaid-svg-3qIAMiXpkuQXoajQ .node ellipse,#mermaid-svg-3qIAMiXpkuQXoajQ .node polygon,#mermaid-svg-3qIAMiXpkuQXoajQ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3qIAMiXpkuQXoajQ .rough-node .label text,#mermaid-svg-3qIAMiXpkuQXoajQ .node .label text,#mermaid-svg-3qIAMiXpkuQXoajQ .image-shape .label,#mermaid-svg-3qIAMiXpkuQXoajQ .icon-shape .label{text-anchor:middle;}#mermaid-svg-3qIAMiXpkuQXoajQ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-3qIAMiXpkuQXoajQ .rough-node .label,#mermaid-svg-3qIAMiXpkuQXoajQ .node .label,#mermaid-svg-3qIAMiXpkuQXoajQ .image-shape .label,#mermaid-svg-3qIAMiXpkuQXoajQ .icon-shape .label{text-align:center;}#mermaid-svg-3qIAMiXpkuQXoajQ .node.clickable{cursor:pointer;}#mermaid-svg-3qIAMiXpkuQXoajQ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-3qIAMiXpkuQXoajQ .arrowheadPath{fill:#333333;}#mermaid-svg-3qIAMiXpkuQXoajQ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3qIAMiXpkuQXoajQ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3qIAMiXpkuQXoajQ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3qIAMiXpkuQXoajQ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-3qIAMiXpkuQXoajQ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3qIAMiXpkuQXoajQ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster text{fill:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ .cluster span{color:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3qIAMiXpkuQXoajQ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-3qIAMiXpkuQXoajQ rect.text{fill:none;stroke-width:0;}#mermaid-svg-3qIAMiXpkuQXoajQ .icon-shape,#mermaid-svg-3qIAMiXpkuQXoajQ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-3qIAMiXpkuQXoajQ .icon-shape p,#mermaid-svg-3qIAMiXpkuQXoajQ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-3qIAMiXpkuQXoajQ .icon-shape .label rect,#mermaid-svg-3qIAMiXpkuQXoajQ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-3qIAMiXpkuQXoajQ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-3qIAMiXpkuQXoajQ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-3qIAMiXpkuQXoajQ :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

纯 HTTP

动态页面

绕过防火墙

用户代码

需要哪种 Fetcher?

Fetcher(curl_cffi 驱动)

DynamicFetcher(Playwright Chrome)

StealthyFetcher(隐身浏览器 + 指纹伪造)

Adaptive Selector(自适应选择器层)

数据结果

  • Fetcher:底层用 curl_cffi 模拟浏览器 TLS 指纹(Chrome/Firefox 都能伪装),纯 HTTP 请求,速度最快
  • DynamicFetcher:包装 Playwright Chromium,处理 JS 渲染的动态页面
  • StealthyFetcher:在 DynamicFetcher 基础上加隐身层——browserforge 伪造浏览器指纹 + apify-fingerprint-datapoints 注入反检测数据

三者共享同一个选择器接口,切换成本为零。你写 .css('.product'),不管底层是 curl 发的请求还是隐身浏览器渲染的页面,都能用。

自适应选择器:为什么网站改版了爬虫还能跑?

这是 Scrapling 最值得讲的设计。传统爬虫靠 CSS 选择器定位元素——.product-price、#main-content。网站一改 HTML 结构,选择器就失效。

Scrapling 的 auto_save=True 模式在首次选择时保存元素的指纹信息:标签名 + 文本内容 + 属性键值 + DOM 树上下文。下次网站改版后,用 adaptive=True 打开自适应模式,Scrapling 不再用死选择器去找,而是用元素相似度算法在页面上搜索匹配度最高的节点。

# 第一遍:正常选择 + 自动保存指纹
products = p.css('.product', auto_save=True)

# 网站改版后:自适应模式自动重定位
products = p.css('.product', adaptive=True)

这套机制的核心实现思路是:

  • 把元素特征向量化(标签、文本摘要、CSS 类名分布、父子节点关系)
  • 构建启发式相似度度量(不是逐字节比较 HTML,而是语义级匹配)
  • 基准测试显示 Scrapling 的元素查找速度是 AutoScraper 的 5 倍多(2.39ms vs 12.45ms)
  • 跟竞品对比:Scrapy 的自适应方案是 AutoScraper,但它依赖手动标注训练样本;Scrapling 的 auto_save 是在你第一次正常抓取时就隐式标注了,零额外成本。

    隐身引擎如何绕过 Cloudflare?

    Cloudflare Turnstile 是当前最常见的反爬挑战。Scrapling 从三个层面绕过它:

    ┌─────────────────────────────────────┐
    │ StealthyFetcher │
    │ │
    │ ┌───────────────────────────────┐ │
    │ │ browserforge: 随机化浏览器指纹│ │
    │ │ – WebGL 指纹 │ │
    │ │ – Canvas 指纹 │ │
    │ │ – 字体列表 │ │
    │ │ – 屏幕分辨率 & 平台信息 │ │
    │ └───────────────────────────────┘ │
    │ ┌───────────────────────────────┐ │
    │ │ apify-fingerprint-datapoints │ │
    │ │ – 注入真实浏览器特征数据 │ │
    │ └───────────────────────────────┘ │
    │ ┌───────────────────────────────┐ │
    │ │ solve_cloudflare=True │ │
    │ │ – 自动等待 + 通过 Turnstile │ │
    │ └───────────────────────────────┘ │
    └─────────────────────────────────────┘

    和 Playwright Stealth 插件相比,Scrapling 的隐身层更「无感」——你不需要手动注入 stealth 脚本或配置额外参数,一行 StealthyFetcher.adaptive = True 就搞定。


    🏗️ 架构分析

    模块划分

    Scrapling 的项目结构很清晰,核心模块都放在 scrapling/ 下:

    #mermaid-svg-d8lzzEzimgxA62kA{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-d8lzzEzimgxA62kA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-d8lzzEzimgxA62kA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-d8lzzEzimgxA62kA .error-icon{fill:#552222;}#mermaid-svg-d8lzzEzimgxA62kA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-d8lzzEzimgxA62kA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-d8lzzEzimgxA62kA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-d8lzzEzimgxA62kA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-d8lzzEzimgxA62kA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-d8lzzEzimgxA62kA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-d8lzzEzimgxA62kA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-d8lzzEzimgxA62kA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-d8lzzEzimgxA62kA .marker.cross{stroke:#333333;}#mermaid-svg-d8lzzEzimgxA62kA svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-d8lzzEzimgxA62kA p{margin:0;}#mermaid-svg-d8lzzEzimgxA62kA .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-d8lzzEzimgxA62kA .cluster-label text{fill:#333;}#mermaid-svg-d8lzzEzimgxA62kA .cluster-label span{color:#333;}#mermaid-svg-d8lzzEzimgxA62kA .cluster-label span p{background-color:transparent;}#mermaid-svg-d8lzzEzimgxA62kA .label text,#mermaid-svg-d8lzzEzimgxA62kA span{fill:#333;color:#333;}#mermaid-svg-d8lzzEzimgxA62kA .node rect,#mermaid-svg-d8lzzEzimgxA62kA .node circle,#mermaid-svg-d8lzzEzimgxA62kA .node ellipse,#mermaid-svg-d8lzzEzimgxA62kA .node polygon,#mermaid-svg-d8lzzEzimgxA62kA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-d8lzzEzimgxA62kA .rough-node .label text,#mermaid-svg-d8lzzEzimgxA62kA .node .label text,#mermaid-svg-d8lzzEzimgxA62kA .image-shape .label,#mermaid-svg-d8lzzEzimgxA62kA .icon-shape .label{text-anchor:middle;}#mermaid-svg-d8lzzEzimgxA62kA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-d8lzzEzimgxA62kA .rough-node .label,#mermaid-svg-d8lzzEzimgxA62kA .node .label,#mermaid-svg-d8lzzEzimgxA62kA .image-shape .label,#mermaid-svg-d8lzzEzimgxA62kA .icon-shape .label{text-align:center;}#mermaid-svg-d8lzzEzimgxA62kA .node.clickable{cursor:pointer;}#mermaid-svg-d8lzzEzimgxA62kA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-d8lzzEzimgxA62kA .arrowheadPath{fill:#333333;}#mermaid-svg-d8lzzEzimgxA62kA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-d8lzzEzimgxA62kA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-d8lzzEzimgxA62kA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d8lzzEzimgxA62kA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-d8lzzEzimgxA62kA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d8lzzEzimgxA62kA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-d8lzzEzimgxA62kA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-d8lzzEzimgxA62kA .cluster text{fill:#333;}#mermaid-svg-d8lzzEzimgxA62kA .cluster span{color:#333;}#mermaid-svg-d8lzzEzimgxA62kA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-d8lzzEzimgxA62kA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-d8lzzEzimgxA62kA rect.text{fill:none;stroke-width:0;}#mermaid-svg-d8lzzEzimgxA62kA .icon-shape,#mermaid-svg-d8lzzEzimgxA62kA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-d8lzzEzimgxA62kA .icon-shape p,#mermaid-svg-d8lzzEzimgxA62kA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-d8lzzEzimgxA62kA .icon-shape .label rect,#mermaid-svg-d8lzzEzimgxA62kA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-d8lzzEzimgxA62kA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-d8lzzEzimgxA62kA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-d8lzzEzimgxA62kA :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    依赖

    依赖

    依赖

    依赖

    scrapling/fetchers/

    请求获取层

    scrapling/spiders/

    整站爬取层

    scrapling/core/

    解析 + 自适应引擎

    scrapling/cli.py

    命令行 & 交互 Shell

    fetchers/:三层请求器 + Session 管理 + ProxyRotator。Lazy import 设计避免初始化时加载浏览器驱动。

    spiders/:Scrapy 风格的 Spider 框架——但用 asyncio 重写,支持并发爬取、断点恢复、多 Session 切换。Scheduler 负责请求队列调度,SessionManager 管理不同类型的连接池。

    core/:解析器和自适应选择器。基于 lxml 的 Selector 类提供 CSS/XPath/text/regex 四种选择方式,自适应能力通过 auto_save 指纹存储实现。mixins.py 里的选择器生成算法能自动生成稳定的 CSS/XPath 选择器。

    cli.py:提供 scrapling shell 交互式调试环境和 scrapling extract 无代码数据提取。

    设计亮点

    懒加载 + 渐进安装:核心包只有 lxml/cssselect/orjson 三个依赖,不到 10MB。fetcher 的 Playwright/curl_cffi 放在 [fetchers] extras 里,MCP 支持放 [ai] 里。用户按需装,不污染环境。

    Fetcher-Session-Spider 三层解耦:Fetcher 可以独立用(快速单页抓取),也可以挂 Session(带 Cookie/代理管理的连续请求),还可以配合 Spider(全站并发爬取)。三个层级各自独立,组合使用。

    可以改进的地方

  • 文档结构偏平:README 虽然详细但信息密度过高,核心概念(自适应选择器 vs 隐身引擎 vs Spider)的最佳实践没有独立成章
  • 对非 Chromium 浏览器支持有限:隐身模式只支持 Chromium,Firefox 用户只能用不带隐身的 DynamicFetcher
  • MCP 集成仍在早期:AI 集成是最新特性,实际生产使用案例还不多

  • ✅ 优缺点 & 适用场景

    三个优点

  • 自适应选择器是滚雪球式的竞争优势——网站改版次数越多,你的爬虫维护成本越低,差距越拉越大
  • 三层 Fetcher 无缝切换——从 curl 到隐身浏览器,API 完全一致,迁移成本为零
  • 性能靠谱——lxml 解析层比 BS4 快 800 倍,json 序列化用 orjson 比标准库快 10 倍
  • 两个缺点

  • 学习成本存在:概念多(Fetcher/Session/Spider/自适应/隐身),新手上手比 requests + BS4 复杂
  • 隐身浏览器启动慢:StealthyFetcher 每次冷启动 1-2 秒,适合间歇性抓取,不适合每秒上百次的 API 调用
  • 谁该立刻试试

    • 正在维护多条爬虫、经常被网站改版折磨的工程师
    • 需要抓 Cloudflare 保护站点的数据分析师
    • 想从 Scrapy 迁移到更轻量方案但不想放弃 Spider 模式的人

    谁该再等等

    • 只需要抓几个静态页面的:requests + lxml 就够,别过度设计
    • 必须用 Firefox 做隐身抓取的:目前只支持 Chromium
    • 完全不会 Python 的:虽然有 CLI 模式,但进阶功能还是需要写代码

    如果只能用一个词形容 Scrapling,那会是 「务实」。它没有发明新技术,但把自适应解析、隐身浏览器、Spider 框架这三个已有能力做到了最顺滑的组合。在这个反爬技术日新月异的时代,这种「帮你少写适配代码」的工具,才是最值钱的。

    赞(0)
    未经允许不得转载:171主机测评 » Scrapling:一个让反爬系统看不见你的 Python 爬虫框架
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址