新文章一周不收录?百度主动推送 + IndexNow + sitemap 分片三通道自动化实战

为什么新文章迟迟不收录:主动推送的三条通道

个人站长最焦虑的事之一,就是文章发出去一周了,site 查询还是零。被动等搜索引擎爬,在内容更新频繁的站点上越来越不灵——爬虫的抓取预算是有限的,一篇文章发布后如果没有外部信号刺激,很可能要等很久才被排进队列。本文讲三种主动推送手段的实战配置:百度站长平台的主动推送 API、IndexNow 协议,以及站点地图分片与更新通知,并给出一个可以挂在 cron 上的自动化脚本。

先检查基础:爬虫到底能不能进来

推送之前,先确保爬虫没有被挡住,否则推了也是白推。三个检查动作:

# 1. robots.txt 是否误封了关键目录
curl -s https://example.com/robots.txt

# 2. 模拟百度爬虫 UA 访问首页
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" https://example.com/

# 3. 模拟 Googlebot
curl -s -o /dev/null -w "%{http_code}\n" -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.com/

返回 200 才算通。如果返回 403 或 503,多半是 WAF、CDN 的爬虫规则或者 Nginx 的 UA 黑名单挡的。另外注意检查是否不小心在 robots.txt 里写了 Disallow: / 又在后面想放行——robots 的规则是"最长匹配优先",写反了很常见。

通道一:百度主动推送 API

百度站长平台(ziyuan.baidu.com)的"普通收录 - API 提交"是最直接的通道。在平台上验证站点后,拿到一个形如 http://data.zz.baidu.com/urls?site=https://example.com&token=XXXXXXXX 的推送地址。

推送注意三点:单次最多提交 2000 条 URL;每天有配额限制(新站通常很少,随收录增长);返回体里 success 是实际接收数,remain 是当天剩余配额。

curl -H 'Content-Type: text/plain' \
  --data-binary @new_urls.txt \
  "http://data.zz.baidu.com/urls?site=https://example.com&token=YOUR_TOKEN"

# 返回示例
# {"remain":2958,"success":42}

new_urls.txt 每行一个完整 URL,不要带 BOM,不要有空行。如果返回 {"error":401,"message":"token is not valid"},检查 token 是否过期或复制时多了空格。

通道二:IndexNow 协议

IndexNow 是 Bing 和 Yandex 主导的开放协议,提交一次,参与的搜索引擎共享结果。它比百度的接口更简单,只需要一个 key 文件放在站点根目录做所有权验证。

第一步,生成一个 key(32 位十六进制即可):

KEY=$(openssl rand -hex 16)
echo "$KEY"
# 例如输出 3f8a9c1e7b2d4f6a8c0e5b7d9f1a3c5e

第二步,把 key 内容写成同名的 txt 文件,放到根目录并能公开访问:

echo "$KEY" > /www/wwwroot/example.com/${KEY}.txt
curl -s https://example.com/${KEY}.txt
# 必须原样返回 key 字符串

第三步,推送 URL:

curl -s -X POST "https://api.indexnow.org/indexnow" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
    "host": "example.com",
    "key": "'"$KEY"'",
    "keyLocation": "https://example.com/'"$KEY"'.txt",
    "urlList": [
      "https://example.com/1234.html",
      "https://example.com/1235.html"
    ]
  }'

返回 200 或 202 即表示接收成功。常见的坑:host 不要带 https:// 前缀;keyLocation 必须能公开访问且内容与 key 完全一致;单次最多 10000 条。

通道三:站点地图分片与 lastmod

sitemap 不只是给爬虫一份目录,它的 lastmod 是爬虫判断"哪些页面值得重新抓"的重要信号。很多站点的 sitemap 是一片死数据:所有 URL 的 lastmod 都是建站日期,爬虫来几次就失去信任了。

正确做法是每次内容更新时同步刷新对应条目的 lastmod。Typecho 站点可以用一条 SQL 导出:

SELECT CONCAT(
  '  <url><loc>https://example.com/', cid, '.html</loc>',
  '<lastmod>', DATE_FORMAT(FROM_UNIXTIME(modified), '%Y-%m-%d'), '</lastmod>',
  '<changefreq>weekly</changefreq><priority>0.8</priority></url>'
) AS entry
FROM typecho_contents
WHERE type='post' AND status='publish'
ORDER BY modified DESC;

当文章超过 5 万条时,需要分片:主 sitemap 只放 <sitemap> 索引,指向 sitemap1.xml、sitemap2.xml 等子文件,每个子文件不超过 5 万条。分片有个容易忽略的约束:同一分片的 URL 必须属于同一站点,且索引文件里每个 <loc> 都要指向可访问的子文件。

更新之后,别忘了在 robots.txt 里声明:

Sitemap: https://example.com/sitemap.xml

把三件事合成一个自动化脚本

手动推送不现实,把它挂到文章发布后的钩子里。下面这个脚本读取最近 N 分钟发布并修改的文章,依次走百度与 IndexNow 两条通道,并统一记录日志:

#!/bin/bash
# /root/push_urls.sh —— 推送最近 30 分钟内变更的文章
set -euo pipefail

SITE="https://example.com"
BAIDU_TOKEN="YOUR_BAIDU_TOKEN"
INDEXNOW_KEY="3f8a9c1e7b2d4f6a8c0e5b7d9f1a3c5e"
DB_PASS="YOUR_DB_PASS"
LOG=/var/log/push_urls.log

# 1) 从数据库取最近 30 分钟修改的文章 cid
CIDS=$(mysql -uroot -p"$DB_PASS" zz1984 -N -B -e \
  "SELECT cid FROM typecho_contents WHERE type='post' AND status='publish' \
   AND modified > UNIX_TIMESTAMP() - 1800;")

[ -z "$CIDS" ] && { echo "$(date) no new posts" >> "$LOG"; exit 0; }

# 2) 生成 URL 列表
> /tmp/push_urls.txt
for cid in $CIDS; do echo "${SITE}/${cid}.html" >> /tmp/push_urls.txt; done

# 3) 百度推送
curl -s -H 'Content-Type: text/plain' --data-binary @/tmp/push_urls.txt \
  "http://data.zz.baidu.com/urls?site=${SITE}&token=${BAIDU_TOKEN}" >> "$LOG" 2>&1

# 4) IndexNow 推送
JSON_URLS=$(paste -sd, /tmp/push_urls.txt | sed 's|[^,]*|"&"|g')
curl -s -X POST "https://api.indexnow.org/indexnow" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d "{\"host\":\"example.com\",\"key\":\"${INDEXNOW_KEY}\",
       \"keyLocation\":\"${SITE}/${INDEXNOW_KEY}.txt\",
       \"urlList\":[${JSON_URLS}]}" >> "$LOG" 2>&1

echo "$(date) pushed $(wc -l < /tmp/push_urls.txt) urls" >> "$LOG"

挂到 crontab,每 10 分钟跑一次:

*/10 * * * * /root/push_urls.sh

收录慢的另外三个真实原因

推送做了还是不见收录,先别急着怀疑接口,检查下面三件事,它们比推送本身更常是瓶颈。

第一,站点整体抓取频次过低。搜索引擎给每个站点分配抓取预算,新站或权重低的站,预算可能只有每天几十次。你推了 500 个 URL,它也只能抓几十个,剩下的排队。这时唯一有效的做法是提高内容更新频率和质量,而不是更频繁地推送。可以在百度站长平台的"抓取频次"里申请上调,但前提是站点确实有持续的原创更新。

第二,相似度过高被判定为低价值页。如果你的文章是模板化的,正文里大段内容是重复的页头、页脚、相关推荐,真正差异化的文字只有几百字,爬虫会认为整页价值低。解决方式是把模板部分从正文里剥离,确保每篇文章的主体文本足够独特——这也是为什么本文强调文章要写足两千字以上的真实内容。

第三,内链孤立。一篇文章如果没有任何其他页面链接到它,它在爬虫眼里就是"孤岛",即便推送了也容易掉出索引。每篇新文章发布后,应该从首页、分类页或至少一篇相关文章里加入指向它的链接。对 Typecho 站点,可以确保文章出现在首页列表和分类归档里——这两处天然提供内链,前提是别把首页设置成静态单页。

sitemap 的三个常见错误

写 sitemap 看似简单,但有三处几乎每个站点都会踩。

第一,XML 头部与命名空间写错。sitemap 必须以 XML 声明开头,并且 urlset 标签要带正确的命名空间,少了这个属性 Bing 和百度都可能直接拒绝解析:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com/1234.html</loc>
    <lastmod>2026-10-02</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.8</priority>
  </url>
</urlset>

第二,lastmod 格式不规范。必须是 W3C datetime 格式,日期部分用 YYYY-MM-DD,带时间的用 YYYY-MM-DDThh:mm:ss+08:00。写成 2026/10/02 或中文日期,爬虫会忽略这个字段——而它恰恰是最重要的信号。

第三,把 404、301、noindex 的页面也写进去。爬虫抓一个死链会降低对整份 sitemap 的信任。生成时务必筛掉草稿、私密和已删除的文章。Typecho 里就是 status='publish' 这个条件,别漏。

生成之后,用工具验证一遍再提交:

# 检查 XML 是否合法
xmllint --noout /www/wwwroot/example.com/sitemap.xml && echo "XML OK"

# 统计 URL 数量
grep -c '<loc>' /www/wwwroot/example.com/sitemap.xml

# 抽查是否混入非 200 页面
for u in $(grep -o '<loc>[^<]*' /www/wwwroot/example.com/sitemap.xml | sed 's/<loc>//' | head -20); do
  code=$(curl -s -o /dev/null -w "%{http_code}" "$u")
  [ "$code" = "200" ] || echo "BAD $code $u"
done

这几条命令不到一分钟,却能挡掉绝大多数"提交了 sitemap 却不收录"的投诉。

推送之后还是看几个指标

推送只是把 URL 送进队列,真正决定收录的是内容质量、站点整体信任度和抓取预算。看这三个数字:

  • 百度站长平台的"抓取频次":如果长期是个位数,说明站点权重太低,再怎么推也快不了,回到内容质量上
  • API 返回的 remain 配额:配额快速下降说明推送被正常接收;一直不变可能有提交格式问题
  • 索引覆盖率:在 Search Console 看"已编入索引"的比例,长期偏低通常是重复内容或采集特征明显

还有一个高频误操作:同一批 URL 反复推送。搜索引擎对重复提交有去重机制,但对频繁无效推送会降低信任。只推新发布和确有修改的页面,老页面不要每天重推一遍。如果发现某个 URL 推送了多次仍不收录,不妨换一个角度排查:用 curl -I 看它返回的状态码和 X-Robots-Tag 头,确认没有被误加 noindex。

curl -sI "https://example.com/1234.html" | grep -iE 'HTTP/|x-robots|x-cache'
# 期望 200,且没有 noindex

顺便说一句,X-Robots-Tag 常常被 CDN 或安全插件偷偷加上。见过不少案例,站长为防采集装了一个插件,结果它给所有 HTML 响应都加了 noindex,导致全站从索引里消失——排查时如果发现状态正常、内容正常但收录一直为零,务必检查这个响应头。

最后,推送和站点地图不是替代关系,而是互补:接口推送负责"新内容即时通知",sitemap 负责"存量内容完整目录",robots.txt 负责"告诉爬虫去哪拿目录"。三者都配好,收录速度才会有肉眼可见的提升。对个人站长来说,这套自动化不到一百行脚本,但省下的是每天手动提交的时间,换来的是新文章当天的可见性。

Last modification:October 2nd, 2026 at 10:24 pm

Leave a Comment