先说结论:不是推送失败,是推送压根没发生。 我的发布脚本直连数据库写文章,WordPress 的发布钩子一个都没触发,挂在钩子上的百度推送自然一次都没跑。
事情是 9 月 29 日晚上暴露的。那晚连发两篇积压的文章。自检 17 项全绿,独立验证也全过:页面 200、robots 标签恰好一个、内链和配图全部可访问。最后顺手查了一步推送记录 —— 推送插件每推一次,都会往 postmeta 的 _zz_baidu_push 落一条账。
查出来是空的。
六篇全查了一遍
两篇新的没记录,那之前的呢?我把库里六篇全翻了一遍:
| 文章 ID | _zz_baidu_push 记录 |
|---|---|
| 10 / 18 / 34 / 43 / 46 | 无 |
| 40 | 有一条,当天上午 08:51 |
翻到 40 那条才发现,它也不是发布时推的 —— 那天上午我测推送功能,手动触发过一次,记录是那时候留下的。也就是说:脚本发的六篇,发布动作真正触发的推送次数,是零。

最讽刺的是 43 那篇,写的就是《WordPress 自动提交百度:我配了半年,其实一直失败》。它自己发布时,同样一声没吭地没推。
根因:SQL 绕过了 wp_insert_post()
我的发布脚本图省事,直接拼 SQL 往 wp_posts 表里 INSERT。可 WordPress 的"发布"不是一条 INSERT 语句 —— wp_insert_post() 里挂着一串钩子,publish_post 就在其中,推送插件整个挂在它上面。

后台发文走 wp_insert_post(),钩子触发,推送执行。脚本发文绕过这一切 —— 没有报错,没有失败,什么都没有。17 项校验也拦不住,因为那些项查的全是"文章本身对不对",没有一项查"发布这个动作的副作用发生了没"。
推送功能本身那天上午刚验证过,是通的。坏的只是接线。
把推送显式补回去
插件不用动,要补的是脚本:校验通过后,显式调一次插件里的推送函数,推完再查一次账 —— 没落记录就当失败:
zz_baidu_push($id, $post); // 复用插件:发请求、拿响应、落账、失败重试
$r = get_post_meta($id, "_zz_baidu_push", true);
// 查完账才敢说成功
再给脚本加个补推模式,把六篇历史文章的 slug 依次丢进去:
python publish_article.py --post wordpress-baidu-auto-push --push
python publish_article.py --post python-cjk-font-pitfalls --push
python publish_article.py --post wordpress-launch-checklist --push
python publish_article.py --post ssl-cert-renewal-403 --push
python publish_article.py --post nginx-return-server-vs-location --push
五条真实记录。百度服务端报的剩余配额一路递减:6 → 5 → 4 → 3 → 2。当晚日志里有这么一行:
[23:14:53] [ OK ] 已推送百度:成功(剩余配额 5)
remain 是百度扣的,本地做不了假。这条递减链就是补推真实发生的证据。

直连数据库之前,先问跳过了谁
这件事最坑的不是 bug 本身,是它不报错。页面正常、文章正常、校验全绿,唯一的异常是一条"根本不存在的记录"。要不是顺手查了推送状态,这个坑到现在还埋着。
所以我给自己立了条规矩:任何直连数据库的写入,先问一句"我跳过了哪些钩子"。 缓存刷新、sitemap、通知、统计、第三方推送,全挂在钩子上,跳过了就静默失效。钩子里具体还挂着什么,我没深究,但默认它挂着东西,比默认它没有安全。
推送修好只解决"通知百度"这一层,百度来不来抓是另一层 —— 上次抓取体检查过,蜘蛛也得按 IP 段验真伪。推送这条线上的坑我写过两篇:site 参数配错半年的那回,和自己写插件时踩的钩子与缓存。加上这篇,这条线上已经三个坑连着排,个个都安静得像没发生过。