这次我们来看一个能让你用代码管理 Substack 博客的工具。Substack 本身是一个流行的邮件订阅和内容发布平台,但它的官方功能主要集中在网页端手动操作。如果你想批量发布文章、自动化内容同步,或者将写作流程集成到自己的工具链里,就会遇到瓶颈。
这个项目就是一个非官方的 Substack 发布 API。它不是一个需要本地部署、消耗大量显存的 AI 模型,而是一个轻量级的 Python 库和命令行工具。它的核心价值在于:通过代码来操作你的 Substack 账户,实现文章的创建、更新、发布、草稿管理等一系列操作。对于开发者、内容创作者或者希望将 Substack 纳入自动化工作流的人来说,这直接解决了“手动操作低效”和“缺乏程序化接口”的痛点。
本文将带你快速了解这个 API 的核心能力、如何配置环境、进行安装,并通过实际的 Python 脚本和 CLI 命令演示如何创建文章、上传图片、管理草稿。我们还会探讨如何将其集成到更复杂的自动化流程中,比如结合 RSS 订阅自动转载,或者与你的静态博客生成器联动。如果你经常与 Substack 打交道,并且厌倦了重复的点击操作,这篇文章值得你继续往下看。
1. 核心能力速览
这个非官方 API 项目主要提供了对 Substack 发布功能程序化访问的能力。下表总结了它的关键特性:
| 能力项 | 说明 |
|---|---|
| 项目类型 | 非官方 Python 库 / 命令行工具 (CLI) |
| 核心功能 | 通过代码创建、更新、发布、删除 Substack 文章;管理草稿;上传图片。 |
| 硬件门槛 | 极低。无需 GPU,普通 CPU 即可运行,主要依赖网络和 Python 环境。 |
| 启动方式 | 通过 Pythonimport调用库,或直接在终端使用substack-apiCLI 命令。 |
| 接口能力 | 提供完整的 Python API 和 RESTful 风格的 CLI,支持所有核心文章操作。 |
| 批量任务 | 支持。可通过脚本循环或任务队列轻松实现批量发布、草稿迁移等。 |
| 依赖管理 | 标准 Python 包,通过pip安装,依赖常见库如requests。 |
| 适合场景 | 内容自动化、多平台同步、与 CI/CD 集成、批量内容管理、开发者工具链。 |
从表格可以看出,这个工具的重点不是复杂的 AI 推理,而是提升 Substack 内容管理的效率和自动化水平。它把网页端的操作封装成了可编程的接口。
2. 适用场景与使用边界
谁适合使用这个工具?
- 技术类内容创作者/开发者:拥有个人 Substack,希望将写作与 Git 工作流结合,或用脚本生成定期内容。
- 团队或机构:需要多人协作或统一发布流程到 Substack,可通过 API 标准化操作。
- 自动化运维人员:希望将其他平台(如个人博客、Medium、RSS 源)的内容自动同步至 Substack。
- 工具链整合者:希望将 Substack 发布功能集成到更大的自动化系统或内部工具中。
能解决什么问题?
- 摆脱手动复制粘贴:从 Markdown 文件或数据库直接发布文章。
- 实现内容同步自动化:监听 RSS 源,自动抓取并发布到 Substack。
- 批量操作:一次性发布多篇积压的草稿,或批量更新文章信息(如标签)。
- 集成到开发流程:在 CI/CD 流水线中,当项目更新时自动生成并发布更新日志到 Substack。
不适合什么场景?
- 非技术用户:如果你完全不接触命令行或代码,使用网页端是更直接的选择。
- 需要官方完整功能:此 API 仅覆盖发布相关核心功能,可能不包含数据分析、订阅者管理、付费墙设置等 Substack 全部后台功能。
- 超高频率调用:需注意礼貌使用,避免对 Substack 服务器造成压力,可能导致临时限制。
版权与合规边界
至关重要:此工具仅提供发布接口,不涉及内容创作。你通过它发布的所有内容,其版权、原创性、合规性责任完全由使用者自行承担。
- 内容授权:确保你拥有发布内容的全部权利,或已获得充分授权。
- 隐私与数据:该工具需要你的 Substack 账户凭证(如 Cookie)进行认证。务必妥善保管这些凭证,不要泄露或在公开代码库中提交。
- 服务条款:使用非官方 API 可能违反 Substack 的服务条款。虽然目前很多平台对合理的自动化工具持默许态度,但使用者需自行评估风险,并避免进行滥用或攻击性操作。
3. 环境准备与前置条件
在开始安装和调用 API 之前,你需要准备好以下环境:
- 操作系统:支持 Windows (建议使用 WSL2 或 PowerShell)、macOS 和 Linux。本文示例以 Linux/macOS 命令行环境为主。
- Python 环境:需要 Python 3.7 或更高版本。推荐使用 Python 3.8+。
- 包管理工具:确保
pip可用(通常随 Python 安装)。 - Substack 账户:一个有效的 Substack 发布者账户。你需要能正常登录并发布文章。
- 认证信息(关键):非官方 API 通常需要通过模拟浏览器登录来获取认证令牌(如
session cookie)。你需要准备好从浏览器中提取的特定 Cookie 值(例如substack.sid)。具体获取方法将在下文详述。 - 网络环境:能够正常访问 Substack 网站。
4. 安装部署与启动方式
安装过程非常简单,因为它是一个标准的 Python 包。
4.1 使用 pip 安装
打开你的终端(命令行),执行以下命令进行安装:
# 安装最新的 substack-api 包(假设包名为此,具体名称需根据项目文档确认) pip install substack-api # 或者,如果项目托管在 GitHub 上,可能需要通过 git 安装 # pip install git+https://github.com/用户名/仓库名.git安装完成后,你可以通过以下命令验证是否安装成功,并查看基本的 CLI 帮助信息:
# 检查是否可调用 substack-api --help # 或 python -m substack_api --help4.2 获取并配置认证信息
这是最关键的一步。由于没有官方 OAuth 授权,我们需要手动获取登录态。
- 登录 Substack:在 Chrome 或 Firefox 浏览器中正常登录你的 Substack 账户。
- 打开开发者工具:在 Substack 网站页面,按
F12打开开发者工具,切换到Application(Chrome) 或Storage(Firefox) 标签页。 - 查找 Cookie:在左侧找到
Cookies->https://substack.com。在 Cookie 列表中,寻找名为substack.sid的项。其Value字段就是一长串字符,这就是你的会话 Cookie。 - 安全保存:切勿将此 Cookie 值提交到公开的 Git 仓库!建议使用环境变量或本地配置文件来管理。
配置方式示例(环境变量):
# 在终端中临时设置(仅当前会话有效) export SUBSTACK_SESSION_COOKIE="你的长长cookie值" # 或者,更安全的方式是写入到仅自己可读的文件中,并在脚本中读取 echo "SUBSTACK_SESSION_COOKIE=你的长长cookie值" > ~/.substack_env chmod 600 ~/.substack_env5. 功能测试与效果验证
安装并配置好认证后,我们就可以开始实际测试 API 的各项功能了。我们将从 CLI 和 Python 脚本两个角度进行验证。
5.1 CLI 命令行快速测试
首先,我们用最直接的命令行方式来创建一篇草稿。
# 假设 CLI 命令为 `substack-post`,并使用环境变量中的 Cookie export SUBSTACK_SESSION_COOKIE="你的cookie" substack-post create-draft \ --title "我的第一篇API测试文章" \ --body "<p>这是通过命令行工具发布的第一段内容。</p><p>支持HTML标签。</p>" \ --substack-url "你的子域名.substack.com"预期结果:命令执行成功后,应返回新创建草稿的 ID 或文章链接。此时,你登录 Substack 后台的“草稿”列表,应该能看到这篇新文章。
判断成功:在 Substack 后台网页可见到对应标题的草稿。常见失败原因:
- Cookie 无效或已过期(重新登录获取)。
--substack-url参数错误,应使用你的完整发布地址(如myname.substack.com)。- 网络问题导致 API 请求失败。
5.2 Python API 基础功能测试
接下来,我们编写一个 Python 脚本来进行更细致的操作。创建一个名为test_substack_api.py的文件。
import os from substack_api import SubstackClient # 假设客户端类名为 SubstackClient # 1. 初始化客户端 cookie = os.getenv("SUBSTACK_SESSION_COOKIE") if not cookie: raise ValueError("请设置 SUBSTACK_SESSION_COOKIE 环境变量") client = SubstackClient( session_cookie=cookie, substack_url="你的子域名.substack.com" # 例如: "techblog.substack.com" ) # 2. 创建一篇新的草稿 print("正在创建草稿...") draft_response = client.create_draft( title="Python API 测试文章", body="""<h2>这是一个二级标题</h2> <p>通过 <strong>Python API</strong> 发布内容真是太方便了。</p> <ul> <li>可以批量操作</li> <li>可以集成到自动化流程</li> </ul> """, # 可选参数 is_published=False, # 保持为草稿 # subtitle="副标题", # 设置副标题 # section_id=123, # 发布到特定栏目(需先获取栏目ID) ) print(f"草稿创建成功!草稿ID: {draft_response['id']}") print(f"编辑链接: {draft_response['edit_url']}") # 3. 上传图片到文章 print("\n正在上传图片...") image_path = "./test_image.png" # 准备一张本地图片 if os.path.exists(image_path): image_info = client.upload_image(image_path) print(f"图片上传成功!URL: {image_info['url']}") # 可以将 image_info['url'] 插入到文章的 body HTML 中 else: print("测试图片不存在,跳过上传步骤。") # 4. 更新已存在的草稿(假设我们知道上一步的草稿ID) print("\n正在更新草稿...") if 'id' in draft_response: update_response = client.update_draft( draft_id=draft_response['id'], body="<p>这是更新后的内容,添加了更多细节。</p>" ) print(f"草稿更新成功!状态: {update_response.get('status')}") # 5. 发布草稿 print("\n正在发布文章...") publish_response = client.publish_draft(draft_id=draft_response['id']) print(f"文章发布成功!文章URL: {publish_response['url']}") # 6. (可选)获取已发布文章列表 print("\n获取最近的文章列表...") posts = client.get_posts(limit=5) for post in posts: print(f"- {post['title']} (发布于: {post.get('post_date')})")操作步骤:
- 将脚本中的
你的子域名.substack.com替换为你的实际地址。 - 确保环境变量
SUBSTACK_SESSION_COOKIE已设置。 - 在脚本同目录下放一张名为
test_image.png的图片(可选)。 - 运行脚本:
python test_substack_api.py。
预期结果:
- 脚本应依次输出“创建成功”、“上传成功”(如果有图片)、“更新成功”、“发布成功”等信息。
- 你的 Substack 后台会先后出现草稿,并且最终该文章变为已发布状态。
- 在 Substack 主页或帖子管理列表中能看到这篇新文章。
功能验证点:
- ✅认证连通性:能成功初始化客户端并与 Substack 通信。
- ✅草稿创建:能在后台创建指定标题和内容的草稿。
- ✅图片上传:能将本地图片上传到 Substack 的 CDN 并获得可访问的 URL。
- ✅内容更新:能对现有草稿进行内容修改。
- ✅文章发布:能将草稿状态变更为已发布。
- ✅文章列表读取:能获取账户下的文章列表。
6. 接口 API 与批量任务
这个项目的核心价值在于其提供的程序化接口。除了上面演示的基本用法,它通常还支持更丰富的操作。
6.1 核心 API 方法概览
一个完善的 Substack API 客户端可能包含以下方法(具体以实际项目文档为准):
create_draft(title, body, **kwargs): 创建草稿。get_draft(draft_id): 获取特定草稿内容。get_drafts(): 获取所有草稿列表。update_draft(draft_id, **kwargs): 更新草稿(标题、正文、封面等)。publish_draft(draft_id): 发布草稿。delete_draft(draft_id): 删除草稿。upload_image(file_path): 上传图片。get_posts(limit, offset): 获取已发布文章。update_post(post_id, **kwargs): 更新已发布文章(部分平台支持)。delete_post(post_id): 删除已发布文章。
6.2 批量任务实践:从 Markdown 文件夹自动发布
假设你有一个装满 Markdown 文件的目录,你想把它们全部发布到 Substack 作为草稿。
import os import glob from markdown import markdown # 需要安装 markdown 库: pip install markdown from substack_api import SubstackClient import time client = SubstackClient( session_cookie=os.getenv("SUBSTACK_SESSION_COOKIE"), substack_url="yourname.substack.com" ) md_dir = "./blog_posts/" for md_file in glob.glob(os.path.join(md_dir, "*.md")): with open(md_file, 'r', encoding='utf-8') as f: content = f.read() # 提取标题(假设第一行是标题) lines = content.strip().split('\n') title = lines[0].lstrip('#').strip() if lines[0].startswith('#') else os.path.splitext(os.path.basename(md_file))[0] # 将 Markdown 转换为 HTML html_body = markdown(content, extensions=['extra', 'codehilite']) print(f"正在发布: {title}") try: response = client.create_draft(title=title, body=html_body, is_published=False) print(f" 成功!草稿ID: {response['id']}") # 避免请求过于频繁,短暂延迟 time.sleep(2) except Exception as e: print(f" 失败!错误: {e}")这个脚本实现了:
- 遍历指定目录下的所有
.md文件。 - 读取文件内容,将第一行
# 标题作为文章标题,或将文件名作为标题。 - 使用
markdown库将 Markdown 内容转换为 HTML。 - 调用 Substack API 创建为草稿。
- 加入短暂延迟,避免触发服务器的速率限制。
6.3 作为 HTTP 服务运行(高级用法)
有些 API 项目会封装一个简单的 HTTP 服务器,提供 RESTful 接口,方便其他语言调用。启动方式可能如下:
# 假设项目提供了 serve 命令 substack-api serve --host 127.0.0.1 --port 8000 --cookie $SUBSTACK_SESSION_COOKIE启动后,你就可以通过curl或任何 HTTP 客户端来调用:
# 创建草稿 curl -X POST http://127.0.0.1:8000/api/drafts \ -H "Content-Type: application/json" \ -d '{"title":"来自cURL的文章", "body":"<p>测试内容</p>", "published": false}' # 获取草稿列表 curl http://127.0.0.1:8000/api/drafts这种方式将 Python API 转换为了一个通用的 HTTP 服务,极大地扩展了集成可能性。
7. 资源占用与性能观察
与消耗大量显存的 AI 模型不同,此类 API 工具的资源占用几乎可以忽略不计,性能瓶颈主要在网络和 Substack 服务器响应。
- CPU/内存占用:一个简单的 Python 脚本或 CLI 命令,内存占用通常在几十 MB 到百 MB 之间,CPU 使用率极低。
- 网络延迟:所有操作都需要向
substack.com发起 HTTP 请求。性能取决于你的网络环境和 Substack 服务器的响应速度。批量操作时,建议在请求间添加time.sleep(1-2)以避免被限制。 - 速率限制:需要特别注意。Substack 虽然没有公开的 API 限流政策,但频繁的自动化请求可能触发反爬虫机制。务必保持请求间隔,模拟人类操作速度。如果遇到
429 Too Many Requests或登录态失效,应暂停程序并检查。 - 稳定性:由于是非官方接口,其稳定性依赖于 Substack 前端网页结构。如果 Substack 网站进行重大改版,可能导致此 API 暂时失效,需要维护者更新代码。
8. 常见问题与排查方法
在使用过程中,你可能会遇到以下问题。这里提供排查思路。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 认证失败,无法创建草稿 | 1. Cookie 值错误或已过期。 2. substack_url参数不正确。3. 账户权限不足(非发布者)。 | 1. 检查环境变量是否正确加载。 2. 手动在浏览器访问 substack_url确认能登录。3. 打印出初始化的客户端配置信息。 | 1. 重新登录 Substack,获取新的 Cookie。 2. 确保 substack_url是你的完整发布地址。3. 确认登录的账户有发布权限。 |
导入错误:ModuleNotFoundError | 1. 包未正确安装。 2. Python 环境有多个版本,安装到了其他版本下。 3. 包名不正确。 | 1. 运行pip list | grep substack查看是否安装。2. 确认当前终端使用的 Python 版本 ( python --version) 与安装包的版本一致。 | 1. 使用pip install重新安装。2. 使用 python -m pip install或虚拟环境确保环境一致。3. 查阅项目文档确认正确的包名。 |
| 上传图片失败 | 1. 图片文件路径错误。 2. 图片文件过大或格式不受支持。 3. API 的图片上传端点有变化。 | 1. 检查image_path是否存在且可读。2. 尝试在网页端手动上传同类型图片,确认平台支持。 3. 查看项目 Issue 或更新日志。 | 1. 使用绝对路径或确认相对路径正确。 2. 压缩图片或转换格式(如 PNG/JPG)。 3. 等待库作者更新或寻找替代上传方法。 |
| 批量操作中途失败 | 1. 网络波动。 2. 触发速率限制。 3. Cookie 在长时间运行后失效。 | 1. 查看错误日志或异常信息。 2. 检查失败前后的请求频率。 3. 在脚本中加入异常捕获和重试机制。 | 1. 在循环内加入try...except,记录失败任务稍后重试。2. 增加请求间隔(如 time.sleep(3))。3. 考虑实现 Cookie 的自动刷新机制(如果库支持)。 |
| API 返回 HTML 或意外内容 | Substack 网站前端结构已更新,导致 API 解析失败。 | 对比库的请求参数和浏览器开发者工具中“网络”选项卡的请求。 | 1. 暂时回退到旧版本库(如果可用)。 2. 关注项目 GitHub 仓库,等待维护者更新。 3. 根据新的网页结构,手动调整或贡献代码。 |
9. 最佳实践与使用建议
为了稳定、安全地使用这个非官方 API,遵循以下最佳实践至关重要:
- 认证信息隔离:永远不要将
session_cookie硬编码在脚本中或提交到公开的版本控制系统(如 GitHub)。务必使用环境变量、配置文件(.gitignore排除)或密钥管理服务。 - 实施请求退避:在批量操作脚本中,务必在请求之间添加随机延迟(例如
time.sleep(2 + random.random())),以模拟人类操作,避免被封。 - 添加完善的错误处理:网络请求可能因各种原因失败。你的脚本应该能捕获异常,记录错误日志,并可能将失败的任务加入重试队列。
- 先草稿,后发布:在自动化流程中,建议先统一创建为草稿。经过人工审核或最终确认后,再运行另一个脚本批量发布。这给了你一个安全缓冲。
- 定期检查与更新:非官方 API 的寿命取决于其与 Substack 网站的兼容性。定期检查你使用的库是否有更新,并测试核心功能是否依然工作。
- 尊重平台与内容:此工具是效率工具,不是攻击工具。请合理使用,不要用于发布垃圾信息、侵犯版权内容或进行任何违反 Substack 服务条款的活动。你对自己发布的所有内容负全部责任。
- 备份你的内容:自动化发布很方便,但不要将 Substack 作为唯一的内容存储地。确保你的原始 Markdown 或 HTML 文件在本地或其它版本库中有备份。
10. 总结与下一步
这个非官方的 Substack Posting API 项目,为开发者打开了一扇门,将内容发布从手动点击变成了可编程、可集成的自动化操作。它最值得尝试的点在于其轻量化和实用性——无需复杂的部署环境,一个pip install和一份 Cookie 就能将你的写作流程接入自动化管道。
你应该最先验证的功能就是创建草稿和上传图片,这是内容发布最核心的两个环节。成功之后,批量发布和与其他系统(如静态站点生成器、RSS 阅读器)的集成便水到渠成。
最容易踩的坑主要集中在认证信息的获取与保管,以及Substack前端变更导致的API失效。因此,在投入生产级自动化之前,务必确保你的脚本有足够的错误处理和日志记录能力。
下一步,你可以探索更多集成可能性:
- 与静态博客联动:在 Hugo 或 Hexo 生成静态网站后,自动将新文章同步一份到 Substack 作为引流渠道。
- 构建内容聚合器:监控特定 RSS 源,将符合条件的内容自动摘要并转发到你的 Substack。
- 开发内部协作工具:为团队制作一个简单的内部界面,让非技术成员也能通过表单提交内容,后端自动调用此 API 发布到 Substack。
工具的价值在于如何使用。这个 API 项目提供了一个可靠的技术抓手,如何用它来提升你的内容工作流效率,就取决于你的想象力和实践了。建议收藏本文,在需要自动化发布时,可以快速回顾关键步骤和避坑指南。