让百度快速收录:WordPress 主动推送 + IndexNow 实战配置

前言:新站最痛的不是写得差,是百度压根不知道你写了

很多人做站的第一反应是「内容不够好」,于是拼命改标题、加关键词、调排版。但真实情况往往是另一回事:文章早就发布了,搜索引擎根本没来过。

尤其是新站、或者更新不频繁的站,蜘蛛来的间隔可能是几天甚至几周。你写了一篇自认为不错的教程,它在你自己的服务器上躺了半个月,百度索引里查不到,搜索域名全称都搜不出来。

解决这件事有三条路,成本从低到高,效果也从弱到强。

一、三条路:sitemap、主动推送、IndexNow

方式 原理 生效速度 成本
sitemap 把全站链接列成一个 XML,等蜘蛛自己来取 慢,取决于蜘蛛来访频率 最低,插件自动生成
百度主动推送 文章一发布,立刻用 API 把这条 URL 推给百度 快,通常几分钟到几小时 中,需要一个 token
IndexNow 推一次,同时通知 Bing、Yandex、Seznam 等多个引擎 最快,Bing 常常秒收 低,只需一个 key 文件

三者不冲突,建议同时开:sitemap 兜底,主动推送解决百度,IndexNow 解决 Bing 系。

二、百度主动推送:从申请 token 到第一次推送

1. 拿到 token

进百度站长平台 → 找到你的站点 → 资源提交 → 主动推送 → 接口调用地址,长这样:

http://data.zz.baidu.com/urls?site=www.511yj.com&token=你的token

这个地址里 site 是域名,token 是你的密钥。token 不要写进公开文章或提交到代码仓库。

2. 接口格式(极简单,但有两个硬性要求)

<code>POST /urls?site=www.511yj.com&amp;token=xxx HTTP/1.1
Content-Type: text/plain
 
https://www.511yj.com/a.html
https://www.511yj.com/b.html</code>

两个容易踩的点:

  • 请求体是纯文本,一行一个 URL,不是 JSON
  • Content-Type 必须是 text/plain,用 JSON 提交会返回「数据格式错误」

返回里 success 是本次成功条数,remain 是当天剩余配额。新站配额一般够用,不用太担心。同一个 URL 当天重复推,只算一次。

3. 挂到发布动作上

<code>add_action('transition_post_status', function($new, $old, $post){
    if ($new !== 'publish' || $old === 'publish') return;
    if ($post-&gt;post_type !== 'post') return;
 
    $api  = 'http://data.zz.baidu.com/urls?site=www.511yj.com&amp;token=xxx';
    $body = get_permalink($post-&gt;ID);
 
    $res = wp_remote_post($api, [
        'timeout' =&gt; 15,
        'headers' =&gt; ['Content-Type' =&gt; 'text/plain'],
        'body'    =&gt; $body,
    ]);
 
    if (!is_wp_error($res)) {
        update_post_meta($post-&gt;ID, '_baidu_push_result', wp_remote_retrieve_body($res));
    }
}, 10, 3);</code>

用 transition_post_status 而不是 save_post,是因为它只在状态真正变成 publish 时触发,草稿保存、自动保存都不会误推。

三、最阴的一种失败:curl 没加载,推送「成功」其实是假的

这一段是整篇文章最值得看的部分,因为它没有任何报错。

WordPress 的 wp_remote_post() 是个双通道设计:curl 扩展可用就走 curl,不可用就降级到 WP_Http_Streams。听起来很稳,但在某些服务器上,stream 通道会因为 allow_url_fopen 关闭或 SSL 配置缺失而静默失败——请求根本没发出去,函数照样返回一个结构完整的结果。

于是你在后台看到「推送完成」,日志里干干净净,百度那边一条都没收到。

先确认一件事,在服务器上跑:

<code>C:\xampp\php\php.exe -r "var_dump(extension_loaded('curl'));"</code>

输出 bool(false) 的话,先去把 curl 修好再谈推送。

相关阅读:Windows Server 2012 R2 下 XAMPP PHP 8.3 的 curl 扩展修复实录——那篇讲了 DLL 依赖链断裂导致扩展静默不加载的完整排查过程,是本文这个坑的前置条件。

推送代码里也可以加一道保险,把失败显性化:

<code>if (is_wp_error($res)) {
    error_log('[baidu-push] ' . $res-&gt;get_error_message());
    return;
}
 
$code = wp_remote_retrieve_response_code($res);
if ($code !== 200) {
    error_log('[baidu-push] HTTP ' . $code . ' ' . wp_remote_retrieve_body($res));
}</code>

四、修好 curl 反而报错:error 60 到底是谁的锅

很多人是在这一步放弃的:按教程下载了 cacert.pem,配好了 curl.cainfo,重启,然后推送报:

cURL error 60: SSL certificate problem:
unable to get local issuer certificate

第一反应通常是「证书包不对」或者「我配错了」,于是换证书、改路径、甚至直接关掉校验。但在动手之前,应该先做一个判断:到底是你这边的问题,还是对方的问题。

用「对照组」定位,别猜

做法很简单:拿同一个证书包,去访问另外两个确定正常的 HTTPS 站点。

<code>add_action('admin_init', function(){
    if (!isset($_GET['ssl-probe'])) return;
 
    $targets = [
        '微信 API'  =&gt; 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential',
        '公网 IP'   =&gt; 'https://api.ipify.org',
        '百度推送'  =&gt; 'http://data.zz.baidu.com/urls?site=www.511yj.com&amp;token=xxx',
    ];
 
    foreach ($targets as $name =&gt; $url) {
        $r = wp_remote_get($url, ['timeout' =&gt; 15]);
        echo $name . ' =&gt; ' . (is_wp_error($r) ? $r-&gt;get_error_message() : 'HTTP ' . wp_remote_retrieve_response_code($r)) . '&lt;br&gt;';
    }
    exit;
});</code>

结果怎么读:

现象 结论
三个全失败 你的问题——证书包路径错、文件损坏,或 curl 没加载
微信和 IP 成功,只有百度失败 百度端的问题——它的证书链/主机名配置有问题,跟你的证书包无关

第二种情况真实存在。data.zz.baidu.com 在某些网络环境下返回的证书,其主机名与访问域名不匹配,而 PHP 的 curl 在严格校验模式下会直接拒绝。浏览器能打开是因为浏览器有额外的容错和补全机制,服务器端的 curl 没有。

原则是:可以降级,但不能静默

遇到对方证书有问题,正确做法不是全局关掉校验——那会把所有 HTTPS 请求都暴露在风险里,而且将来你自己的站点真出问题也发现不了。

应该只在确认是 SSL/证书类错误时才跳过校验,并且明确标记:

<code>$res = wp_remote_post($api, $args);
 
if (is_wp_error($res)) {
    $msg = $res-&gt;get_error_message();
 
    // 只有 SSL 类错误才降级,403/429 等绝不能降级
    if (stripos($msg, 'SSL') !== false || stripos($msg, 'certificate') !== false) {
        $args['sslverify'] = false;
        $res = wp_remote_post($api, $args);
 
        if (!is_wp_error($res)) {
            $res['_noverify'] = true;   // 必须留痕
        }
    }
}</code>

关键点:403(token 错)、429(配额超限)这类错误绝对不能降级——它们是真实的业务错误,跳过校验只会让你误以为推成功了。

五、IndexNow:一次推送,多个引擎

IndexNow 是微软和 Yandex 推的开放协议,逻辑极简单:你告诉任何一个参与的搜索引擎「这个 URL 变了」,它会把消息广播给其他参与者。目前 Bing、Yandex、Seznam、Naver 都支持。

1. 生成 key 并放成文件

key 是你自己随便定的一串字符,要求是 8-128 位的十六进制字符(a-f, 0-9)。比如可以用随机生成:

$key = bin2hex(random_bytes(16));   // 32 位,合法

然后在网站根目录放一个纯文本文件 key.txt,内容就只有这一串 key,不能有多余空格或换行。

验证:https://www.511yj.com/key.txt 应该直接显示那串字符。

2. 推送请求

<code>{
  "host": "www.511yj.com",
  "key": "你的key",
  "keyLocation": "https://www.511yj.com/key.txt",
  "urlList": [
    "https://www.511yj.com/a.html",
    "https://www.511yj.com/b.html"
  ]
}</code>
$res = wp_remote_post('https://api.indexnow.org/indexnow', [
    'timeout' => 20,
    'headers' => ['Content-Type' => 'application/json; charset=utf-8'],
    'body'    => wp_json_encode($payload),
]);

3. 403 的头号原因:两处 key 对不上

IndexNow 返回 403,九成是因为服务器上的 key.txt 内容,和你在插件里填的、请求里发的 key 不一致。

这不是什么玄学。常见成因:

  • 改过 key,但忘了重新上传 key.txt
  • key.txt 尾部多了个换行(很多编辑器默认会加)
  • 插件设置里填的时候复制漏了字符

所以自检功能必须有,而且必须是真的去 HTTP 请求一次并比对内容,不是检查文件存不存在:

<code>$r = wp_remote_get($key_location, ['timeout' =&gt; 15]);
$code = wp_remote_retrieve_response_code($r);
$body = trim(wp_remote_retrieve_body($r));
 
if ($code !== 200) {
    return 'key.txt 无法访问(HTTP ' . $code . ')';
}
if ($body !== $key) {
    return 'key.txt 内容与设置不一致:文件里是 ' . $body . ',设置里是 ' . $key;
}
return 'key 验证通过';</code>

六、一个能长期用的推送插件,该有什么设计

把代码挂到 transition_post_status 上只是起点。真要长期用,下面这些是必需的。

设计点 为什么需要
推送日志 没有日志就只能靠「猜」。记录 URL、时间、HTTP 码、返回内容
失败重试 网络抖动很常见,一次失败不该就此丢掉
SSL 失败记忆 确认校验不过的机器,12 小时内直接走降级,省掉注定失败的握手
跳过密码保护文章 搜索引擎抓不到,推了没意义
日志自动清理 批量推一次能写几千行,不清理会撑大数据库
删除文章时清日志 不留指向已不存在页面的记录
超时设 20 秒 发布文章时不能干等,超过就放弃本次

尤其「日志」这一项,没有它,前面所有问题你都发现不了。

七、避坑清单

坑 说明
curl 没加载就配推送 顺序反了。此时推送可能静默失败,先把扩展修好
用 JSON 提交百度接口 必须 text/plain,一行一个 URL
token 写进公开代码 等于把推送权限交出去
遇到 error 60 就全局关校验 先做对照组判断是谁的问题,降级也要留痕
403 也去降级 403 是真实的业务错误,降级只会掩盖问题
key.txt 多了换行 IndexNow 403 的头号成因。用 trim 比对
改了 key 没换文件 两处必须完全一致
没有日志 出问题只能靠猜,无法回溯

八、怎么确认真的推成功了

三个层次的验证,从快到慢:

  1. 看接口返回:百度返回 success:1,IndexNow 返回 200,这一步最及时
  2. 看插件日志:确认 URL、时间、状态码都记下来了,不是空白
  3. 搜索引擎验证:百度站长平台查「索引量」,Bing 用 site:域名 搜索,通常需要几小时到几天

如果前两步都正常、第三步几天后仍无变化,那问题就不在推送了——通常是内容质量、站点权重或 robots 配置的问题,得换方向查。

写在最后

主动推送这件事,技术上不复杂,难的是它失败的时候经常不报错。curl 没加载会静默失败,stream 通道不通会静默失败,对方证书有问题会让你误以为是自己配错了。

所以真正值钱的不是那几行推送代码,而是配套的日志、对照组判断和失败留痕。有了这些,出问题你能在五分钟内定位;没有,就只能像本文第三节那样,白白等上两周才发现一条都没推成功。

分享到:

用微信扫一扫,分享给朋友


发布日期:

所属分类: SEO 网站运营 标签:  



下一篇:

没有了,已经是最新文章