Scrapling:一个让网页抓取”不再怕网站改版”的 Python 框架
你是否曾经辛苦写好了一套爬虫脚本,结果目标网站一改版,所有 CSS 选择器全部失效,数据采集戛然而止?这几乎是每个做过网页抓取的人都经历过的噩梦。Scrapling 想要彻底解决这个问题。
目录
-
Scrapling 是什么? -
它能解决哪些核心痛点? -
主要功能模块详解 -
性能到底有多快? -
安装教程(手把手) -
代码示例:从入门到实战 -
命令行工具:不写代码也能抓数据 -
与 AI 结合使用:MCP 服务器模式 -
常见问题解答 -
使用注意事项
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 都支持全异步模式(AsyncFetcher、AsyncStealthySession、AsyncDynamicSession),可以配合 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 及浏览器依赖
如果需要使用 StealthyFetcher、DynamicFetcher 等,执行:
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)
命令行工具:不写代码也能抓数据
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 模式(FetcherSession、StealthySession 等)会在多次请求之间共享 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
PyPI 安装:pip install scrapling
本文内容基于 Scrapling 官方 README 文档整理,技术细节以项目最新版本为准。
