Scrapling MCP Server API 参考:把网页抓取能力接入 AI Agent 的十个工具与完整参数解析
本文以 Scrapling 仓库中的 MCP Server API 参考 为主体,逐字段解析其响应模型、会话模型与 ScraplingMCPServer 类的全部抓取工具,并结合 scrapling/core/ai.py 的源码实现、CLI 命令定义 与 测试用例 说明各参数的默认值、取值范围与底层行为。读完本文,你可以直接把 Scrapling 的静态请求、动态浏览器、隐身反检测抓取能力以标准 Model Context Protocol(MCP)服务接入任意支持 MCP 的 AI 客户端,并掌握 HTTP 传输、认证令牌与 DNS 重绑定防护等生产级配置。
启动方式:CLI 命令与服务类两种入口
API 参考文档给出的启动方式有两种,二者等价,底层都构造 ScraplingMCPServer 实例并调用 serve()。
方式一:CLI 命令
scrapling mcp
scrapling/cli.py 中定义了 mcp 命令,完整参数如下:
| 参数 | 类型/默认值 | 作用 |
|---|---|---|
--http |
flag,默认 False |
使用 Streamable HTTP 传输,否则为 stdio |
--host |
字符串,默认 0.0.0.0 |
HTTP 模式下监听的主机 |
--port |
整数,默认 8000 |
HTTP 模式下的端口 |
--executable-path |
字符串,默认 None |
浏览器工具使用的自定义 Chromium 兼容可执行文件路径 |
--auth-token |
字符串,默认 None |
要求客户端携带 Authorization: Bearer <token>(仅 streamable-http 生效) |
--allowed-host |
字符串,可重复 | 启用 DNS 重绑定防护,仅接受该主机名(形如 mcp.example.com:8000) |
命令实现只有两行核心逻辑:
def mcp(http, host, port, executable_path, auth_token, allowed_host):
from scrapling.core.ai import ScraplingMCPServer
server = ScraplingMCPServer(executable_path=executable_path, auth_token=auth_token)
server.serve(http, host, port, allowed_hosts=allowed_host)
方式二:直接导入服务类
from scrapling.core.ai import ScraplingMCPServer
server = ScraplingMCPServer()
server.serve(http=False, host="0.0.0.0", port=8000)
若浏览器类工具需要指定自定义 Chromium 兼容浏览器可执行文件,构造时传入 executable_path:
server = ScraplingMCPServer(executable_path="/path/to/chromium")
从 scrapling/core/ai.py#L143-L159 的构造函数看,executable_path 与 auth_token 都有环境变量的回退逻辑:
executable_path省略时读取SCRAPLING_EXECUTABLE_PATH;auth_token省略时读取SCRAPLING_MCP_AUTH_TOKEN;- 之后每次工具调用仍可用单请求级的
executable_path参数覆盖服务器级默认值(见_resolve_executable_path,scrapling/core/ai.py#L157-L159)。
此外,pyproject.toml 中注册了两个控制台脚本:scrapling(主 CLI)与 scrapling-mcp(直接指向 scrapling.cli:mcp),因此 MCP 客户端配置中可以直接使用 scrapling-mcp 单命令形式,这是较新版本为了方便注册表集成而提供的快捷方式,旧版本需要用 scrapling mcp。仓库根目录的 server.json 是面向 MCP 注册表的服务器清单,声明了 PyPI(scrapling,stdio 传输,固定参数 mcp)与 OCI(ghcr.io/d4vinci/scrapling)两种分发包形式。
响应模型:所有抓取工具的统一输出结构
API 参考文档指出,所有 MCP 服务器工具都返回同一标准响应结构。对应实现是 scrapling/core/ai.py#L61-L66 中的 Pydantic 模型:
class ResponseModel(BaseModel):
"""Request's response information structure."""
status: int = Field(description="The status code returned by the website.")
content: list[str] = Field(description="The content as Markdown/HTML or the text content of the page.")
url: str = Field(description="The URL given by the user that resulted in this response.")
三个字段含义如下:
| 字段 | 类型 | 说明 |
|---|---|---|
status |
int |
网站返回的 HTTP 状态码 |
content |
list[str] |
页面内容,格式由 extraction_type 决定(Markdown/HTML/纯文本) |
url |
str |
产生该响应的用户给定 URL |
值得注意的两个源码细节:
content是列表而非字符串。_translate_response(scrapling/core/ai.py#L98-L114)会先对每个内容块执行_CONTROL_CHARS_PATTERN.sub("", chunk)去除控制字符,再调用Convertor._extract_content完成 CSS 选择器筛选与格式转换。也就是说,AI 拿到的内容已经过清洗。- 转换发生在响应层而非请求层:所有抓取工具(
get、fetch、stealthy_fetch及其 bulk 版本)底层都拿到完整的 ScraplingResponse对象后,统一经_translate_response(page, extraction_type, css_selector, main_content_only)转成ResponseModel,因此四个工具的输出契约完全一致。
会话模型:持久化浏览器会话的数据结构
API 参考文档将会话管理拆成三个模型类,全部定义在 scrapling/core/ai.py#L69-L88:
class SessionInfo(BaseModel):
"""Information about an open browser session."""
session_id: str = Field(description="The unique identifier of the session.")
session_type: SessionType = Field(description="The type of the session: 'dynamic' or 'stealthy'.")
created_at: str = Field(description="ISO timestamp of when the session was created.")
is_alive: bool = Field(description="Whether the session is still alive and usable.")
SessionType 是一个 Literal["dynamic", "stealthy"](scrapling/core/ai.py#L43),即会话只有两种类型:
dynamic:标准 Playwright 浏览器,适合 JS 渲染、中低防护网站;stealthy:带指纹伪装的隐身浏览器,可解决 Cloudflare Turnstile/Interstitial 等高防护场景。
在此基础上的两个响应模型:
| 模型 | 继承 | 附加字段 | 用途 |
|---|---|---|---|
SessionCreatedModel |
SessionInfo |
message: str(确认消息) |
open_session 成功后返回 |
SessionClosedModel |
无 | session_id: str、message: str |
close_session 成功后返回 |
服务器内部用 @dataclass _SessionEntry 记录每个打开的会话(scrapling/core/ai.py#L91-L95):真实会话对象(AsyncDynamicSession 或 AsyncStealthySession)、类型和创建时间(UTC ISO 时间戳)。整个服务器实例通过 self._sessions: Dict[str, _SessionEntry] 维护全部会话,因此会话生命周期与服务器进程绑定——服务器重启后旧会话 ID 全部失效。
十个 MCP 工具全解析
API 参考文档开篇提到 MCP Server 提供抓取工具,而从源码的 _build_server 注册段(scrapling/core/ai.py#L921-L1018)与 tests/ai/test_ai_mcp.py 中断言 len(tools) == 10 的用例看,当前版本共注册 10 个工具:get、bulk_get、fetch、bulk_fetch、stealthy_fetch、bulk_stealthy_fetch、open_session、close_session、list_sessions、screenshot。前六个均为只读抓取(ToolAnnotations(read_only_hint=True, open_world_hint=True)),会话三件套标记为非只读,list_sessions 标记为只读且 open_world_hint=False。
get / bulk_get:静态 HTTP 请求
get 是单 URL 版,源码中它直接委托给 bulk_get(urls=[url]) 并取第一个结果(scrapling/core/ai.py#L427-L448),因此两者参数完全一致。bulk_get 在一个 FetcherSession 内用 asyncio.gather 并发请求全部 URL。关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
impersonate |
"chrome" |
伪装的浏览器指纹版本,默认最新 Chrome(TLS 指纹、HTTP 头等一致化) |
extraction_type |
"markdown" |
提取格式:"markdown"、"html"、"text" |
css_selector |
None |
CSS 选择器,先于 AI 精确截取目标元素 |
main_content_only |
True |
只取 <body> 内的主内容 |
timeout |
30 秒 |
请求超时 |
follow_redirects |
"safe" |
跟随重定向但拒绝指向内网/私有 IP 的重定向(SSRF 防护);传 True 可解除限制 |
max_redirects |
30 |
-1 表示不限 |
retries / retry_delay |
3 / 1 |
重试次数与间隔秒数 |
proxy / proxy_auth / auth |
None |
代理 URL、代理 Basic 认证、站点 Basic 认证(后两者为含 username/password 的字典) |
verify |
True |
是否校验 HTTPS 证书 |
http3 |
False |
是否启用 HTTP/3(与 impersonate 同用可能有问题) |
stealthy_headers |
True |
生成真实浏览器请求头并附带 Google referer |
bulk_get 在发请求前会先经 _normalize_credentials 校验 proxy_auth/auth 字典必须同时含 username 和 password,缺键即抛 ValueError(scrapling/core/ai.py#L117-L128)。
fetch / bulk_fetch:动态浏览器抓取
fetch 同样委托 bulk_fetch(urls=[url])。无 session_id 时,bulk_fetch 会临时创建一个 AsyncDynamicSession(强制 block_ads=True),按 URL 数量计算页面池大小后并发抓取,取完即关闭;传 session_id 时则复用 open_session 打开的持久会话(scrapling/core/ai.py#L657-L700)。关键参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
headless |
True |
无头模式;False 时浏览器可见(调试/观察反爬挑战时有用) |
timeout |
30000 毫秒 |
页面全部操作与等待的超时 |
wait |
0 毫秒 |
页面就绪后额外等待时间 |
wait_selector / wait_selector_state |
None / "attached" |
等待指定 CSS 选择器到达指定状态 |
network_idle |
False |
等待网络空闲至少 500ms,适合 SPA |
proxy |
None |
字符串或仅含 server/username/password 键的字典 |
useragent / extra_headers / cookies |
None |
UA 覆盖(否则自动生成与浏览器一致的 UA)、附加请求头、Playwright 格式 Cookie |
locale / timezone_id |
系统默认 | 影响 navigator.language、Accept-Language 与日期/数字格式 |
real_chrome |
False |
使用本机已安装的 Chrome |
cdp_url |
None |
不启动新浏览器,改为通过 CDP 连接已运行的浏览器(本机、他机或托管浏览器服务均可) |
executable_path |
None |
单请求级自定义 Chromium 可执行文件,覆盖服务器默认 |
disable_resources |
False |
丢弃 font、image、media、beacon、object、imageset、texttrack、websocket、csp_report、stylesheet 类请求提速 |
google_search |
True |
设置 Google referer 头(优先级高于 extra_headers 中的 referer) |
session_id |
None |
传入则复用 open_session 的动态会话 |
页面池大小由 _page_pool_size 控制(scrapling/core/ai.py#L48-L53):min(max(len(urls), 1), _MAX_POOL_PAGES),其中 _MAX_POOL_PAGES = 50 与 scrapling/engines/_browsers/_validators.py 中 PagesCount 的上限对齐。即批量超过 50 个 URL 时,会用 50 个并发页面的池子分批抓取,不会突破引擎校验器边界。
stealthy_fetch / bulk_stealthy_fetch:高防护网站抓取
这是唯一适合高防护网站的抓取器。相比 fetch 多了隐身专属参数(scrapling/core/ai.py#L796-L908):
| 参数 | 默认值 | 说明 |
|---|---|---|
solve_cloudflare |
False |
自动解决各类 Cloudflare Turnstile/Interstitial 挑战 |
hide_canvas |
False |
向 Canvas 操作注入随机噪声防指纹识别 |
block_webrtc |
False |
强制 WebRTC 走代理,防止本地 IP 泄漏 |
allow_webgl |
True |
不建议关闭——不少 WAF 现在会检查 WebGL 是否启用 |
additional_args |
None |
透传给 Playwright context 的附加设置,优先级高于 Scrapling 自身设置 |
使用持久会话时,_get_session 会校验会话类型必须是 stealthy,否则抛错提示"请使用与你的会话类型匹配的抓取工具"(scrapling/core/ai.py#L161-L173)。这从实现层面保证了 dynamic 会话只能配 fetch/bulk_fetch,stealthy 会话只能配 stealthy_fetch/bulk_stealthy_fetch。
open_session / close_session / list_sessions:会话三件套
open_session(scrapling/core/ai.py#L175-L285)创建可跨多次抓取复用的持久浏览器会话,省去每次请求都启动浏览器的开销。核心行为:
session_id自定义:不传则生成uuid4().hex[:12]的 12 位随机十六进制 ID;传入已有 ID 会立即抛ValueError,便于提前发现命名冲突(tests/ai/test_ai_mcp.py 中test_open_session_duplicate_id_raises对此有断言);max_pages:会话内并发页面/标签页上限,默认 5,值越大允许更多并行抓取;- 强制
block_ads=True:浏览器工具默认拦截广告/跟踪域名请求; - stealthy 专属参数(
hide_canvas、block_webrtc、allow_webgl、solve_cloudflare、additional_args)对 dynamic 会话不生效; - CDP 连接:传
cdp_url(ws:///wss://端点,或本机chrome --remote-debugging-port=9222对应的http://localhost:9222)时,浏览器已在运行,headless、real_chrome、executable_path等"启动期"参数会被忽略,但locale、useragent、proxy、cookies、timezone_id等仍然生效,因为每个会话在远端浏览器上创建自己的 context。
close_session 会 pop 出会话并 await session.close() 释放资源;不存在的 ID 抛 ValueError 并提示用 list_sessions 查看。list_sessions 返回所有活跃会话的 SessionInfo 列表,其中 is_alive 实时读取底层会话的 _is_alive 状态——所以"ID 存在"不等于"可用",抓取前的 _get_session 会同时检查存活状态。
screenshot:把页面截图作为图像内容块返回
screenshot 是唯一不走结构化输出(structured_output=False)的工具(scrapling/core/ai.py#L1010-L1017)。它的返回是 [ImageContent, TextContent] 内容块列表:图像本体加最终 URL 文本,模型能"直接看到"页面,而不是一段 base64 字符串。
- 必须先用
open_session打开一个dynamic或stealthy会话并传入其session_id(测试覆盖两种类型,见 tests/ai/test_ai_mcp.py 的test_screenshot_png_with_dynamic_session与test_screenshot_jpeg_with_quality等用例); image_type支持png/jpeg,quality(0-100)仅对 JPEG 有效,对 PNG 传入会抛ValueError;full_page=True截取整个可滚动页面,默认只截视口;- 与
fetch相同的wait、wait_selector、wait_selector_state、network_idle、timeout控制项全部可用; - 实现上它通过
session.fetch(url, page_action=_capture)在页面就绪回调里执行page.screenshot(),因此等待逻辑与抓取工具完全一致。
服务器级行为:指令、认证与传输安全
_build_server(scrapling/core/ai.py#L921-L954)除了注册工具,还设置了三类元信息:
- 服务器元数据:标题
Scrapling、版本取scrapling.__version__、官网文档地址、缓存提示(tools/list结果缓存 1 小时); instructions:写给 AI 的系统级指令,共 10 条,例如"用户未指定工具时先用get再逐级升级"、"多请求同站时开 session 更高效"、"css_selector命中多个元素时全部返回"、"main_content_only默认只返回<body>内容"等。这段指令决定了 Agent 在没有明确提示时的工具选择策略;- 认证设置:设置了
auth_token时,构造_StaticTokenVerifier(基于hmac.compare_digest的常量时间比较)与AuthSettings,客户端请求需携带Authorization: Bearer <token>,缺失或不匹配即被401拒绝。tests/ai/test_ai_mcp.py 中test_correct_token_is_accepted、test_wrong_tokens_are_rejected、test_non_ascii_token覆盖了正确/错误/非 ASCII 令牌的验证行为。
serve() 方法(scrapling/core/ai.py#L1020-L1042)在启动时会做两处安全警告:
--http但无令牌:打印警告——任何能到达host:port的人都能调用全部工具(包括从本机抓取任意 URL),建议传--auth-token或设置SCRAPLING_MCP_AUTH_TOKEN;- 有令牌但 stdio 模式:警告令牌仅对 streamable-http 传输生效,stdio 下被忽略。
HTTP 模式下调用 server.run(transport="streamable-http", ...),并把 _transport_security(allowed_hosts) 作为 transport_security 传入。当传入 --allowed-host 时,_transport_security(scrapling/core/ai.py#L910-L919)启用 DNS 重绑定防护,allowed_origins 会自动为每个主机名派生 http/https 两个 origin。测试 test_allowed_hosts_enable_dns_rebinding_protection 验证了该配置确实被启用。
依赖安装与适用前提
从 pyproject.toml#L84-L96 看,MCP 能力属于 ai 可选依赖:
pip install "scrapling[ai]"
ai extra 包含 mcp>=2.0.0、markdownify>=1.2.0 与 scrapling[fetchers](即完整抓取栈)。浏览器类工具还需要安装浏览器依赖:
scrapling install
CLI 的 install 命令 实际执行 playwright install chromium 与 playwright install-deps chromium,并更新 TLD 数据库;已安装过会写 .scrapling_dependencies_installed 标记文件直接跳过。适用前提与限制:get/bulk_get 仅适合低-中防护网站;fetch/bulk_fetch 适合 JS 渲染网站;只有 stealthy_fetch/bulk_stealthy_fetch 面向高防护站点。
源码与测试佐证
本文引用的实现事实均可在仓库中复核:
- 工具注册与全部工具函数:scrapling/core/ai.py(
ScraplingMCPServer,约 1042 行); - CLI
mcp/scrapling-mcp入口与参数定义:scrapling/cli.py#L145-L185; - 控制台脚本声明:pyproject.toml#L107-L109;
- MCP 注册表清单:server.json;
- 功能测试:tests/ai/test_ai_mcp.py,覆盖工具调用、会话开闭与类型错配、自定义
session_id冲突、executable_path的服务器级/环境变量/单请求三级覆盖、页面池上限、截图 PNG/JPEG/quality 校验、令牌认证与 10 个工具的注册断言(test_all_tools_are_registered_with_auth_enabled中len(built._tool_manager.list_tools()) == 10); - 配套使用指南(提示词示例、客户端配置、最佳实践):docs/ai/mcp-server.md。
实践要点
- 在提示词中明确工具:
get与浏览器工具的成本、行为差异很大,写明"使用普通请求"或"使用隐身抓取"可获得一致结果,也能让 Agent 先get再按需升级; - 用
css_selector在到达 AI 之前收窄内容:这是 Scrapling MCP 服务器相对其他抓取服务器的核心优势——不需要把整页塞给模型再让模型自己找字段; - 多页同站任务开会话:
open_session→ 传session_id复用浏览器 → 用毕close_session;会话忘记关闭会一直占用资源,丢失 ID 时可用list_sessions找回; - 批量优先:多 URL 场景使用
bulk_*工具,并发由页面池自动管理(上限 50); - 对外暴露 HTTP 端点时:配置
--auth-token(优先用SCRAPLING_MCP_AUTH_TOKEN环境变量避免令牌出现在进程列表)、--allowed-host开启 DNS 重绑定防护,并把服务器置于 TLS 终结的反向代理之后——明文 HTTP 会裸露令牌,且这是共享密钥而非每客户端凭据,轮换需要重启服务器。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00