Scrapling 完全指南:从自适应解析到多会话爬虫框架的实战手册
【免费下载链接】Scrapling🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!项目地址: https://gitcode.com/GitHub_Trending/sc/Scrapling
本文以 Scrapling 仓库的官方主文档为骨架,完整覆盖其核心能力:三类 Fetcher(HTTP / 隐身 / 动态浏览器)、可暂停恢复的 Spider 爬虫框架、自适应元素定位、CLI 与交互式 Shell、性能基准以及安装部署方式。读完你可以直接在本地跑通从单个请求到大规模并发抓取的全套流程,并理解每个功能在源码中的落地位置。
项目定位与核心设计
Scrapling 是一个自适应(adaptive)Web Scraping 框架,覆盖从单个 HTTP 请求到全规模爬虫的完整链路。它的设计围绕三个支柱:
- 自适应解析器:解析器会学习网站结构变化,当页面改版后自动重新定位你之前保存过的元素;
- 隐身抓取器:内置对 Cloudflare Turnstile 等反爬机制的绕过能力;
- Spider 框架:支持并发、多会话、暂停/恢复、自动代理轮换的大规模爬虫,全部用几行 Python 完成。
官方快速示例展示了“抓取 + 自适应提取”的最小闭环:
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 重新找到元素也可以直接扩展为完整爬虫:
from scrapling.spiders import Spider, Response class MySpider(Spider): name = "demo" start_urls = ["https://example.com/"] async def parse(self, response: Response): for item in response.css('.product'): yield {"title": item.css('h2::text').get()} MySpider().start()从源码结构看,scrapling/fetchers/__init__.py通过_LAZY_IMPORTS映射表实现延迟导入:只有当你真正访问Fetcher、DynamicFetcher、StealthyFetcher等类时才加载对应模块(requests.py、chrome.py、stealth_chrome.py),这正是主文档强调的“基础安装只带解析器引擎、不带 Fetcher 依赖也能导入包本身”的底层原因。
Fetcher 家族与多类型抓取
三类请求能力的对比
| 类 | 底层机制 | 适用场景 |
|---|---|---|
Fetcher/AsyncFetcher | HTTP 客户端,可模拟浏览器 TLS 指纹、自定义请求头、HTTP/3 | 普通静态页面,速度优先 |
DynamicFetcher/DynamicSession | Playwright 驱动的 Chromium / 系统 Google Chrome | 需要 JS 渲染的动态页面 |
StealthyFetcher/StealthySession | 指纹伪装的隐身 Chromium(patchright) | 被 Cloudflare 等反爬保护的站点 |
基础 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()在 Fetcher 类中,get/post/put/delete均为类方法,内部委托给共享的__FetcherClientInstance__客户端实例;参数经_merge_selector_config合并解析器配置,因此Response对象可以直接调用css、xpath等选择器方法。
隐身模式(StealthyFetcher)
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()完整浏览器自动化(DynamicFetcher)
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()基于浏览器的进阶能力
主文档列出的 Fetcher 层高级特性还包括:
- Proxy 轮换:内置
ProxyRotator,支持周期性或自定义策略,适用于所有会话类型,且支持按请求覆盖代理; - 域名与广告拦截:可封锁指定域名(含子域)的请求,或启用内置广告拦截(约 3,500 个已知广告/追踪域名);
- DNS 泄漏防护:可选 DNS-over-HTTPS,将 DNS 查询经 Cloudflare DoH 转发,配合代理使用时避免 DNS 泄漏;
- 远程浏览器:通过
cdp_url连接已在运行的 CDP 浏览器(本机、远程服务器或托管浏览器均可),也可以用executable_path指向自己的 Chromium; - 后台捕获 API 请求:向
capture_xhr传入 URL 模式,页面加载期间所有匹配的 XHR/fetch 响应会以Response对象形式收集到response.captured_xhr中——无需自己逆向分析网站 API; - 全异步支持:所有 Fetcher 与异步会话类(
AsyncFetcher、AsyncDynamicSession、AsyncStealthySession)完整支持 async。
异步会话管理示例
import asyncio from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession async with FetcherSession(http3=True) as session: # FetcherSession 是上下文感知的,兼容同步/异步两种模式 page1 = session.get('https://quotes.toscrape.com/') page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135') # 使用 async 隐身会话并发抓取 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())Spiders:Scrapy 风格的全功能爬虫框架
Spider 子系统是 Scrapling 从“请求库”升级为“爬取框架”的关键。主文档列出的能力清单:
- Scrapy 风格 API:定义 Spider 类,使用
start_urls、asyncparse回调和Request/Response对象; - 并发控制:可配置的并发上限、按域限速、下载延迟;
- 多会话支持:同一个 Spider 内统一管理 HTTP 请求与无头隐身浏览器,通过
sid标识将请求路由到不同会话; - 暂停/恢复:基于 Checkpoint 的爬取续跑,Ctrl+C 平滑停止,重新运行后从断点恢复;
- Streaming 模式:
async for item in spider.stream()实时流式输出条目并附带即时统计,适合 UI、管道和长时爬取; - 封禁检测:自动检测被封请求并重试,重试逻辑可自定义;
- AutoThrottle:按域自动调整延迟——依据站点响应速度动态调参,被封禁或限流时加倍延迟(或遵循
Retry-After),恢复正常后再提速; - robots.txt 合规:可选
robots_txt_obey,尊重Disallow、Crawl-delay、Request-rate并按域缓存; - 开发模式:首次运行把响应落盘,之后重放缓存,允许反复调试
parse()而不重复请求目标服务器; - Spider 模板:
CrawlSpider(按规则跟踪链接)、SitemapSpider(基于 sitemap/robots.txt 爬取)、XMLFeedSpider/CSVFeedSpider(解析 XML/RSS 与 CSV 订阅源)、ShopifySpider(通过 Shopify JSON 接口拉取全店商品,每个 variant 一个条目); - 链接提取:独立的
LinkExtractor,支持 allow/deny 模式、域名过滤、CSS/XPath 作用域限定、扩展名过滤与链接规范化; - 内建导出:通过
result.items.to_json()、to_jsonl()、to_csv()、to_xml()直接落盘。
在 spiders 包入口中,以上能力一一对应导出:Spider、Request、CrawlResult、Scheduler、CrawlerEngine、SessionManager、LinkExtractor以及全部模板类。
基础 Spider 示例
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"Scraped {len(result.items)} quotes") result.items.to_json("quotes.json")从源码看 Spider 基类给出了各配置项的真实默认值,主文档示例中未显式写出的行为均可由此解释:
| 类属性 | 默认值 | 含义 |
|---|---|---|
concurrent_requests | 4 | 全局并发上限 |
concurrent_requests_per_domain | 0 | 按域并发限制,0 表示不额外限制 |
download_delay | 0.0 | 请求间下载延迟(秒) |
max_blocked_retries | 3 | 被封请求的最大重试次数 |
robots_txt_obey | False | 是否遵守 robots.txt |
development_mode | False | 是否启用响应缓存回放 |
autothrottle_enabled | False | 是否启用自动限速 |
autothrottle_start_delay | 5.0 | AutoThrottle 初始延迟 |
autothrottle_max_delay | 60.0 | AutoThrottle 延迟上限 |
同时源码中定义了封禁状态码集合BLOCKED_CODES = {401, 403, 407, 429, 444, 500, 502, 503, 504},这就是“封禁检测与自动重试”判定为封禁请求的依据。start()方法通过 anyio 驱动 asyncio 事件循环,并安装 SIGINT 信号处理器实现“第一次 Ctrl+C 优雅停止、第二次强制退出”;若构造时传入了crawldir,优雅停止时会保存 Checkpoint。
单 Spider 内混合多种会话
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)
QuotesSpider(crawldir="./crawl_data").start()按 Ctrl+C 平滑停止——进度自动保存;再次运行同一 Spider 并传入相同的crawldir,即从上次中断处恢复。源码中Spider.__init__的第二个参数interval(默认300.0秒)控制周期性 Checkpoint 的保存间隔。
模板:不写爬虫逻辑直接开工
以 Shopify 商店为例,拉取整个商品目录:
from scrapling.spiders import ShopifySpider class MyStore(ShopifySpider): target_website = "example.com" result = MyStore().start() # 商店的全部商品,每个 variant 一个条目模板类在 templates 模块中实现,配套测试见 test_templates.py 与 test_shopify.py。
高级解析与 DOM 导航
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() # 下方元素如果不需要抓取页面、只想解析已有 HTML,可以直接使用解析器:
from scrapling.parser import Selector page = Selector("<html>...</html>") # 后续 css/xpath/find_all 等用法完全一致解析器内核基于 lxml/cssselect,其中 CSS 到 XPath 的转换子模块源自 Parsel(BSD 许可),对应 translator 实现。解析能力的专项测试集中在 tests/parser 目录(如 test_adaptive.py 验证自适应定位、test_selectors_filter.py 验证选择器过滤)。
CLI 与交互式 Shell
Scrapling 附带功能完整的命令行工具(入口定义见 cli.py,由scrapling = "scrapling.cli:main"注册,见 pyproject.toml)。
交互式抓取 Shell
scrapling shell这是一个与 Scrapling 深度集成的 IPython Shell,内置快捷指令和辅助工具,例如把 curl 请求转换为 Scrapling 请求、在浏览器中查看请求结果等。
免代码直接提取页面
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输出格式由文件扩展名决定:默认提取<body>内内容;.txt输出纯文本;.md输出 Markdown 表示;.html输出 HTML 原文。从 cli.py 的源码结构看,extract是一个命令组,除文档中展示的get、fetch(DynamicFetcher)、stealthy-fetch(StealthyFetcher)外,还提供post、put、delete等完整的 HTTP 动词子命令,并共享一组 HTTP 选项(--impersonate等)与浏览器选项(--no-headless、--solve-cloudflare等)。此外 CLI 还提供scrapling install(安装浏览器依赖)、scrapling shell、scrapling-mcp(MCP 服务器)等顶层命令。
性能基准
主文档给出的基准数据(100 次运行均值,方法论见 benchmarks.py):
文本提取速度(5000 个嵌套元素)
| # | 库 | 耗时 (ms) | 相对 Scrapling |
|---|---|---|---|
| 1 | Scrapling | 1.99 | 1.0x |
| 2 | Parsel/Scrapy | 2.06 | 1.035x |
| 3 | Raw Lxml | 2.56 | 1.286x |
| 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 |
主文档还强调工程层面的性能设计:优化的数据结构与惰性加载降低内存占用;基于 orjson 的快速 JSON 序列化(orjson 是 pyproject.toml 中的硬依赖之一);代码库全量类型标注(py.typed标记,PyRight/MyPy 全量检查);92% 的测试覆盖率。
安装与可选依赖
Scrapling 要求Python 3.10+(pyproject.toml 中requires-python = ">=3.10",当前仓库版本为 0.4.13):
pip install scrapling重要:基础安装只包含解析器引擎及其依赖(lxml、cssselect、orjson、tld、w3lib、typing_extensions),不含任何 Fetcher 或 CLI 依赖。因此仅做基础安装时,
from scrapling.fetchers import ...或from scrapling.spiders import ...会抛出ModuleNotFoundError。如需使用 Fetcher 或 Spider,必须先安装 Fetcher 依赖:
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) # 强制重装可选功能包(对应 pyproject.toml 的optional-dependencies):
pip install "scrapling[ai]" # MCP 服务器(mcp、markdownify,且隐含 fetchers) pip install "scrapling[shell]" # Web Scraping Shell 与 extract 命令(IPython、markdownify,且隐含 fetchers) pip install "scrapling[all]" # 以上全部安装任一扩展后,仍需确保已执行scrapling install完成浏览器依赖安装。fetchers扩展的核心依赖包括 click、curl_cffi(TLS 指纹模拟)、playwright、patchright(隐身 Chromium)、browserforge 与 apify-fingerprint-datapoints(指纹生成)、protego(robots.txt 解析)等。
Docker 部署
每个版本都会自动构建并推送带全部扩展与浏览器的 Docker 镜像:
docker pull pyd4vinci/scrapling # 或从 GitHub 容器仓库拉取 docker pull ghcr.io/d4vinci/scrapling:latest仓库根目录提供了 Dockerfile 供查阅构建细节。
许可证与合规说明
- 本项目采用BSD-3-Clause许可(见 LICENSE);
- 代码包含基于 Parsel(BSD 许可)修改而来的组件,主要用于 translator 子模块;
- 官方免责声明:该库仅供教育与研究目的使用,使用者需遵守当地与国际的数据抓取和隐私法律,并尊重目标网站的服务条款与 robots.txt 文件。
如需参与开发,请阅读 CONTRIBUTING.md;各功能的完整文档分布在 docs/fetching、docs/parsing、docs/spiders、docs/cli 与 docs/ai 等目录中,可配合本文的源码引用继续深入。
【免费下载链接】Scrapling🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!项目地址: https://gitcode.com/GitHub_Trending/sc/Scrapling
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考