news 2026/9/7 18:57:45

Scrapling 完全指南:从自适应解析到多会话爬虫框架的实战手册

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Scrapling 完全指南:从自适应解析到多会话爬虫框架的实战手册

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映射表实现延迟导入:只有当你真正访问FetcherDynamicFetcherStealthyFetcher等类时才加载对应模块(requests.pychrome.pystealth_chrome.py),这正是主文档强调的“基础安装只带解析器引擎、不带 Fetcher 依赖也能导入包本身”的底层原因。

Fetcher 家族与多类型抓取

三类请求能力的对比

底层机制适用场景
Fetcher/AsyncFetcherHTTP 客户端,可模拟浏览器 TLS 指纹、自定义请求头、HTTP/3普通静态页面,速度优先
DynamicFetcher/DynamicSessionPlaywright 驱动的 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对象可以直接调用cssxpath等选择器方法。

隐身模式(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 与异步会话类(AsyncFetcherAsyncDynamicSessionAsyncStealthySession)完整支持 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,尊重DisallowCrawl-delayRequest-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 包入口中,以上能力一一对应导出:SpiderRequestCrawlResultSchedulerCrawlerEngineSessionManagerLinkExtractor以及全部模板类。

基础 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_requests4全局并发上限
concurrent_requests_per_domain0按域并发限制,0 表示不额外限制
download_delay0.0请求间下载延迟(秒)
max_blocked_retries3被封请求的最大重试次数
robots_txt_obeyFalse是否遵守 robots.txt
development_modeFalse是否启用响应缓存回放
autothrottle_enabledFalse是否启用自动限速
autothrottle_start_delay5.0AutoThrottle 初始延迟
autothrottle_max_delay60.0AutoThrottle 延迟上限

同时源码中定义了封禁状态码集合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是一个命令组,除文档中展示的getfetch(DynamicFetcher)、stealthy-fetch(StealthyFetcher)外,还提供postputdelete等完整的 HTTP 动词子命令,并共享一组 HTTP 选项(--impersonate等)与浏览器选项(--no-headless--solve-cloudflare等)。此外 CLI 还提供scrapling install(安装浏览器依赖)、scrapling shellscrapling-mcp(MCP 服务器)等顶层命令。

性能基准

主文档给出的基准数据(100 次运行均值,方法论见 benchmarks.py):

文本提取速度(5000 个嵌套元素)

#耗时 (ms)相对 Scrapling
1Scrapling1.991.0x
2Parsel/Scrapy2.061.035x
3Raw Lxml2.561.286x
4PyQuery23.98~12x
5Selectolax197.02~99x
6MechanicalSoup1545.15~776.5x
7BS4 + Lxml1562.1~785.0x
8BS4 + html5lib3412.73~1714.9x

元素相似度搜索与文本搜索

耗时 (ms)相对 Scrapling
Scrapling2.31.0x
AutoScraper12.585.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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 18:57:28

光伏电站监控大屏设计与实践:打破信息孤岛,实现一屏运维

1. 光伏电站碰上"信息孤岛"&#xff1a;为什么我们最终决定上大屏1.1 上百台逆变器分布在几公里山头上&#xff0c;靠什么掌握全局我做光伏电站运营这些年&#xff0c;感受最深的一件事是&#xff1a;电站越大&#xff0c;越容易"看不见"。组件铺在山坡上、…

作者头像 李华
网站建设 2026/9/7 18:56:41

Zynq xc7z020与复旦微FM25F32 QSPI Flash烧写配置实战指南

简介&#xff1a;针对Xilinx公司Zynq-7000系列现场可编程门阵列在国产化替代中&#xff0c;开发环境无法识别复旦微电子Nor型QSPI闪存FM25F32的问题&#xff0c;这套基于XC7Z020器件的验证工程给出了完整解决思路。作者利用自编烧写测试程序&#xff0c;绕过开发套件自带工具的…

作者头像 李华
网站建设 2026/9/7 18:56:23

Hive与TimescaleDB整合实践:时序数据的冷热分离与同步链路设计

1. 为什么时序数据场景不能只用一种数据库1.1 我最初遇到的真实困境去年我做了一个典型的工业物联网数据平台&#xff0c;设备端每5秒上报一次运行状态&#xff0c;包括温度、振动、电流、电压、产量计数等指标。单台设备一天产生的记录量大概在1.7万条左右&#xff0c;几百台设…

作者头像 李华
网站建设 2026/9/7 18:55:30

基于Spring Boot的小区业主物业公共收益管理系统实战解析

在Java后端这个方向里&#xff0c;毕设项目的选题其实挺有讲究。做得太简单&#xff0c;答辩的时候讲不出东西&#xff1b;做得太复杂&#xff0c;自己又扛不住开发周期。今天聊的这个“基于Spring Boot的小区业主物业公共收益管理系统”&#xff0c;属于最典型的中等体量实战项…

作者头像 李华