百度主动推送实战:3种方式API+JS+Sitemap
写在前面:3种百度收录通道的本质区别
保哥做SEO这么多年,被问得最多的一个问题就是"为什么我的新页面发布几天了百度还没收录"。其实在百度生态里,等爬虫自己来发现页面是最慢的一种方式,主动推送(过去常说的"主动ping")才是新页面进库最快的渠道。今天这篇文章保哥把主动推送的工作原理、几种实现方式以及踩过的坑都讲一遍,重点放在Windows下使用POST推送工具的具体配置,同时也会给出Linux/Python/PHP/Node.js的等价实现,让不同环境的朋友都能用。
3种推送方式量化对比
保哥见过太多新人把这三个概念搞混。先把它们的本质区别说清楚,后面操作的时候才知道每个工具是在解决哪一类问题。
| 推送方式 | 触发条件 | 抓取速度 | 每日配额 | 适合场景 |
|---|---|---|---|---|
| 主动推送(API) | 站长主动POST调用 | 几分钟到几小时 | 新站100-500,老站5000-50000+ | 新发布内容、紧急收录 |
| 自动推送(JS) | 用户访问页面触发JS | 1到3天 | 无明确上限 | 常规页面被动覆盖 |
| sitemap提交 | 百度按自己节奏抓取 | 3天到2周 | 受文件大小限制(50MB或5万URL) | 历史存量内容兜底 |
| 等爬虫自然发现 | 外链或站内导航 | 1周到3个月 | 不可控 | 没有任何主动推送时 |
保哥的三档配合打法
保哥的实际打法是三个都用,但优先级是主动推送优于自动推送优于sitemap。新发布的内容一定走主动推送,老存量内容用sitemap兜底,自动推送当作备用通道。具体分工:
- 主动推送:每篇新文章发布后立刻调用接口推送一次,配合钩子自动化
- 自动推送:所有页面挂百度提供的JS片段,靠用户访问被动触发
- sitemap:每周生成一次完整sitemap.xml并提交,覆盖全站历史内容
- 外链建设:在权重站做内链推荐,让爬虫"顺路"发现
四档配合后,新文章基本能在2到6小时内进入抓取队列,48小时内被索引的概率超过80%。
主动推送、自动推送、sitemap的本质差异
主动推送(active push)
站长后台给每个站点分配一个唯一的token,你拿这个token加上站点域名拼出一个接口地址,往这个地址POST你的URL列表,百度收到后会立刻进入抓取队列。这是最快的渠道,单条URL通常几分钟内就会被爬虫访问。优点:响应快、可控、可批量。缺点:有每日配额、token泄露有风险、必须由站长主动触发。
自动推送(auto push)
百度给的一段JavaScript代码,你把它放到网站每个页面里,用户访问页面时这段JS会自动把当前URL推送到百度。优点:不用你自己写代码、用户访问即触发。缺点:依赖用户访问,如果一个新页面没人访问就不会被推送;JS执行可能被广告屏蔽工具拦截;速度比主动推送慢。
sitemap提交
站点地图,你把所有URL整理成XML提交给百度,百度按它自己的节奏去抓。这是最慢但最稳定的方式,适合一次性把历史页面全部推上去。优点:一次配置长期生效、能覆盖全站。缺点:抓取节奏百度说了算、新增内容反映慢、文件大小有限制。
在百度站长平台拿到接口调用地址
登录百度搜索资源平台(前身就是百度站长平台),左侧菜单找到"数据引入 -> 链接提交 -> API提交"(部分版本叫"主动推送")。如果你的站点还没在站长平台验证,需要先做验证。
站点验证的3种方式对比
| 验证方式 | 难度 | 稳定性 | 适合场景 |
|---|---|---|---|
| HTML文件验证 | 低 | 最高 | 有FTP/SSH访问权限的所有场景 |
| HTML标签验证 | 低 | 高 | 主题文件可编辑的CMS |
| CNAME验证 | 中 | 低(DNS缓存) | 仅有DNS控制权时 |
保哥个人最推荐HTML文件验证,最稳定,CNAME验证容易因为DNS缓存导致几个小时内验证不通过。
接口地址的标准格式
验证通过以后,在API提交页面会看到一个接口调用地址,格式长这样:
http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx
这里的site参数是你的主域名(不带http、不带尾部斜杠),token是百度给你的密钥。token不能公开,不要贴到博客里,不要发到GitHub公开仓库,不要给任何陌生人看。token一旦泄露,恶意者可以伪造垃圾URL推送到你的站点配额下,把你的每日推送配额刷光,严重的还会导致百度对你站点的信任度下降。
token安全的5条最佳实践
- 本地加密存储:用环境变量或者密码管理器(1Password、Vault)保管,不要写在脚本里硬编码
- 定期重置:每3个月在站长平台主动重置一次token,特别是怀疑泄露时立刻重置
- 限制使用环境:只在固定的服务器或本机使用,不要带出工作环境
- 开启接口日志:记录每次推送的来源IP和URL数量,发现异常调用立即重置
- 分离测试与生产token:测试环境用独立token,生产事故不会污染生产配额
准备URL列表
主动推送一次最多可以提交多少条URL,要看你站点的每日推送配额。配额由百度根据站点质量动态计算。
不同站点规模的典型配额
| 站点阶段 | 每日配额 | 建议推送策略 |
|---|---|---|
| 新站点(建站3个月内) | 100到500条 | 每天分批推送,保留50%余量 |
| 中等站点(10到100万PV) | 1000到5000条 | 新文章实时推、归档每周补推 |
| 大型站点(100万PV+) | 5000到50000+条 | 新文章实时推、可建批量推送队列 |
| 资讯类站点(更新极快) | 申请后可达数十万 | 对接消息队列实时推送 |
URL文件格式与3个关键陷阱
URL列表的格式很简单,一行一个完整URL,保存为纯文本文件,编码UTF-8无BOM。但保哥见过3个反复出现的陷阱:
- UTF-8 BOM污染:用记事本默认保存会带一个BOM字节,推送接口返回success但实际上第一条URL永远进不了队列,就是因为那个BOM把URL头部污染了。Windows下推荐用Notepad++或者VSCode保存,编码栏里明确选"UTF-8 without BOM"
- 协议不一致:URL里的协议要和站长平台验证时填的一致,如果你验证的是https站点,URL列表里就不能写http
- 重复URL:不要把同一个URL重复推送,配额会被算两次但实际上百度只会处理一次,纯属浪费
URL去重与排序的小技巧
把URL列表预处理一下,能更高效用配额:
# Linux 一行去重并排序
sort -u urls.txt > urls_clean.txt
# PowerShell 等效
Get-Content urls.txt | Sort-Object -Unique | Set-Content urls_clean.txt
# Python 等效
seen = set()
clean = []
with open('urls.txt') as f:
for line in f:
u = line.strip()
if u and u not in seen:
seen.add(u)
clean.append(u)
open('urls_clean.txt', 'w').write('\n'.join(clean))
使用百度POST实时推送工具(Windows GUI方案)
百度POST实时推送工具是早些年第三方开发者做的一个Windows桌面工具,至今还在很多老站长的工具箱里。保哥个人也用过,配置简单,适合不会写代码的朋友。
详细操作步骤
- 下载解压后会看到主程序exe和一个"网址.txt"
- 把准备好的URL列表全部贴到"网址.txt"里保存(UTF-8无BOM)
- 打开主程序,界面有两个输入框
- 第一个输入框"接口调用地址":粘贴从百度站长平台拿到的完整地址(含site和token参数)
- 第二个输入框"实时推送文件":点旁边的"打开"按钮,选择"网址.txt"
- 点"开始推送",工具会逐行读取URL并POST到接口
正常返回与错误返回的识别
正常情况下你会看到一条返回:
{
"remain": 4982,
"success": 18
}
remain是当天剩余配额,success是本次成功推送的条数。如果看到下面这些字段,说明部分URL有问题:
| 返回字段 | 含义 | 处理方法 |
|---|---|---|
| not_same_site | URL域名与site参数不匹配 | 检查URL列表,剔除外部链接 |
| not_valid | URL格式不合法(如缺协议头) | 补全http或https前缀 |
| error 400 | token无效或过期 | 到站长平台重新复制token |
| error 401 | 未授权(site或token错) | 核对site参数与token配对 |
| error 403 | 当日配额已用完 | 等明日0点重置,或申请提升 |
GUI工具的限制
这个工具还有一个保哥比较喜欢的功能,就是可以挂在Windows服务器上做定时自动推送。配合一个简单的正则规则,让它定期扫描你网站的新URL(比如从sitemap.xml解析),扫到新的就推送。但这个功能依赖工具内置的正则匹配能力,规则写错了会漏推或者重复推,保哥实际部署的时候宁愿用脚本替代。
用脚本替代GUI工具(推荐方案)
保哥这几年管理的站点越来越多,桌面GUI工具已经不够用了。现在100%用脚本做主动推送,下面给五种语言的实现,挑你顺手的用。
Python版本(最简洁)
import requests
API = "http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx"
with open("urls.txt", "r", encoding="utf-8") as f:
urls = [line.strip() for line in f if line.strip()]
body = "\n".join(urls)
resp = requests.post(
API,
data=body.encode("utf-8"),
headers={"Content-Type": "text/plain"},
timeout=15,
)
print(resp.status_code, resp.json())
Linux Shell(crontab首选)
#!/bin/bash
API="http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx"
curl -H 'Content-Type:text/plain' --data-binary @urls.txt "$API"
# crontab 每小时跑一次
# 0 * * * * /usr/local/bin/baidu_push.sh >> /var/log/baidu_push.log 2>&1
PHP版本(Typecho/WordPress钩子)
function baidu_push($urls) {
$api = 'http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, implode("\n", $urls));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/plain']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$result = curl_exec($ch);
curl_close($ch);
return json_decode($result, true);
}
// Typecho 钩子:发布文章后自动推送
Typecho_Plugin::factory('Widget_Contents_Post_Edit')->finishPublish = function($cid){
$post = Helper::widgetById('Contents', $cid);
baidu_push([$post->permalink]);
};
Node.js版本(异步友好)
const fs = require('fs');
const axios = require('axios');
const API = 'http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx';
async function baiduPush() {
const urls = fs.readFileSync('urls.txt', 'utf-8')
.split('\n').map(s => s.trim()).filter(Boolean);
const body = urls.join('\n');
const resp = await axios.post(API, body, {
headers: { 'Content-Type': 'text/plain' },
timeout: 15000,
});
console.log(resp.status, resp.data);
}
baiduPush();
Go版本(高并发场景)
package main
import (
"bytes"
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
api := "http://data.zz.baidu.com/urls?site=zhangwenbao.com&token=xxxxxxxx"
data, _ := os.ReadFile("urls.txt")
lines := strings.Split(string(data), "\n")
body := strings.Join(lines, "\n")
resp, _ := http.Post(api, "text/plain", bytes.NewBufferString(body))
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(out))
}
保哥自己的Typecho站点用的就是PHP版本,挂在Typecho_Plugin::factory('Widget_Contents_Post_Edit')->finishPublish钩子上,文章一发布马上推送,几乎不会延迟。
5个典型生产场景的推送策略
场景一:个人博客(每日0到3篇新内容)
用PHP钩子挂在CMS发布动作上,每篇文章发布后立即推送一次。配额完全够用,不需要批量。
场景二:企业新闻站(每日10到50篇)
实时推送 + 每天凌晨0点重新推送当天发布的所有文章(兜底)。后者用Shell脚本配合crontab,从数据库SELECT前24小时发布的URL列表批量推送。
场景三:电商商品站(每日数百到上千SKU上新)
实时推送 + 每小时批量推送。考虑到电商URL变动频繁(价格、库存变更),增加一个"重要变更触发再推送"的逻辑。配额吃紧时优先推送有价格变动或新评价的商品页。
场景四:UGC内容站(每分钟数十条新内容)
对接消息队列(Redis、Kafka),每条新内容入队后异步推送。批量推送,每次合并100到1000条URL发送一次,降低API调用次数。
场景五:聚合资讯站(爬虫抓取后入库)
抓取入库后立即推送,但要注意百度对"批量推送他站内容"的容忍度很低,所有抓取来的内容必须做改写或聚合分析,否则反而降权。这类站点保哥建议同时投入到自动推送和sitemap,分散风险。
推送之后怎么验证效果
推送成功不等于收录成功,这是两个完全不同的事。保哥的验证流程是:
验证一:API返回字段
看接口返回的success字段是否等于你提交的URL数。如果不等,说明部分URL被过滤了,需要查not_same_site和not_valid字段。这一步是推送有效性验证,不是收录验证。
验证二:site语法查询
过24到48小时,到百度搜索框里输入site:你的域名 关键词,看新页面是否已经能被搜出来。如果搜不到,可能是页面本身质量问题(内容太短、和已有页面雷同度高、没有外链支持),不是推送的问题。
验证三:抓取频次趋势
登录百度站长平台,"数据统计 -> 抓取频次",看推送后两三天内爬虫访问频次是否上升。如果完全没上升,说明你的推送可能根本没生效,要回头查token和接口地址。
验证四:服务器日志反查
看Nginx或Apache的access_log,搜索User-Agent包含Baiduspider的请求,确认推送后24小时内是否有百度爬虫访问对应URL:
grep 'Baiduspider' /var/log/nginx/access.log \
| grep '推送的URL路径' | tail -20
保哥的经验是,推送后70%的页面会在48小时内被抓取,但抓取不等于收录。被抓取后页面是否进入索引库,取决于内容质量和站点整体权重。所以主动推送解决的是"被发现"的问题,不解决"被收录"的问题,后者需要长期内容运营来支持。
配额耗尽以后的应急策略
保哥处理过几次配额耗尽的紧急情况,分享下应急策略。
策略一:等次日重置
配额是按自然日重置的,凌晨0点重新计数。所以如果今天的配额用完了,明天0点以后再推剩下的。注意以北京时间为准,不是UTC。
策略二:申请提升配额
如果你的内容更新量长期超过配额,在站长平台"数据引入"里提交一份申请说明,描述你的站点规模和内容更新频率。配额本质上是百度对站点信任度的量化体现,质量上去了配额会自动涨。申请通过率约30到50%,提供详细的内容质量数据(独立访客、停留时长)能提高通过率。
策略三:兜底通道补救
保哥还有一个野路子,就是把超出配额的URL同时通过自动推送(JS代码)和sitemap两个渠道兜底,效果虽然不如主动推送,但聊胜于无。具体做法:把今天没推完的URL列表,对应的页面在文档底部插入一段JS——访问者打开就触发自动推送;同时这些URL进入下一周期的sitemap.xml里。
策略四:错峰推送
把高优先级URL放在配额刚重置的凌晨0到6点推送,低优先级的放到白天。这样即使配额吃紧,重要内容也能优先进入抓取队列。
3个真实踩坑案例
案例一:UTF-8 BOM导致首条URL永远没推上
某客户用记事本编辑urls.txt,每次保存默认带BOM。脚本读出第一行URL时BOM被当成URL一部分,百度服务端解析为不合法URL丢弃,但因为是格式错误不计入not_valid计数,看起来success=N但实际上只有N-1条入队列。修复:用Notepad++保存时明确选UTF-8无BOM;或者脚本读文件时用open('urls.txt', encoding='utf-8-sig')自动剥BOM。教训:编码细节会吞掉静默错误,必须用日志+服务器log双重验证。
案例二:token硬编码进GitHub仓库被刷爆配额
某客户把推送脚本提交到GitHub公开仓库,token明文写在脚本里。第二天发现配额被刷光,错误日志显示大量陌生IP的POST请求。修复:立即在站长平台重置token、清理GitHub历史(用git filter-branch彻底删除)、把token改为环境变量。教训:任何API凭据绝对不能进版本控制,连私有仓库也不要写,用环境变量或密钥管理服务。
案例三:URL协议不一致导致全部not_same_site
客户站点全站HTTPS,但urls.txt里URL都是http://开头(沿用了多年前的列表)。每次推送返回success=0,全部进入not_same_site。修复:批量替换URL列表里的http为https,建立预检脚本在推送前验证URL协议与站点验证一致。教训:CMS升级HTTPS后所有外发推送链路都要重新验证一遍,不要假设旧脚本还能用。
常见问题解答
主动推送的接口需要HTTPS吗?
保哥实际测试过,data.zz.baidu.com同时支持http和https,两种都能用。但保哥个人推荐https,避免token在传输过程中被中间人截获。把接口地址里的http改成https即可,业务上没有任何差异,只是传输层加密。如果你的服务器在公网代理环境下(很多企业网通过代理上网),强制https还能避免代理记录明文token的风险。
可以把多个站点的URL放在同一个文件里推送吗?
不可以。每个站点的token都是独立的,接口地址里site参数也只能写一个域名。如果一个URL不属于这个site,会被not_same_site过滤。多站点推送的话需要为每个站点单独配置一份接口地址和URL列表,分别调用。可以用一个统一的脚本,按站点名分别加载token和URL列表分批推送,但API调用必须分开。
推送的URL是不是越多越好?
不是。保哥见过有人为了刷配额,把每个URL加上无意义的query参数推送N次,比如加问号v等于1、问号v等于2这种,这种做法百度后端会识别为伪造,不仅当次推送无效,还可能被降权。每个URL推送一次就够了,重要内容可以三五天后再补推一次,不要密集重推。如果一定要重推(比如内容做了重大更新),把?refresh=日期戳写到URL里作为版本标识,但要确保对应URL在站点上真的能访问到。
用第三方工具推送会不会被百度判作弊?
保哥的回答是不会,前提是你推送的内容是你自己站点的真实内容、URL没有伪造、不超过配额。百度只关心内容质量和token合法性,不关心你用什么工具推送。但如果工具本身有问题,比如token被工具开发者收集后用于推送其他站点,那就是另一回事了。所以选工具的时候要选信誉好的,或者干脆自己写脚本最安全。开源工具优于闭源工具,能审计代码最稳。
主动推送和Bing IndexNow可以同时用吗?
可以而且推荐。两者面向的搜索引擎不同——主动推送是百度专用,IndexNow是Bing、Yandex、Seznam等支持的协议,互不冲突。保哥的Typecho站点同时挂了百度推送插件和BingIndexNow插件,文章发布后两个通道并行触发。具体配置:百度按本文方法,IndexNow用zhangwenbao.com目前装的BingIndexNow插件即可,每个搜索引擎各推一次。
推送了一周但site语法还是搜不到,怎么排查?
分四步:第一确认推送有效(API返回success大于0、抓取频次有上升);第二用Search Console的"URL检查"或百度站长的"抓取诊断"工具单条URL测试抓取,看能否抓到200状态码与正常HTML;第三检查页面是否有noindex标记或robots.txt屏蔽;第四对比同站点已收录页面与未收录页面的差异,常见原因是内容过短(少于500字)、模板雷同度过高、缺少首屏关键词。如果四步都通过仍未收录,可能是站点整体权重不足,需要长期内容运营累积。
站点改版后推送是否需要重新配置?
看改了什么。如果只是模板换皮、URL规则不变,token可以继续用。如果改了URL结构(比如从id变slug),需要做三件事:第一把所有新URL重新生成sitemap并提交;第二把新URL的列表通过主动推送一次性提交;第三在旧URL上加301跳转到新URL,让百度更新索引。任何URL结构变更必须配合301跳转,否则会丢失原有排名。
有没有办法批量监控多个站点的推送状态?
百度站长平台目前不提供批量API,只能逐站登录后台查看。保哥的做法是自己写一个汇总脚本:每天定时调用各站点的http://data.zz.baidu.com/urls接口,从返回的remain字段反推已用配额,存入本地数据库做趋势分析。配合Grafana面板,能直观看到所有站点的每日推送量、配额使用率、错误率。这套监控对站群运营特别有用,单站点没必要。
写在最后
以上就是保哥多年使用百度主动推送的全部经验。SEO这件事没有银弹,主动推送只是缩短了百度发现新页面的时间窗口,真正决定排名的还是内容本身的价值和站点整体权重。先把内容做好,再让推送工具去做它该做的事,顺序不能反。
保哥的建议是:新站期重点用主动推送加快入库速度;中期建立"主动推送+自动推送+sitemap"三档配合的标准流程;长期则把精力放回内容质量,让推送变成习惯性动作而不是焦虑来源。每天看看抓取频次曲线、收录率、配额使用率三个指标就够了,不需要天天盯着推送脚本。
因本文不是用Markdown格式的编辑器书写的,转换的页面可能不符合AMP标准。