为什么选 XML-RPC 而不是 REST API
先说结论:WordPress 有两套接口可以远程发文,REST API 和 XML-RPC。很多人第一反应是用 REST API,毕竟 JSON 格式看着舒服,文档也多。但我实际试了一圈下来,XML-RPC 更适合自动发文章这个场景。
原因很简单:
1. REST API 需要搞 Application Passwords,WordPress 5.6 以后才原生支持,而且有些主机环境会拦截 REST 请求
2. XML-RPC 是 WordPress 老牌接口,几乎所有版本都支持,开箱即用
3. 用 Python 的 python-wordpress-xmlrpc 库,几行代码就能发文章,比 REST API 少写一半代码
4. 批量操作时 XML-RPC 更稳定,不容易被安全插件拦截
有人说 XML-RPC 不安全,容易被打暴力破解。这个确实要注意,后面会说我怎么处理的。
环境准备
我用的是腾讯云轻量应用服务器,2核2G,装了宝塔面板 + WordPress。服务器选腾讯云主要是因为便宜,新用户一年几十块钱就能搞一台,而且备案流程也方便。
如果你还没有服务器,可以先领个优惠券:https://curl.qcloud.com/7Znu7m7b
Python 环境
# 装 python-wordpress-xmlrpc 库
pip install python-wordpress-xmlrpc
这个库是官方推荐的 XML-RPC Python 客户端,封装得很好,不需要自己拼 XML。
确认 XML-RPC 已开启
WordPress 默认是开启 XML-RPC 的,但有些安全插件会把它关掉。访问你的站点:
https://你的域名/xmlrpc.php
如果返回 “XML-RPC server accepts POST requests only.”,说明是开着的。如果返回 403 或 404,那可能是被安全插件拦了,去插件设置里放行。
完整代码:自动发一篇文章
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods.posts import NewPost
连接 WordPress
wp = Client('https://你的域名/xmlrpc.php', '用户名', '密码')
创建文章
post = WordPressPost()
post.title = '测试文章标题'
post.content = '<p>这是文章内容,支持 HTML 标签</p>'
post.post_status = 'publish' # 直接发布,改成 draft 就是草稿
设置分类(用分类 ID,别用名称)
post.terms = [{'id': 6}] # 6 是"自动化运营"分类的 ID
发布
post_id = wp.call(NewPost(post))
print(f'发布成功!文章 ID: {post_id}')
就这么多代码,是不是比想象中简单?
批量发文:从 1 篇到 100 篇
单个发文没啥技术含量,批量发文才是真正要折腾的。我的需求是一次发几十篇文章,还不能被服务器判定为攻击。
批量发布脚本
import time
from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods.posts import NewPost
wp = Client('https://你的域名/xmlrpc.php', '用户名', '密码')
articles = [
{'title': '文章1标题', 'content': '文章1内容', 'category_id': 6},
{'title': '文章2标题', 'content': '文章2内容', 'category_id': 6},
# ... 更多文章
]
success_count = 0
fail_count = 0
for i, article in enumerate(articles):
try:
post = WordPressPost()
post.title = article['title']
post.content = article['content']
post.post_status = 'publish'
post.terms = [{'id': article['category_id']}]
post_id = wp.call(NewPost(post))
print(f'[{i+1}/{len(articles)}] 发布成功: ID {post_id} - {article["title"]}')
success_count += 1
# 每篇间隔 3-5 秒,别太快
time.sleep(3 + (i % 3))
except Exception as e:
print(f'[{i+1}/{len(articles)}] 发布失败: {article["title"]} - {str(e)}')
fail_count += 1
# 失败后等久一点再试
time.sleep(10)
print(f'\n发布完成!成功 {success_count} 篇,失败 {fail_count} 篇')
几个关键点:
1. 每篇之间加 3-5 秒间隔,随机化一下,避免触发限流
2. 失败后等 10 秒再继续,别硬冲
3. 记录成功和失败数量,方便事后检查
踩过的坑
坑1:分类用名称字符串,结果文章全没分类
刚开始我用的是 terms_names 传分类名称:
# 错误写法
post.terms_names = {'category': ['自动化运营']}
结果文章发出来了,但分类全是”未分类”。排查了半天才搞明白,terms_names 在某些 WordPress 版本下有 bug,中文分类名会识别失败。
正确做法是用 terms + 分类 ID:
# 正确写法
post.terms = [{'id': 6}]
怎么查分类 ID?用 XML-RPC 的 wp.getTerms 方法:
from wordpress_xmlrpc.methods.taxonomies import GetTerms
terms = wp.call(GetTerms('category'))
for t in terms:
print(f'ID: {t.id} | 名称: {t.name}')
坑2:SSL 证书验证报错
腾讯云装的免费 SSL 证书,Python 默认会验证证书链,偶尔会报 SSL 验证失败。解决办法:
import ssl
创建不验证 SSL 的上下文(仅开发环境用,生产环境建议修复证书)
ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
Client 初始化时传入
注意:python-wordpress-xmlrpc 底层用 xmlrpc.client,需要这样处理
import xmlrpc.client
transport = xmlrpc.client.SafeTransport(context=ssl_context)
然后用底层方式连接
或者更简单的方式,直接用 Node.js 的 https 模块发 XML-RPC 请求(对,我后来转 Node.js 了,Python 的 SSL 处理太折腾)。
坑3:PowerShell 执行 Node.js 代码时特殊字符炸了
在 Windows 上用 PowerShell 执行 node -e "..." 的方式跑 JS 代码,XML 里的 < > & 引号等字符会被 PowerShell 先解析一遍,然后 Node.js 收到的就是残缺的代码。
解决办法:别用 -e 参数了,把 JS 代码写成 .js 文件再执行:
# 错误:PowerShell 会破坏特殊字符
node -e "const xml = '<?xml version=\"1.0\"?>...'"
正确:写文件再执行
node publish_article.js
这个坑浪费了我好几个小时。
坑4:单引号导致 Python 语法错误
文章内容里有 Let's Encrypt 这种带撇号的字符串,如果用单引号包裹:
content = 'SSL证书:免费Let's Encrypt' # 语法错误!
Python 会把 Let' 后面的 s Encrypt' 当成语法错误。必须用双引号或转义:
content = "SSL证书:免费Let's Encrypt" # 用双引号
content = 'SSL证书:免费Let\'s Encrypt' # 或转义
这种小问题很难排查,因为报错行号不一定准确。
坑5:批量发 100 篇导致文章无分类
有一次批量发了 100 篇文章,全部用的 terms_names,结果所有文章都归到了"未分类"。后来不得不写脚本批量修改分类,又折腾了半天。
教训就是:永远用 terms + 分类 ID,别图省事用 terms_names。
实际效果
我用这套方案跑了一个多月,说说真实数据:
- 批量发文速度:每分钟大约 15-20 篇(加了间隔保护)
- 成功率:99% 以上,偶尔网络波动会失败一篇
- 单篇文章发布耗时:0.5-2 秒
- 对服务器压力:2 核 2G 轻量应用服务器完全扛得住
相比手动在 WordPress 后台一篇篇发,效率提升了至少 50 倍。以前发 50 篇文章要点一整个下午,现在脚本跑 3 分钟搞定。
还有一个意想不到的好处:因为发文节奏稳定(每天定时发 2-3 篇),搜索引擎抓取频率明显提高了。之前一周来一次的百度蜘蛛,现在隔天就来。
Node.js 版本(补充)
后来我主要用 Node.js 做自动发布了,因为 Python 的 SSL 和编码问题在 Windows 上太闹心。Node.js 用 https 模块直接发 XML-RPC 请求,简单粗暴但管用:
const https = require('https');
function publishPost(title, contentHtml, categoryId) {
const xml = <?xml version="1.0" encoding="UTF-8"?>
<methodCall>
<methodName>wp.newPost</methodName>
<params>
<param><value><int>1</int></value></param>
<param><value><string>你的用户名</string></value></param>
<param><value><string>你的密码</string></value></param>
<param><value><struct>
<member><name>post_title</name><value><string>${escapeXml(title)}</string></value></member>
<member><name>post_content</name><value><string>${escapeXml(contentHtml)}</string></value></member>
<member><name>post_status</name><value><string>publish</string></value></member>
<member><name>terms</name><value><array><data>
<value><struct>
<member><name>taxonomy</name><value><string>category</string></value></member>
<member><name>id</name><value><int>${categoryId}</int></value></member>
</struct></value>
</data></array></value></member>
</struct></value></param>
</params>
</methodCall>;
return new Promise((resolve, reject) => {
const req = https.request({
hostname: '你的域名',
path: '/xmlrpc.php',
method: 'POST',
headers: { 'Content-Type': 'text/xml', 'Content-Length': Buffer.byteLength(xml) }
}, res => {
let body = '';
res.on('data', c => body += c);
res.on('end', () => {
const idMatch = body.match(/<name>post_id<\/name>.*?<value>(?:<string>)?(\d+)/);
if (idMatch) resolve(idMatch[1]);
else reject(new Error('发布失败: ' + body.substring(0, 200)));
});
});
req.on('error', reject);
req.write(xml);
req.end();
});
}
function escapeXml(str) {
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}
// 使用
publishPost('测试文章', '<p>这是内容</p>', 6).then(id => console.log('发布成功: ' + id));
Node.js 版本不需要额外装库,直接用内置的 https 模块,而且不用折腾 SSL 证书问题。
安全建议
XML-RPC 确实容易被暴力破解攻击,建议做好防护:
1. 在 Nginx 层面限制 xmlrpc.php 的访问频率
2. 使用强密码(16位以上,含特殊字符)
3. 如果不需要离线发布(如 Windows Live Writer),可以只允许特定 IP 访问 xmlrpc.php
4. 定期检查访问日志,看有没有异常的批量请求
Nginx 限流配置示例:
# 在 http 块中
limit_req_zone $binary_remote_addr zone=xmlrpc:10m rate=30r/m;
在 server 块中
location /xmlrpc.php {
limit_req zone=xmlrpc burst=5 nodelay;
fastcgi_pass unix:/tmp/php-cgi.sock;
# ... 其他 fastcgi 配置
}
这样每分钟最多 30 次请求,正常发文绰绰有余,暴力破解就很难了。
最后
自动发文这事儿,上手不难,但细节真的多。从选接口到处理编码,从 SSL 到批量限流,每一步都可能踩坑。我花了一周时间才把整个流程跑通,希望这篇文章能帮你少走点弯路。
如果你还没买服务器,这里有个腾讯云优惠链接:https://curl.qcloud.com/7Znu7m7b ,新用户价格很划算,我自己的站就是跑在腾讯云上的。
有问题可以留言,我会回复的。关注我,后面还会分享更多自动化运营的实操经验。

