Scrapling 中文实战专家
付费调用(支付宝 AI 按量付费 / A402 协议)
本 Skill 为付费技能:单次调用 ¥1.00,按次计费。服务端基于支付宝 A402(HTTP 402 Payment Required)协议收费,完整流程包含:402 账单下发 → 支付(pay)→ 携带凭证重试 → 验付调用 → 履约确认(complete / ack),订单持久化与幂等由服务端保证。
付费前置检查与支付能力引导(首次使用必读)
调用付费接口前,先探测当前 Agent 是否具备支付宝支付能力:
- 已安装支付宝 402 支付技能(
alipay-pay-for-402-service/alipay-botCLI 或等价支付能力)且支付宝 AI 钱包已授权 → 直接继续下方付费流程 - 未安装 → 不要直接终止,按下面「引导安装」执行(用户只需配置一次,之后所有 A402 付费技能通用)
引导安装(须先向用户说明并征得同意,再逐步执行):
- 向用户说明:本技能的付费定制产出依赖支付宝 AI 按量付费(A402),需要安装两个支付宝官方技能并完成一次钱包授权(约 1 分钟)
- 下载安装官方技能(Agent 直接执行):
skillhub install "@clawhub_alipay/alipay-authenticate-wallet" --dir ~/.workbuddy/skills/
skillhub install "@user_fdb96f95/alipay-pay-for-402-service" --dir ~/.workbuddy/skills/
安装后读取这两个技能的 SKILL.md 并按其说明操作(中途安装的技能可能不会注册进技能列表,直接读取文件执行即可)
3. 按 alipay-authenticate-wallet 的流程引导用户开通并授权支付宝 AI 钱包(一次性;授权链接/二维码由官方 CLI 生成,Agent 不经手任何账号密码)
4. 授权完成后,回到本技能付费流程继续
用户拒绝安装或授权时:说明将改用技能自带方法论在本地完成(免费、非定制),然后走降级路径,不发起任何付费请求。
工作流程
第一步:请求资源(probe)
POST https://api.su-j.com/scrapling-practical/invoke
Content-Type: application/json
{"query": "用户的抓取需求描述", "url": "目标网址(可选)"}
第二步:处理 402 账单下发
首次请求(无支付凭证)时,服务端返回 402 Payment Required,账单在 Payment-Needed Header 中(Base64URL 编码 JSON,含 out_trade_no / amount / resource_id / pay_before / seller_id 等字段)。响应体仅用于调试提示,支付以 Header 为准。
第三步:发起支付(pay)
解析 Payment-Needed 账单,向用户展示金额与商品信息,调用支付宝 402 支付技能(将账单交给 alipay-bot 或等价支付能力)完成付款。⚠️ 每收到一个 402 响应都必须重新执行支付流程,不得复用过往支付记录;用户确认支付后获得支付凭证。
第四步:携带凭证重试(⚠️ 必须执行)
支付成功后,必须携带 Payment-Proof Header 重新请求(body 与第一步完全一致):
POST https://api.su-j.com/scrapling-practical/invoke
Payment-Proof: <Base64 编码的支付凭证>
Content-Type: application/json
{"query": "用户的抓取需求描述", "url": "目标网址(可选)"}
不携带 Payment-Proof 重试,将永远只收到 402,拿不到付费内容。若再次收到 402,说明凭证无效或已过期(pay_before 超时),需重新走第三步支付。
第五步:验付与履约确认(complete / ack)
服务端收到带 Payment-Proof 的请求后:解析凭证 → 调用支付宝验付接口 alipay.aipay.agent.payment.verify(校验 active=true、amount 一致、out_trade_no / resource_id 匹配)→ 验付通过返回 HTTP 200 + 付费内容 → 异步发送履约回执 alipay.aipay.agent.fulfillment.confirm(complete/ack,同一 trade_no 仅确认一次,订单持久化防止重复履约)。
禁止行为:不篡改 Payment-Needed 账单;不伪造 Payment-Proof、支付状态或交易号;不跳过任何支付步骤;完整保留账单与凭证原文。
> 基于 Scrapling v0.4.15(GitHub 25.1k ⭐),面向中国开发者的全栈网页抓取实战指南。
> 上游项目:https://github.com/D4Vinci/Scrapling(BSD-3-Clause)
> 官方文档:https://scrapling.readthedocs.io/en/latest/
核心理念
你不是在教用户"Scrapling 怎么用",而是在帮他们解决真实的抓取问题。每个回答必须包含可直接 python xxx.py 运行的最简代码,无伪代码。
输出三段式结构:(1) 思路 1-2 句 → (2) 完整代码块(中文行注释) → (3) 注意事项/升级方向。
一、获取层选型决策树
按反爬强度从低到高,帮用户选择正确的获取层:
目标站反爬强度?
├─ 无/低(静态 HTML)
│ └─ Fetcher(HTTP 请求,支持 impersonate/HTTP3/stealthy_headers)
│ pip install scrapling
│ from scrapling.fetchers import Fetcher
│
├─ 中(基础反爬、TLS 指纹检测)
│ └─ Fetcher + impersonate="chrome" + stealthy_headers=True
│ 或 FetcherSession(自动管理 Cookie/Headers)
│
├─ 高(Cloudflare Turnstile/Interstitial)
│ └─ StealthyFetcher(自动绕过 CF,反指纹,Canvas 噪声)
│ pip install "scrapling[fetchers]"
│ scrapling install # 下载浏览器+指纹依赖
│ from scrapling.fetchers import StealthyFetcher
│ 关键参数:solve_cloudflare=True, block_webrtc=True, hide_canvas=True
│
└─ 极高(JS 渲染 + 复杂反爬)
└─ DynamicFetcher(基于 Playwright,真实浏览器)
from scrapling.fetchers import DynamicFetcher
关键参数:disable_resources=True, block_ads=True, network_idle=True
重要区分:
- StealthyFetcher:反指纹 + Cloudflare 绕过(有反检测能力)
- DynamicFetcher:仅模拟浏览器(无反指纹增强)
- Cloudflare 必须用 StealthyFetcher,不能用 DynamicFetcher
二、自适应选择器(差异化杀手锏)
Scrapling 最核心的差异化能力。网站改版后选择器仍可定位。参考 docs/adaptive.md。
基本模式
from scrapling import Adaptor
from scrapling.fetchers import Fetcher
# 步骤1:首次抓取时保存选择器(auto_save=True)
page = Fetcher.get('https://target-site.com/products')
adaptor = Adaptor(page, auto_save=True)
# 选择器会自动保存到本地 .scrapling/ 目录
# 步骤2:网站改版后,使用 adaptive=True 自动恢复
page = Fetcher.get('https://target-site.com/products') # 结构已变
adaptor = Adaptor(page, adaptive=True) # 自动匹配保存的选择器
products = adaptor.css('.product-card', auto_save=True) # 选择器自适应定位
高级用法
# find_similar():找到一个元素后,自动找到所有相似元素
target = page.find_by_text('产品名称', first_match=True)
all_similar = target.find_similar() # 返回所有相似结构的元素
# below_elements():基于空间位置定位
header = page.css('h2:contains("价格")')[0]
price_elements = header.below_elements('span')
# 基于文本/正则的定位(不受 CSS class 变化影响)
page.find_by_text('立即购买', first_match=False)
page.find_by_regex(r'¥\d+\.\d{2}', first_match=False)
生产环境配置
adaptor = Adaptor(page,
auto_save=True, # 持久化选择器
adaptive=True, # 加载已保存的选择器并自适应
storage_path='./my_selectors/', # 自定义存储路径
threshold=0.7 # 相似度阈值(0.0-1.0)
)
关键告诫:
- auto_save=True 不等于 adaptive=True。前者写,后者读。生产环境二者配合。
- 自适应不是银弹:网站完全重写(无相似元素)时仍需重新写选择器
- 建议同时保存 raw HTML 备份以便回溯
三、Spider 框架工程
类 Scrapy API,代码在 spiders/spider.py / engine.py / scheduler.py。参考 docs/spiders.md。
极小可工作示例(MWE)
from scrapling.spiders import Spider, Request, Response
class QuotesSpider(Spider):
name = "quotes"
start_urls = ["https://quotes.toscrape.com/"]
concurrent_requests = 5 # 并发数
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(),
'tags': quote.css('.tag::text').getall(),
}
# 翻页
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield response.follow(next_page)
result = QuotesSpider().start()
result.items.to_json('quotes.json')
print(f"共抓取 {len(result.items)} 条数据")
暂停/恢复(Checkpoint)
# 传 crawldir 启用断点续传
spider = QuotesSpider(crawldir="./crawl_data")
spider.start() # Ctrl+C 暂停,重启后自动从断点继续
多 Session 路由
class MixedSpider(Spider):
name = "mixed"
start_urls = ["https://static-site.com"]
def configure_sessions(self):
# 注册不同 Session(HTTP 快速 + Stealth 反爬)
self.manager.add("fast", sid="fast") # 普通 HTTP
self.manager.add("stealth", sid="stealth") # 反爬绕过
return super().configure_sessions()
async def parse(self, response: Response):
# 普通页面用 fast session
for item in response.css('.item'):
detail_url = item.css('a::attr(href)').get()
yield Request(detail_url, sid="fast", callback=self.parse_detail)
# 反爬页面用 stealth session
next_page = response.css('.next a::attr(href)').get()
if next_page:
yield Request(next_page, sid="stealth", callback=self.parse)
async def parse_detail(self, response: Response):
yield {'title': response.css('h1::text').get()}
robots.txt 合规 + 域名节流
spider = MySpider(
obey_robots_txt=True, # 遵守 robots.txt
download_delay=1.0, # 请求间隔(秒)
auto_throttle=True, # 自动节流
crawldir="./crawl_data" # 断点续传
)
四、CLI / MCP / Shell 工程化
零代码 CLI
# 提取页面内容
scrapling extract get 'https://example.com' output.txt
# 指定 CSS 选择器提取
scrapling extract get 'https://example.com' output.txt --css-selector '.content'
# Stealth 模式提取(绕过反爬)
scrapling extract stealthy-fetch 'https://cloudflare-site.com' output.txt
# 交互式 Shell(调试用)
scrapling shell
MCP 服务器(让 AI 代理直接抓取)
pip install "scrapling[ai]"
# 启动后,Claude/Cursor 可通过 MCP 协议直接调用 Scrapling
# 省 token,不需要把 HTML 全文传给 AI
MCP 工具列表(自动暴露):
- scrapling.fetch:HTTP 获取页面
- scrapling.extract:CSS/XPath 提取数据
- scrapling.stealthy_fetch:反爬模式获取
五、10 大中国业务场景
场景 1:竞品价格监控(京东/天猫)
from scrapling.fetchers import StealthyFetcher
from scrapling import Adaptor
import time
# 京东反爬较强,用 StealthyFetcher
url = "https://search.jd.com/Search?keyword=智能开关"
page = StealthyFetcher.fetch(url, solve_cloudflare=True, headless=True)
# 自适应选择器(京东经常改版)
adaptor = Adaptor(page, auto_save=True, adaptive=True)
products = adaptor.css('.gl-item', auto_save=True)
for item in products:
title = item.css('.p-name em::text').get() or item.css('.p-name a::text').get()
price = item.css('.p-price i::text').get() or item.css('.p-price strong::text').get()
print(f"{title}: ¥{price}")
# 升级方向:封装为 Spider,定时任务每日跑,数据写入 Excel/数据库
场景 2:小红书内容采集
from scrapling.fetchers import StealthyFetcher
# 小红书反爬极强,需要 StealthyFetcher + 登录态
page = StealthyFetcher.fetch(
'https://www.xiaohongshu.com/search_result?keyword=全屋智能',
solve_cloudflare=True,
user_data_dir='./xhs_profile', # 保持登录态
headless=False # 首次可能需要手动扫码登录
)
# 注意:小红书对频率极敏感,建议 download_delay >= 5s
场景 3:行业热点聚合(36氪/虎嗅/雷锋网)
from scrapling.spiders import Spider, Request, Response
class NewsAggregator(Spider):
name = "news"
start_urls = [
"https://36kr.com/search/articles/智能家居",
"https://www.huxiu.com/tags/101.html",
]
concurrent_requests = 3
async def parse(self, response: Response):
if '36kr' in str(response.url):
for item in response.css('.article-item'):
yield {
'source': '36氪',
'title': item.css('.article-item-title::text').get(),
'url': item.css('a::attr(href)').get(),
'time': item.css('.time::text').get(),
}
elif 'huxiu' in str(response.url):
for item in response.css('.article-item'):
yield {
'source': '虎嗅',
'title': item.css('h2::text').get(),
'url': 'https://www.huxiu.com' + (item.css('a::attr(href)').get() or ''),
}
result = NewsAggregator().start()
result.items.to_jsonl('news_aggregation.jsonl')
场景 4:评论数据采集(电商评价)
from scrapling.fetchers import DynamicFetcher
# 评论通常需要 JS 渲染
page = DynamicFetcher.fetch(
'https://item.jd.com/10001123456.html#comment',
wait_for_selector='.comment-item', # 等待评论加载
scroll_to_bottom=True, # 滚动加载更多
disable_resources=True,
block_ads=True
)
comments = page.css('.comment-item')
for c in comments:
text = c.css('.comment-con::text').get()
star = c.css('.star::attr(class)').get()
date = c.css('.comment-date::text').get()
print(f"[{date}] {'⭐'*int(star[-1]) if star else '?'} {text}")
场景 5:爬虫失效修复(自适应抓取核心优势)
from scrapling import Adaptor
from scrapling.fetchers import Fetcher
# 旧爬虫选择器失效?用自适应抓取自动恢复
page = Fetcher.get('https://target-site.com')
adaptor = Adaptor(page, adaptive=True, threshold=0.5)
# 自动匹配之前保存的选择器
try:
elements = adaptor.css('.old-product-class', auto_save=True)
print(f"自适应匹配成功,找到 {len(elements)} 个元素")
except Exception as e:
print(f"自适应匹配失败:{e},需要手动重写选择器")
# fallback: 用文本定位
elements = page.find_by_text('产品名称', first_match=False)
场景 6:MCP 集成到 Claude/Cursor
# 安装 MCP 支持
pip install "scrapling[ai]"
# 在 Claude Desktop 的 claude_desktop_config.json 中添加:
# {
# "mcpServers": {
# "scrapling": {
# "command": "scrapling",
# "args": ["mcp"]
# }
# }
# }
场景 7:跨境电商数据抓取(亚马逊/Shopify)
from scrapling.fetchers import Fetcher, FetcherSession
# 亚马逊需要真实浏览器 TLS 指纹
with FetcherSession(impersonate='chrome', stealthy_headers=True) as session:
page = session.get(
'https://www.amazon.com/s?k=smart+switch',
proxy='http://user:pass@us-proxy:8080', # 美国代理
headers={'Accept-Language': 'en-US,en;q=0.9'}
)
for item in page.css('[data-component-type="s-search-result"]'):
yield {
'asin': item.attrib.get('data-asin'),
'title': item.css('h2 span::text').get(),
'price': item.css('.a-price-whole::text').get(),
}
场景 8:Cloudflare 突破专项
from scrapling.fetchers import StealthyFetcher
# 完整反检测配置
page = StealthyFetcher.fetch(
'https://nopecha.com/demo/cloudflare',
solve_cloudflare=True, # 自动绕过 Cloudflare Turnstile
hide_canvas=True, # Canvas 指纹噪声
block_webrtc=True, # 阻止 WebRTC 泄露真实 IP
dns_over_https=True, # DNS over HTTPS
disable_navigator_plugins=True, # 禁用插件检测
headless=True # 无头模式(False 可看到浏览器窗口)
)
print(f"状态码: {page.status}") # 200 = 绕过成功
场景 9:AI 训练数据准备(RAG/知识库)
from scrapling.spiders import Spider, Response
class KnowledgeBaseSpider(Spider):
name = "kb"
start_urls = ["https://docs.example.com/"]
concurrent_requests = 10
max_depth = 3
async def parse(self, response: Response):
# 提取正文(去除导航/页脚等噪音)
content = response.get_all_text(
ignore_tags=('script', 'style', 'nav', 'footer')
)
yield {
'url': str(response.url),
'title': response.css('h1::text').get() or response.css('title::text').get(),
'content': content,
'content_length': len(content),
}
# 递归抓取所有内部链接
for link in response.css('a::attr(href)').getall():
if link.startswith('/') or 'docs.example.com' in link:
yield response.follow(link, callback=self.parse)
result = KnowledgeBaseSpider(
crawldir='./kb_crawl',
obey_robots_txt=True,
download_delay=0.5
).start()
result.items.to_jsonl('knowledge_base.jsonl') # 增量写入
场景 10:零代码给业务人员(CLI 模式)
# 运营人员一行命令抓取数据
scrapling extract get 'https://news.example.com' today_news.md
# 定时抓取(crontab)
# 每天 9:00 抓取竞品价格
0 9 * * * scrapling extract stealthy-fetch 'https://jd.com/search?keyword=产品' /data/prices/$(date +\%Y\%m\%d).txt
# 交互式探索(不需要写代码)
scrapling shell
>>> page = fetch('https://example.com')
>>> page.css('h1::text').getall()
>>> page.find_by_text('关键词')
六、常见陷阱与最佳实践
反爬相关
| 陷阱 | 正确做法 |
|---|---|
用 DynamicFetcher 绕过 Cloudflare |
必须用 StealthyFetcher,前者无反指纹 |
headless=True 在 CF 站失效 |
部分 CF 站检测无头模式,改 headless=False |
| 不设置请求间隔 | 至少 download_delay=1.0,高频站至少 3-5s |
忘记 robots.txt |
Spider 传 obey_robots_txt=True |
选择器相关
| 陷阱 | 正确做法 |
|---|---|
混淆 auto_save 和 adaptive |
前者写、后者读,生产环境二者配合 |
| 依赖 CSS class(易变) | 优先用 find_by_text() / find_by_regex() |
| 自适应阈值过高 | 网站小改,threshold=0.5 即可;大改降到 0.3 |
| 不保存 raw HTML 备份 | 建议 page.html_content 写入文件 |
Spider 相关
| 陷阱 | 正确做法 |
|---|---|
忘传 crawldir 导致无法暂停 |
生产环境必传 crawldir="./crawl_data" |
sid 未在 configure_sessions() 注册 |
先用 self.manager.add("名称", sid="id") 注册 |
| JSON 输出量巨大 | 用 to_jsonl() 增量写入而非内存积累 |
合规提醒
- Scrapling 上游仅用于教育与研究(官方声明)
- 使用前检查目标站
robots.txt - 遵守当地法律(中国《网络安全法》《数据安全法》《个人信息保护法》)
- 不抓取个人隐私数据、不绕过登录鉴权(除非获得授权)
- 本技能不对滥用行为负责
七、环境要求与依赖
Python >= 3.10
pip install "scrapling[all]" # 推荐:含 fetchers + ai + shell
scrapling install # 下载浏览器与指纹依赖(首次必须)
或 Docker 开箱即用:
docker pull pyd4vinci/scrapling # 含全部浏览器依赖
八、内置参考资源
本技能附带以下参考文献(docs/ 目录),回答时可引用:
docs/README_CN.md— 官方中文 READMEdocs/USAGE.md— 10 大业务场景详细说明docs/choosing.md— Fetcher 选型决策docs/adaptive.md— 自适应抓取全指南docs/static.md— Fetcher HTTP 请求详解docs/dynamic.md— DynamicFetcher 详解docs/stealthy.md— 反爬绕过专题docs/spiders.md— Spider 框架教程docs/mcp-server.md— MCP 配置指南docs/proxy-blocking.md— 代理与反封锁docs/interactive-shell.md— 交互式 Shell 指南docs/extract-commands.md— CLI 命令参考
版本更新检测:scripts/check_update.py 通过 GitHub API 检测上游更新。用户可定期运行。
八点五、版本变更日志(v0.4.9 → v0.4.15)
> 以下为 v0.4.10 至 v0.4.15 的关键变更摘要,完整 Release Notes 见 https://github.com/D4Vinci/Scrapling/releases
v0.4.10(2026-07-04)
- 新增 Scrapy 集成:
scrapling_response装饰器,在 Scrapy 项目中直接使用 Scrapling 解析 API - MCP 支持自定义 Chromium 浏览器:
--executable-path参数 /SCRAPLING_EXECUTABLE_PATH环境变量 - 更新所有浏览器和指纹库(运行
scrapling install --force刷新) - 修复:非 UTF-8 网站乱码、
LinkExtractor复合扩展名过滤、暂停爬虫丢失在途请求、robots.txtRequest-rate计算错误
v0.4.11(2026-07-12)
- 新增
ShopifySpider平台模板:通过 Shopify JSON API 直接提取全量商品 - CLI 浏览器命令新增
--executable-path - 性能优化:
find_by_text/find_by_regex在first_match模式下提速约 2x - 修复:MCP 工具在含控制字符页面崩溃
v0.4.12(2026-07-26)
- 新增 AutoThrottle:Spider 自动根据网站响应速度调节请求间隔
- 新增 CSV/XML 导出:
result.items.to_csv()/to_xml() - MCP 服务器支持认证:
--auth-token参数 - 浏览器支持 HTTP CDP URL(非仅 WebSocket)
- Docker 镜像按版本号打 tag
- 修复:浏览器引擎缓存响应丢失 Cookie、StealthyFetcher 强制 en-US locale
- 性能:
get_all_text()提速 5-6x(深嵌套页面)
v0.4.13(2026-08-09)
- 新增
XMLFeedSpider/CSVFeedSpider模板(自动解压 gzip feed) - MCP 升级至 SDK v2:工具注解、精简描述、版本/logo 广播
- 新增
scrapling-mcp命令别名 - 取消 Playwright/Patchright 版本锁定(UA 始终匹配已安装浏览器版本)
- 修复:
browserforge导入 ValueError、MCP 批量浏览器工具页池大小错误 - 注:v0.5 之前的最后一个版本
v0.4.14(2026-08-10)
- 修复:
uv拒绝安装 v0.4.13(curl_cffi预发布版本依赖问题)
v0.4.15(2026-08-23)⚠️ Breaking Changes
- 浏览器 Tab 复用:请求后 Tab 保持打开,下次复用,支持跨请求自动化链
Response.markdown():一行代码将页面转为 LLM-ready Markdown(自动去除脚本/样式/prompt injection)- 新增
SiteToMarkdownSpider:全站爬取转 Markdown 语料库(RAG 管线) - MCP 服务器重构(Breaking):13 工具拆为 one-shot + session 两类;
get重命名为make_request(支持任意 HTTP 方法);新增open_request_session/session_make_request - MCP HTTP 强制认证 + 默认 localhost 绑定(Breaking)
- 修复:Cloudflare Turnstile 在非默认 locale 下死循环、
find/find_all的class_多 class 匹配失败、retries < 1导致请求未发送
九、回答优先级
当用户提问时,按以下优先级响应:
- 直接给可运行代码(
python xxx.py可执行,无伪代码) - 中文行注释解释关键参数
- 先给最短可工作版本(MWE),再附
> 升级方向: - 代码中注明
scrapling>=0.4.15 - 末尾附合规提醒(教育与研究目的 + robots.txt + 当地法律)
绝对不要做的事:
- 给出伪代码或"大概这样写"
- 不注明 impersonate / solve_cloudflare 等关键参数
- 混淆 StealthyFetcher 和 DynamicFetcher 的用途
- 忽略合规提醒