站点图标 高效码农

网站一改版爬虫就报废?这款Python库让你和CSS选择器失效的噩梦说再见

Scrapling:一个让网页抓取”不再怕网站改版”的 Python 框架

你是否曾经辛苦写好了一套爬虫脚本,结果目标网站一改版,所有 CSS 选择器全部失效,数据采集戛然而止?这几乎是每个做过网页抓取的人都经历过的噩梦。Scrapling 想要彻底解决这个问题。


目录

  1. Scrapling 是什么?
  2. 它能解决哪些核心痛点?
  3. 主要功能模块详解
  4. 性能到底有多快?
  5. 安装教程(手把手)
  6. 代码示例:从入门到实战
  7. 命令行工具:不写代码也能抓数据
  8. 与 AI 结合使用:MCP 服务器模式
  9. 常见问题解答
  10. 使用注意事项

Scrapling 是什么?

Scrapling 是一个用 Python 编写的自适应网页抓取框架,能够处理从单次 HTTP 请求到大规模并发爬取的全套需求。

它最独特的地方在于一个词:自适应

传统的爬虫脚本依赖固定的 CSS 选择器或 XPath 路径来定位页面元素。一旦目标网站调整了 HTML 结构,这些路径就全部失效,脚本需要手动维护。Scrapling 的解析器内置了一套相似度算法,能在网站结构发生变化后,自动重新定位你之前找到的元素,不需要你手动修改代码。

除了解析器,Scrapling 还内置了:

  • 一套能绕过 Cloudflare Turnstile 等反爬系统的 Fetcher(请求器)
  • 一个类似 Scrapy 的 Spider 框架,支持并发、多 Session 和暂停恢复
  • 一个可以不写代码直接从终端抓数据的 CLI 工具
  • 一个可以配合 Claude、Cursor 等 AI 工具使用的 MCP 服务器

用一句话总结:一个库,覆盖网页抓取的全链路需求,不需要东拼西凑各种工具。


它能解决哪些核心痛点?

在进入功能细节之前,先说说做网页抓取时最常遇到的三类问题,以及 Scrapling 是如何应对的:

痛点一:网站改版导致脚本失效

这是最常见的问题。Scrapling 的自适应元素追踪功能,会在第一次抓取时保存元素的位置特征,之后即使网站改版,也能根据相似度找回对应的元素。使用方式非常简单,在 CSS 选择器中加一个参数就行:

# 第一次抓取时保存元素特征
products = page.css('.product', auto_save=True)

# 网站改版后,用 adaptive=True 重新找到它们
products = page.css('.product', adaptive=True)

痛点二:遇到反爬机制被封

很多网站使用 Cloudflare 等反爬系统。Scrapling 内置了 StealthyFetcher,能够模拟真实浏览器的 TLS 指纹、请求头,并自动处理 Cloudflare Turnstile 验证,开箱即用,无需额外配置

痛点三:项目规模扩大后难以管理

从单个页面到大规模并发爬取,Scrapling 的 Spider 框架提供了并发控制、多 Session 路由、Checkpoint 断点续爬等能力,不需要你从零搭建这些基础设施。


主要功能模块详解

1. Spider 爬虫框架

Spider 是 Scrapling 面向大规模爬取场景设计的核心模块。如果你用过 Scrapy,会发现 API 设计非常相似,上手成本极低。

并发爬取:可以通过 concurrent_requests 参数控制同时发出的请求数量,并按域名设置节流和下载延迟,避免对目标服务器造成压力。

多 Session 支持:在同一个 Spider 里,你可以同时使用普通 HTTP 请求和隐秘无头浏览器。对于普通页面用快速 HTTP Session 处理,对于有反爬保护的页面路由到隐秘 Session,通过 Session ID 统一管理。

暂停与恢复:通过指定 crawldir 参数开启 Checkpoint 功能。运行中随时按 Ctrl+C 优雅中断,下次启动时传入同样的 crawldir,爬虫会从上次中断的位置继续,不丢失任何进度。

Streaming 模式:对于长时间运行的爬取任务,可以通过 async for item in spider.stream() 实时获取数据,不用等到全部完成才能处理结果,非常适合接数据管道或实时展示 UI。

被阻止请求检测:框架会自动识别哪些请求被目标网站拦截,并支持配置自定义重试逻辑。

内置数据导出:抓到的数据可以通过 result.items.to_json()result.items.to_jsonl() 直接导出为 JSON 或 JSONL 格式。


2. Fetcher 请求器

Scrapling 提供了三种不同用途的 Fetcher,分别应对不同场景:

Fetcher 类型 适用场景 特点
Fetcher / FetcherSession 普通 HTTP 请求,速度优先 支持 TLS 指纹模拟、HTTP/3,速度快
StealthyFetcher / StealthySession 有反爬保护的网站 高级浏览器指纹伪装,自动绕过 Cloudflare
DynamicFetcher / DynamicSession JavaScript 渲染的动态页面 基于 Playwright 的完整浏览器自动化

每种 Fetcher 都有对应的 Session 类,Session 支持跨请求保持 Cookie 和状态,非常适合需要登录或维持会话的场景。

此外,所有 Fetcher 都支持全异步模式AsyncFetcherAsyncStealthySessionAsyncDynamicSession),可以配合 asyncio 进行高并发异步爬取。


3. 自适应解析器

解析器是 Scrapling 的技术核心。它支持多种元素选择方式:

  • CSS 选择器page.css('.quote')
  • XPath 选择器page.xpath('//div[@class="quote"]')
  • BeautifulSoup 风格page.find_all('div', class_='quote')
  • 文本内容搜索page.find_by_text('quote', tag='div')
  • 相似元素自动查找element.find_similar()

解析器同样可以单独使用,不依赖 Fetcher,直接传入 HTML 字符串即可:

from scrapling.parser import Selector

page = Selector("<html>...</html>")
# 后续用法与 Fetcher 返回的 page 对象完全一致

还支持丰富的 DOM 导航操作:

first_quote = page.css('.quote')[0]

author = first_quote.next_sibling.css('.author::text')   # 下一个兄弟节点
parent = first_quote.parent                               # 父节点
similar = first_quote.find_similar()                      # 找相似元素
below = first_quote.below_elements()                      # 当前元素下方的元素

4. 代理轮换

内置 ProxyRotator,支持轮询或自定义轮换策略,适用于所有 Session 类型,并且可以按请求单独覆盖代理设置。还支持在基于浏览器的 Fetcher 中屏蔽特定域名(及其子域名)的请求,比如屏蔽广告追踪域名。


性能到底有多快?

性能是选择爬虫库时绕不开的话题。以下是官方提供的基准测试数据,测试场景为 5000 个嵌套元素的文本提取,每项测试均为 100+ 次运行的平均值:

文本提取速度对比

排名 耗时(毫秒) 与 Scrapling 的倍数关系
1 Scrapling 2.02 1.0x(基准)
2 Parsel / Scrapy 2.04 约 1.01x
3 Raw Lxml 2.54 约 1.26x
4 PyQuery 24.17 约 12x 慢
5 Selectolax 82.63 约 41x 慢
6 MechanicalSoup 1549.71 约 767x 慢
7 BS4 + Lxml 1584.31 约 784x 慢
8 BS4 + html5lib 3391.91 约 1679x 慢

可以看出,Scrapling 与 Parsel/Scrapy 处于同一量级,比 PyQuery 快约 12 倍,比 BeautifulSoup(配合 Lxml)快将近 800 倍。

自适应元素查找速度对比

耗时(毫秒) 倍数关系
Scrapling 2.39 1.0x
AutoScraper 12.45 约 5.2x 慢

在”自适应查找相似元素”这个细分场景里,Scrapling 比 AutoScraper 快 5 倍以上。

除了速度,Scrapling 还做了以下性能优化:

  • 使用优化的数据结构和延迟加载策略,内存占用极低
  • 内置比标准库快 10 倍的 JSON 序列化实现
  • 项目拥有 92% 的测试覆盖率和完整的类型提示,代码质量有保障
  • 已经在数百名开发者的日常使用中经过了超过一年的实战验证

安装教程(手把手)

Scrapling 需要 Python 3.10 或更高版本

基础安装(仅解析器)

pip install scrapling

这个命令只安装解析引擎,不包含任何 Fetcher 或命令行工具,适合只需要解析 HTML 的场景,依赖最轻量。

安装 Fetcher 及浏览器依赖

如果需要使用 StealthyFetcherDynamicFetcher 等,执行:

pip install "scrapling[fetchers]"
scrapling install

第二条命令会自动下载所需的浏览器(Chromium/Chrome)及其系统依赖,以及指纹操作相关的依赖库。

按需安装其他功能

功能模块 安装命令
MCP 服务器(AI 集成) pip install "scrapling[ai]"
命令行 Shell 和 extract 命令 pip install "scrapling[shell]"
全部功能 pip install "scrapling[all]"

注意:安装任何额外功能后,如果之前没有运行过 scrapling install,需要补跑一次,以确保浏览器依赖完整。

Docker 安装

如果不想在本地配置复杂的浏览器依赖,可以直接用官方 Docker 镜像,内置所有功能和浏览器:

# 从 DockerHub 拉取
docker pull pyd4vinci/scrapling

# 或从 GitHub 容器注册表拉取
docker pull ghcr.io/d4vinci/scrapling:latest

该镜像通过 GitHub Actions 在每次代码发布时自动构建,始终保持最新版本。


代码示例:从入门到实战

场景一:普通网页的 HTTP 抓取

最简单的用法,发一个 GET 请求,用 CSS 选择器提取数据:

from scrapling.fetchers import Fetcher, FetcherSession

# 方式一:一次性请求
page = Fetcher.get('https://quotes.toscrape.com/')
quotes = page.css('.quote .text::text').getall()

# 方式二:保持 Session(适合需要多次请求的场景)
with FetcherSession(impersonate='chrome') as session:
    page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
    quotes = page.css('.quote .text::text').getall()

impersonate='chrome' 会让请求使用 Chrome 最新版本的 TLS 指纹,对许多简单反爬措施有效。


场景二:绕过 Cloudflare 抓取受保护的页面

from scrapling.fetchers import StealthyFetcher, StealthySession

# 方式一:一次性请求,打开浏览器完成后自动关闭
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
data = page.css('#padded_content a').getall()

# 方式二:Session 模式,浏览器保持打开,适合连续抓取多个页面
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()

场景三:JavaScript 动态渲染页面

对于那些数据是通过 JavaScript 异步加载的页面,需要用完整浏览器来渲染:

from scrapling.fetchers import DynamicFetcher, DynamicSession

# 等待网络请求完成再抓取(network_idle=True)
page = DynamicFetcher.fetch('https://quotes.toscrape.com/', network_idle=True)
data = page.css('.quote .text::text').getall()

# 或使用 XPath 选择器
data = page.xpath('//span[@class="text"]/text()').getall()

场景四:构建完整爬虫(Spider)

类似 Scrapy 的写法,支持翻页、并发、数据导出:

from scrapling.spiders import Spider, Response

class QuotesSpider(Spider):
    name = "quotes"
    start_urls = ["https://quotes.toscrape.com/"]
    concurrent_requests = 10  # 最多 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"共抓取了 {len(result.items)} 条数据")
result.items.to_json("quotes.json")  # 保存为 JSON 文件

场景五:带断点续爬的长时间任务

对于可能中途中断的大型爬取任务,加上 crawldir 参数:

QuotesSpider(crawldir="./crawl_data").start()

运行中按 Ctrl+C 会优雅地保存当前进度。下次运行时传入同样的 crawldir,爬虫会自动从断点继续。


场景六:在一个 Spider 中混用多种 Session

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):
        # 注册两种 Session
        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:
                # 有保护的页面路由到隐秘 Session
                yield Request(link, sid="stealth")
            else:
                # 普通页面用快速 Session
                yield Request(link, sid="fast", callback=self.parse)

场景七:异步高并发抓取

import asyncio
from scrapling.fetchers import AsyncStealthySession

async def main():
    async with AsyncStealthySession(max_pages=2) as session:
        urls = ['https://example.com/page1', 'https://example.com/page2']
        tasks = [session.fetch(url) for url in urls]

        print(session.get_pool_stats())  # 查看浏览器标签池状态(忙碌/空闲/错误)
        results = await asyncio.gather(*tasks)
        print(session.get_pool_stats())

asyncio.run(main())

场景八:自适应元素追踪的完整流程

from scrapling.fetchers import StealthyFetcher

# 开启全局自适应模式
StealthyFetcher.adaptive = True

# 第一次抓取:用 auto_save=True 保存元素特征
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True)
products = page.css('.product', auto_save=True)

# ---- 网站改版之后 ----

# 用 adaptive=True 自动找回元素,即使选择器已经失效
products = page.css('.product', adaptive=True)

命令行工具:不写代码也能抓数据

CLI 演示

Scrapling 内置了强大的命令行工具,不需要写一行 Python 代码就能完成数据抓取。

启动交互式 Shell(需要先安装 scrapling[shell]):

scrapling shell

这会打开一个集成了 Scrapling 的 IPython 交互环境,支持将 curl 命令转换为 Scrapling 请求,并可以在浏览器中预览请求结果,非常适合调试选择器。

直接从命令行提取页面内容

# 提取整个页面为 Markdown
scrapling extract get 'https://example.com' content.md

# 提取纯文本
scrapling extract get 'https://example.com' content.txt

# 指定 CSS 选择器,模拟 Chrome
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

# 绕过 Cloudflare 提取
scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.html --css-selector '#padded_content a' --solve-cloudflare

输出格式由文件扩展名决定:

  • .txt → 目标元素的纯文本内容
  • .md → HTML 内容转换为 Markdown 格式
  • .html → 原始 HTML 内容

与 AI 结合使用:MCP 服务器模式

Scrapling 内置了 MCP(Model Context Protocol)服务器,可以让 Claude、Cursor 等 AI 工具直接调用 Scrapling 的抓取和解析能力。

这种集成方式有一个明显优势:AI 在处理网页内容时,不需要把整个页面的 HTML 全部传给大语言模型,而是通过 Scrapling 先精准提取目标内容,再将提取后的精简数据传给 AI,这样可以大幅缩短响应时间,同时显著减少 token 消耗,降低使用成本。

安装 MCP 功能:

pip install "scrapling[ai]"

常见问题解答

Q:Scrapling 和 Scrapy 有什么区别?

Scrapy 是一个成熟的大型爬虫框架,功能全面但相对重量级,学习曲线较陡。Scrapling 定位为更现代、更轻量的选择,特别加入了自适应元素追踪、内置反爬绕过和 AI 集成等 Scrapy 原生不具备的能力,同时 Spider API 设计对 Scrapy 用户非常友好,迁移成本低。

Q:StealthyFetcher 能绕过所有反爬系统吗?

根据文档,StealthyFetcher 能够开箱即用地自动绕过所有类型的 Cloudflare Turnstile 和 Interstitial 验证。对于其他类型的反爬系统,效果取决于具体实现。

Q:自适应元素追踪是怎么工作的?

Scrapling 在第一次用 auto_save=True 提取元素时,会将该元素的位置特征(如周围文本、层级关系、属性信息等)保存下来。当网站结构改变后,使用 adaptive=True 时,解析器会通过相似度算法在新的页面结构中找到最匹配的元素,而不是依赖固定路径。

Q:单纯想解析 HTML,不需要发请求,可以用 Scrapling 吗?

完全可以。直接用解析器模块即可:

from scrapling.parser import Selector
page = Selector("<html>你的HTML内容</html>")
# 后续用法和 Fetcher 返回的对象完全一样

Q:Session 模式和一次性请求有什么区别?

Session 模式(FetcherSessionStealthySession 等)会在多次请求之间共享 Cookie、Headers 和浏览器状态,适合需要登录或维持会话的场景。一次性请求(直接调用 Fetcher.get()StealthyFetcher.fetch())则每次都是独立的,适合简单快速的单次抓取。

Q:Scrapling 的 Docker 镜像有多大?包含什么?

Docker 镜像包含所有额外功能和浏览器(Chromium 等),通过 GitHub Actions 在每次版本发布时自动构建,保证与最新代码同步。具体镜像大小以实际拉取为准。

Q:可以在 Scrapling 里使用自定义代理吗?

可以。Scrapling 内置 ProxyRotator,支持轮询和自定义策略,适用于所有 Session 类型,并且可以在单个请求级别覆盖代理设置。


使用注意事项

在使用任何网页抓取工具时,有几点值得认真对待:

遵守目标网站的规则:在开始抓取之前,建议先查看目标网站的 robots.txt 文件(通常位于 https://example.com/robots.txt),了解哪些路径允许爬取,哪些明确禁止。同时阅读网站的服务条款,了解对数据采集是否有明确限制。

控制请求频率:即使技术上可以高并发抓取,也应该设置合理的下载延迟和并发限制,避免对目标服务器造成不必要的压力。Scrapling 的 Spider 框架内置了域名节流功能,合理配置即可。

数据使用合规:抓取到的数据应在适用法律框架内使用。不同国家和地区对数据采集、存储和使用有不同的法律要求(如 GDPR、个人信息保护法等)。

合法与教育用途:Scrapling 本身是一个用于教育和研究目的的工具。使用者需要对自己的行为负责,工具开发者和贡献者对软件的滥用不承担法律责任。


总结

Scrapling 是一个在设计上就考虑了”网站会变、反爬会有、规模会扩大”这三个现实问题的框架。

它不是要替代所有爬虫工具,而是在以下场景中提供了明显更好的选择:

  • 你在维护长期运行的数据采集脚本,担心网站改版破坏它
  • 你需要抓取有 Cloudflare 等反爬保护的网站,不想自己研究绕过方法
  • 你的项目从单机脚本扩展到并发爬取,需要一个结构化的框架来组织代码
  • 你想把网页内容接入 AI 工作流,需要高效的内容提取中间层

对于 Python 开发者、数据工程师和研究人员来说,这是一个值得在工具箱里放一份的库。


项目地址GitHub – D4Vinci/Scrapling

完整文档scrapling.readthedocs.io

PyPI 安装pip install scrapling


本文内容基于 Scrapling 官方 README 文档整理,技术细节以项目最新版本为准。

退出移动版