用代码做自媒体(一):Python 调用博客园(cnblogs) MetaWeblog API 自动发布 Markdown 文章

用一段纯标准库的 Python 脚本,把本地 Markdown 通过博客园的 MetaWeblog API(XML-RPC) 一键发布、更新、查询,告别网页后台复制粘贴。下面是可直接照抄的完整步骤和脚本。

环境

  • Python 3.6+(只用标准库 xmlrpc.client,无需 pip install
  • 一个博客园账号(接口端点形如 https://rpc.cnblogs.com/metaweblog/<博客名>
  • 操作系统无关(Linux / macOS / Windows 均可)

步骤 1:后台启用 MetaWeblog 并拿令牌

MetaWeblog 默认关闭,不开直接调用会报 Fault 403: 您的博客已禁用 MetaWeblogApi

  1. 打开 https://i.cnblogs.com/settings#enableServiceAccess
  2. 勾选「博客客户端访问」并保存
  3. 复制页面上的访问令牌(Token)——注意它不是登录密码,且启用时可能被重新生成,务必用最新的
  4. 同一页面能看到你的接口地址:https://rpc.cnblogs.com/metaweblog/<你的博客名>

步骤 2:保存发布脚本

把下面的脚本存为 cnblogs_publish.py,改掉 ENDPOINT 里的博客名:

#!/usr/bin/env python3
import os, sys, argparse, xmlrpc.client
from datetime import datetime

ENDPOINT = "https://rpc.cnblogs.com/metaweblog/<你的博客名>"
BLOG_ID = "blog"  # 博客园下此值不影响结果

def server():
    return xmlrpc.client.ServerProxy(ENDPOINT, allow_none=True)

def creds():
    return os.environ["CNBLOGS_USER"], os.environ["CNBLOGS_TOKEN"]

def list_posts(n):
    u, t = creds()
    for p in server().metaWeblog.getRecentPosts(BLOG_ID, u, t, n):
        print(p["postid"], p["dateCreated"], p["title"])

def publish(md, title, cats, tags, postid, draft):
    u, t = creds()
    content = open(md, encoding="utf-8").read()
    cats = [c.strip() for c in cats.split(",")] if cats else []
    if "[Markdown]" not in cats:          # 见步骤 6 的坑
        cats.insert(0, "[Markdown]")
    post = {"title": title, "description": content,
            "dateCreated": datetime.now(), "categories": cats,
            "mt_keywords": tags or ""}
    s, flag = server(), not draft         # flag: True=公开 False=草稿
    if postid:
        s.metaWeblog.editPost(postid, u, t, post, flag); print("updated", postid)
    else:
        print("created", s.metaWeblog.newPost(BLOG_ID, u, t, post, flag))

if __name__ == "__main__":
    ap = argparse.ArgumentParser()
    ap.add_argument("md", nargs="?"); ap.add_argument("--title")
    ap.add_argument("--cats"); ap.add_argument("--tags"); ap.add_argument("--postid")
    ap.add_argument("--draft", action="store_true"); ap.add_argument("--list", type=int)
    a = ap.parse_args()
    if a.list: list_posts(a.list)
    else: publish(a.md, a.title, a.cats, a.tags, a.postid, a.draft)

步骤 3:配置凭证

凭证从环境变量读取,别硬编码进脚本:

export CNBLOGS_USER=你的博客名
export CNBLOGS_TOKEN=你的访问令牌

步骤 4:验证连通

先列出最近文章,能打印出来就说明打通了:

python3 cnblogs_publish.py --list 5

输出示例:

20187928 20260527T16:27:00 如何通过博客园的 MetaWeblog API 发布文章
19806404 20260401T13:17:00 PostgreSQL 备份表结构和数据
19521376 20260123T11:45:00 监控指标

步骤 5:发布文章(先草稿,确认后公开)

先发草稿,在后台预览渲染无误,再带 postid 转公开:

# 发草稿
python3 cnblogs_publish.py post.md --title "我的标题" \
  --cats "[随笔分类]Python" --tags "python,自动化" --draft

# 确认后转公开(用上一步返回的 postid,去掉 --draft)
python3 cnblogs_publish.py post.md --title "我的标题" \
  --cats "[随笔分类]Python" --tags "python,自动化" --postid 上一步的ID

步骤 6:避开三个坑

  • Fault 403: 已禁用 MetaWeblogApi:后台开关没开或令牌过期,回到步骤 1。
  • 格式全乱categories 必须含 [Markdown],否则博客园按 HTML 解析正文。脚本已自动插入。
  • 分类没生效/建出重复分类--cats 的名称要带 [随笔分类] 前缀且与后台一字不差;不确定先 getCategories 查。

快速参考

接口端点  https://rpc.cnblogs.com/metaweblog/<博客名>
启用页面  https://i.cnblogs.com/settings#enableServiceAccess
凭证      export CNBLOGS_USER / CNBLOGS_TOKEN(Token 非登录密码)
列文章    python3 cnblogs_publish.py --list N
发草稿    ... --draft
转公开    ... --postid <ID>
方法 作用
metaWeblog.newPost 新建(末参 True 公开 / False 草稿)
metaWeblog.editPost 更新(带 postid)
metaWeblog.getRecentPosts 列最近文章
metaWeblog.getCategories 取分类(含 [Markdown] 等标志)
blogger.deletePost 删除

三条铁律:正文 Markdown 必带 [Markdown];分类名带 [随笔分类] 前缀且一字不差;先草稿预览再公开。

posted @ 2026-05-27 16:27  Hello_worlds  阅读(17)  评论(0)    收藏  举报