关于 notion-sdk
notion-sdk 是通过官方 Python notion-client SDK 自动化操作 Notion 的技能,提供创建页面、添加内容块和查询数据库的脚本,并支持令牌验证与重试处理。
主要功能
- 01创建页面和数据库条目
- 02追加格式化内容块
- 03查询、筛选和排序数据库
- 04验证集成令牌
- 05重试限流和服务器错误请求
适用场景
- 01通过 Python 工作流创建 Notion 页面
- 02向页面添加结构化内容
- 03检索筛选后的数据库记录
- 04处理暂时性 API 错误
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill notion-sdk安装后在 Claude Code 中输入/notion-sdk确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/block-types.mdevolution-log.mdpagination.mdproperty-types.mdrich-text.mdscripts/add_blocks.pycreate_page.pynotion_wrapper.pyquery_database.pytests/test_block_builders.pytest_client.pytest_filter_builders.pytest_integration.pytest_property_builders.py详细介绍
Notion SDK 技能
使用官方 notion-client Python SDK 以编程方式控制 Notion。当前版本请参阅 PyPI。
自我演进的技能:此技能会在使用过程中不断改进。如果说明有误、参数发生变化,或需要使用变通方案,请立即修复此文件,不要拖延。仅针对真实且可复现的问题进行更新。
何时使用此技能
在以下情况下使用此技能:
- 通过 API 在 Notion 中创建页面或数据库
- 以编程方式查询 Notion 数据库
- 向 Notion 页面添加块(文本、代码、标题)
- 使用 Python 自动化 Notion 工作流
- 将外部数据源与 Notion 集成
预检:收集令牌
执行任何 Notion API 操作前,先收集集成令牌:
AskUserQuestion(questions=[{
"question": "Please provide your Notion Integration Token (starts with ntn_ or secret_)",
"header": "Notion Token",
"options": [
{"label": "I have a token ready", "description": "Token from notion.so/my-integrations"},
{"label": "Need to create one", "description": "Go to notion.so/my-integrations → New integration"}
],
"multiSelect": false
}])
用户提供令牌后:
- 验证格式(必须以
ntn_或secret_开头) - 使用
scripts/notion_wrapper.py中的validate_token()进行测试 - 提醒用户:必须将每个页面/数据库共享给该集成
快速入门
1. 在数据库中创建页面
from notion_client import Client
from scripts.create_page import (
create_database_page,
title_property,
status_property,
date_property,
)
client = Client(auth="ntn_...")
page = create_database_page(
client,
data_source_id="abc123...", # Database ID
properties={
"Name": title_property("My New Task"),
"Status": status_property("In Progress"),
"Due Date": date_property("2025-12-31"),
}
)
print(f"Created: {page['url']}")
2. 添加内容块
from scripts.add_blocks import (
append_blocks,
heading,
paragraph,
bullet,
code_block,
callout,
)
blocks = [
heading("Overview", level=2),
paragraph("This page was created via the Notion API."),
callout("Remember to share the page with your integration!", emoji="⚠️"),
heading("Tasks", level=3),
bullet("First task"),
bullet("Second task"),
code_block("print('Hello, Notion!')", language="python"),
]
append_blocks(client, page["id"], blocks)
3. 查询数据库
from scripts.query_database import (
query_data_source,
checkbox_filter,
status_filter,
and_filter,
sort_by_property,
)
# Find incomplete high-priority items
results = query_data_source(
client,
data_source_id="abc123...",
filter_obj=and_filter(
checkbox_filter("Done", False),
status_filter("Priority", "High")
),
sorts=[sort_by_property("Due Date", "ascending")]
)
for page in results:
title = page["properties"]["Name"]["title"][0]["plain_text"]
print(f"- {title}")
可用脚本
| 脚本 | 用途 |
|---|---|
notion_wrapper.py | 客户端设置、令牌验证、重试封装 |
create_page.py | 创建页面、属性构建器 |
add_blocks.py | 追加块、块类型构建器 |
query_database.py | 查询、筛选、排序、搜索 |
参考资料
重要限制
速率限制
- 平均每秒 3 次请求(短时间内可容忍突发请求)
- 使用
api_call_with_retry()自动处理速率限制 - 429 响应包含
Retry-After标头
身份验证模型
- 必须进行 页面级共享(而非整个工作区共享)
- 用户必须将集成明确添加到每个页面/数据库:
- 页面 → ... 菜单 → 连接 → 添加连接 → 选择集成
API 版本(v2.6.0+)
- 多数据源数据库使用
data_source_id,而非database_id - 简单数据库仍可使用旧版
database_id - 脚本会自动处理这两种模式
不支持的操作
- 修改工作区设置
- 管理用户权限
- 创建/管理模板
- 访问账单/订阅
API 行为模式
通过集成测试发现的见解(请查阅测试引用以进行验证)。
速率限制与重试逻辑
api_call_with_retry() 会自动处理暂时性故障:
| 错误类型 | 行为 | 等待策略 |
|---|---|---|
| 429 速率受限 | 重试 | 遵循 Retry-After 标头(默认 1s) |
| 500 服务器错误 | 重试 | 指数退避:1s、2s、4s |
| 身份验证/验证 | 立即失败 | 不重试 |
引用:test_client.py::TestRetryLogic(第 146-193 行)
写入后读取一致性
新建的块可能无法立即查询。请至少延迟 0.5s:
append_blocks(client, page_id, blocks)
time.sleep(0.5) # Eventual consistency delay
children = client.blocks.children.list(page_id)
引用:test_integration.py::TestBlockAppend::test_retrieve_appended_blocks(第 298 行)
v2.6.0 API 迁移
| 旧模式 | 新模式(v2.6.0+) |
|---|---|
client.databases.query() | client.data_sources.query() |
filter: {"value": "database"} | filter: {"value": "data_source"} |
引用:test_integration.py::TestDatabaseQuery(第 110 行)
仅归档删除
无法通过 API 永久删除页面——只能将其归档(移至回收站):
client.pages.update(page_id, archived=True) # Trash, not delete
引用:test_integration.py 清理 fixture(第 72-76 行)
边界情况与验证
属性构建器的边界情况
| 输入 | 行为 | 有效? |
|---|---|---|
空字符串 "" | 创建空内容 | 是 |
空数组 [] | 清空多选项/关联 | 是 |
数字类型的 None | 清空属性值 | 是 |
零 0 | 有效数字(不会被视为假值) | 是 |
负数 -42 | 有效数字 | 是 |
| Unicode/表情符号 | 完整保留 | 是 |
引用:test_property_builders.py::TestPropertyBuildersEdgeCases(第 302-341 行)
输入验证责任
构建器有意保持宽松——验证在 API 层进行:
| 属性 | 构建器接受 | API 验证 |
|---|---|---|
| 日期 | 任意字符串 | 仅限 ISO 8601 |
| URL | 任意字符串 | 有效的 URL 格式 |
| 复选框 | 真值 | 需要布尔值 |
最佳实践:在构建属性之前,在应用程序中进行验证。
引用:test_property_builders.py::TestPropertyBuildersInvalidInputs(第 347-376 行)
令牌验证
- 区分大小写:只有小写的
ntn_和secret_有效 - API 调用前会进行格式检查(避免不必要的请求)
- 空令牌或仅含空白字符的令牌会立即被拒绝
引用:test_client.py::TestClientEdgeCases(第 196-224 行)
查询与筛选模式
复合筛选器组合
# Empty compound (matches all)
and_filter() # {"and": []}
# Deep nesting supported
and_filter(
or_filter(filter_a, filter_b),
and_filter(filter_c, filter_d)
)
引用:test_filter_builders.py::TestFilterEdgeCases(第 323-360 行)
筛选器限制
筛选器不会排除 NULL 属性——请在 Python 中检查:
if row["properties"]["Rating"]["number"] is not None:
# Process non-null values
引用:test_integration.py::TestDatabaseQuery::test_query_database_with_filter(第 120-135 行)
分页不变量
| 条件 | has_more | next_cursor |
|---|---|---|
| 还有更多结果 | True | 存在且非 None |
| 没有更多结果 | False | 可能不存在/为 None |
使用 next_cursor 前,始终检查 has_more。
引用:test_integration.py::TestDatabaseQuery::test_query_database_with_pagination(第 137-151 行)
错误处理
from notion_client import APIResponseError, APIErrorCode
try:
result = client.pages.create(...)
except APIResponseError as e:
if e.code == APIErrorCode.ObjectNotFound:
print("Page/database not found or not shared with integration")
elif e.code == APIErrorCode.Unauthorized:
print("Token invalid or expired")
elif e.code == APIErrorCode.RateLimited:
print(f"Rate limited. Retry after {e.additional_data.get('retry_after')}s")
else:
raise
安装
uv pip install notion-client # v2.6+ required for data_source support
或者使用 PEP 723 内联依赖项(脚本中包含这些依赖项)。
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 未找到对象 | 页面未与集成共享 | 共享页面:... 菜单 → 连接 → 添加集成 |
| 未授权 | 令牌无效或已过期 | 在 notion.so/my-integrations 生成新令牌 |
| 触发速率限制(429) | 请求过多 | 使用 api_call_with_retry() 自动处理 |
| 查询结果为空 | 筛选条件未匹配任何内容 | 检查筛选语法和属性名称 |
| 创建后未找到区块 | 最终一致性延迟 | 写入后、读取前延迟 0.5s |
| 属性类型无效 | 使用了错误的构建器 | 检查数据库架构中的属性类型 |
| 令牌格式不被接受 | 前缀错误(区分大小写) | 令牌必须以 ntn_ 或 secret_(小写)开头 |
| 数据源 ID 无法使用 | API 版本过旧 | 将 notion-client 升级到最新版本 |
执行后反思
此技能完成后,请在结束前检查:
- 命令是否成功? — 如果没有,请修正导致失败的指令或错误表。
- 参数或输出是否发生变化? — 如果底层工具的接口有所变动,请更新用法示例和参数表,使其与之匹配。
- 是否需要变通处理? — 如果你不得不临时变通(使用不同的标志、执行额外步骤),请更新此 SKILL.md,以便下次调用时无需重复同样的变通处理。
仅在问题真实且可复现时进行更新,不要更新推测性问题。