百度URL推送收录:质量预审与推送策略实操
站点收录这件事,我前后在内容站、工具站、以及一个带大量列表页的行业信息站上都折腾过。百度搜索资源平台的URL推送接口本身并不复杂,一个 POST 请求就能完成,但真正决定成败的从来不是这个请求,而是请求前后的两件事:推什么、推得对不对。前者是质量预审,后者是推送策略。很多人卡在"提交成功但收录为零"这一步,往往以为是接口失灵,实际上问题早在内容层就埋下了。
这篇内容面向的是有自己站点、能改代码、能看日志的开发者和运营同学,也适合刚接手站点收录工作的新手当作流程手册来用。我会把URL推送的接口细节、参数含义、批量与重试的设计、质量预审的自查维度,以及我自己踩过的坑,按实操顺序摊开讲。文中所有域名、数据、站点均为示例,你可以直接替换成自己的。
1. 收录机制的整体设计与思路拆解
在敲下第一行推送代码之前,得先明白推送在整个收录链路里到底站在哪个位置。不夸张地说,八成的"推了不收"问题,根源都是对这个位置的理解有偏差。
1.1 一个URL从被发现到被展现,中间隔着四道门
搜索侧处理一个新链接,大致顺序是:发现、抓取、建库、索引,最后才轮到展现。URL推送只作用于第一道门——发现。它做的事情是把"我这里有个新页面"这件事主动告知,让系统把这个链接放进待抓队列,如此而已。
打个生活化的比方:你给快递员报了一个新地址,他记下来了,这算"发现";但他今天路线排满了,明天才来,这算"抓取调度";来了发现门锁着、或者屋里是空的,这算"抓取失败";东西收走了但不符合上架标准,这算"未建索引"。四个环节环环相扣,任何一环断掉,你在后台看到的都是"未收录"这个结果,但病因完全不同。
所以推送的价值不在"直接收录",而在于缩短发现延迟。一个靠外链和爬虫自然发现的页面,可能需要几天甚至几周才进入待抓队列;主动推送之后,这个延迟通常能压缩到小时级。对于时效性强的内容——新闻、价格变动、库存更新、活动页——这几小时的差距是实打实的流量差距。
理解这一点之后,很多决策就顺了:你不需要纠结"为什么推了没收录",而应该问"推完之后,抓取和索引这两关我过得了吗"。
1.2 推送量、抓取预算与内容质量构成的三角约束
我见过最常见的误区,是把每日推送配额当成"收录额度"来用,恨不得把全站几十万条URL一天推完。这里必须把三个概念拆开:推送配额是你每天能提交多少条URL给平台,抓取预算是搜索引擎愿意在你的站点上花多少资源去爬,内容质量决定抓下来的页面值不值得进索引。三者的关系是:推送负责"报名",抓取预算负责"排队进场",内容质量负责"过安检"。
配额是明面上的数字,后台能看到剩余量;抓取预算是隐形的,它由站点的历史表现决定——你的服务器响应快不快、页面是不是大量重复、有没有成片的死链、历史抓取的成功率高不高,这些都会影响系统愿意在你这里投入多少爬取资源。我操作过一个内容站,早期页面模板化严重,列表页和详情页内容高度雷同,推送了五万条,最终被索引的不到两千。后来把列表页做了 noindex、详情页补了实质内容,同样的推送量,索引率涨到六成以上。配额没变,变的是后面两关的通过率。
这里有个容易被忽略的推论:低质量页面不只是自己收不进去,还会挤占整个站点的抓取预算。你推一万条垃圾页,系统来爬了,全是低质,下一次它对你站点的抓取意愿就会下降,连带那些真正的好页面也排不上队。这就是为什么我后来养成了一个习惯:宁可少推,也要保证推出去的每一条都拿得出手。
1.3 三种提交方式的边界与选型逻辑
平台提供的提交路径不止一条,选错了不仅浪费配额,还会打乱节奏。下表是我自己在不同场景下的取舍标准,配额数值以后台实际显示为准:
| 提交方式 | 触发时机 | 实时性 | 消耗配额 | 适用场景 |
|---|---|---|---|---|
| API 推送 | 代码主动调用接口 | 高,分钟级进入队列 | 是,按条数计 | 内容发布、数据更新、批量新页上线 |
| 站点地图 | 提交 sitemap 文件,定期被抓取 | 中,取决于抓取周期 | 单独额度 | 全量存量页面、结构梳理、兜底 |
| 自动推送 JS | 用户访问页面时前端触发 | 中高,依赖真实访问 | 独立额度 | 有自然流量的站点的补充手段 |
| 手动提交 | 后台逐条填写 | 低,适合零星页面 | 极少 | 紧急单页、数量极少的场景 |
选型的核心逻辑是按页面的生命周期分层。新发布的内容走 API 推送,抢占发现延迟;存量页面用 sitemap 做周期性兜底,保证不会因为某次代码改动被漏掉;有真实流量的页面用自动推送 JS 顺手补一刀;手动提交只留给"今天必须让这条进去"的极少数情况。
需要强调的是,这几种方式不是互斥的,而是分层的。我现在的标准做法是:入库即推 API,每天凌晨生成一次 sitemap,页面模板里挂自动推送脚本。三条腿走路,任何一条出问题都不至于全站失联。
2. 前置准备:站点验证与基础配置的硬性门槛
推送接口不是拿到 token 就能用的,前面还有几道必须过的门槛。这些配置一旦做错,后面所有努力都白费,而且报错信息往往含糊,排查起来很费时间。
2.1 站点验证的三条路径与各自的坑
站点归属验证通常有文件校验、DNS 记录校验、HTML 标签校验三种。听起来随便选一个就行,实际上各有各的隐雷。
文件校验要求把一个特定命名的文件放到站点根目录,并能通过https://你的域名/文件名直接访问。坑在于很多站点的路由做了兜底重写,任何不存在的路径都会返回首页或 404 页面模板,状态码却是 200。校验程序拿到的内容不对,自然过不去。排查方法很简单,用命令行直接请求那个路径,看返回体的前几行和状态码:
curl -I https://www.example.com/verify_file.html curl -s https://www.example.com/verify_file.html | head -c 200DNS 记录校验的好处是不依赖服务器配置,适合前后端分离、静态托管在多处的站点。坑在于生效时间,TXT 记录改完之后可能几分钟到几小时才全网可见,急着点验证只会反复失败。我一般会先用公共的 DNS 查询工具确认记录已经能查到,再回后台点验证。
HTML 标签校验最省事,往首页<head>里塞一个 meta 标签即可。但它有个隐患:如果站点用了多套模板,或者首页缓存策略比较激进,标签可能只在一部分访问路径上生效。验证通过之后,如果后续换了模板把标签删了,部分功能可能会受影响。所以我倾向在验证通过后保留标签,别急着清理。
注意:验证通过不等于永久有效。站点换域名、改 HTTPS、模板重做,都可能让归属关系失效。我在一次改版后忘了迁移验证文件,推送接口连续报错两天才发现,白丢了一批时效内容的收录窗口。
2.2 站点属性配置:协议、子域与目录的独立处理
一个常见的认知偏差是:验证了主域名,全站就都通了。实际上,http和https、带www和不带www、主域和子域,在系统看来是不同的站点实体,需要分别处理归属。如果你的站点同时存在example.com和www.example.com且都能访问,那就存在重复内容风险,必须用 301 把其中一个统一到另一个。
我建议在后台把主站点属性配置完整:站点名称、所属行业、站点类型、联系方式。这些信息不直接影响推送接口的可用性,但会影响系统对你站点的理解,进而影响质量评估。有次帮一个站做诊断,发现站点类型被填成了"其他",行业分类空着,改过来并补全信息之后,抓取频次在两周内有可感知的提升。这个因果不能百分百确认,但配置成本几乎为零,没有不做的理由。
另一个细节是目录级提交。如果站点体量很大,不同频道的内容质量差异明显,可以把优质频道单独作为一个站点属性来提交,避免被其他低质频道拖累。这个操作有前提:频道必须有独立且稳定的目录结构,比如/news/、/docs/。
2.3 每日推送配额到底由什么决定
后台能看到"今日剩余推送额度",但很多人不知道这个数字是怎么来的。据我的观察和多次对比,影响因素大致有这几项:站点整体的历史收录表现、近期内容更新的持续性和规律性、是否存在违规或低质记录、站点验证的完整程度、以及内容是否原创。
这解释了一个现象:新站刚上线时配额往往很小,随着持续输出并保持一定的收录率,配额会逐步放开。反过来,如果一段时间大量推送低质页面导致收录率暴跌,配额也可能被收紧。所以我一直把配额当成一个需要维护的信用额度来对待,而不是可以随便刷的免费资源。
实操上有个技巧:先小批量试水,看收录反馈再放量。新站上线初期,我一般每天推 20 到 50 条,观察一周的收录情况。如果收录率能维持在相对健康的水平,再逐步提高到几百条。这种爬坡式的节奏,比一上来就全量猛推的效果好得多。
3. 核心细节解析:URL 推送的实操要点
接口本身很简单,一个带参数的 POST 请求,请求体是换行分隔的 URL 列表。真正需要花心思的是鉴权信息管理、报文边界、频率控制和失败处理这四件事。
3.1 接口地址与 token 的获取与保管
推送接口的形态是固定的:一个固定域名下的路径,加上site和token两个查询参数。site必须是你在后台验证过的站点,协议和子域要和验证时完全一致——https://www.example.com和https://example.com是两个不同的值,写错了会直接返回不属于该站点的错误。token在后台的接口调用页面里能看到,一串固定长度的字符。
关于 token 的保管,说三遍都不为过:不要写进前端代码,不要提交到公开仓库,不要出现在日志的明文里。我见过把 token 硬编码在页面 JS 里的做法,等于把推送权限公开了。正确做法是放在服务端的环境变量或配置中心,日志里做脱敏,只保留前后各几位。
如果真的泄露了,后台一般提供重置入口。重置之后所有旧的调用都会失效,得同步更新所有引用点。所以更稳妥的做法是在配置里预留一个 token 版本号字段,方便轮换时做灰度。
3.2 请求报文的结构与字段边界
请求体的格式是纯文本,每行一个完整 URL,包括协议头。几个容易出错的地方:
- URL 必须是完全规范化的:带协议、带域名、不带多余的空格和换行符残留。从数据库读出来的字段经常带着不可见字符,得先做 trim。
- 单次提交有条数上限,超过会被截断或报错。我一般按 1000 到 2000 条一批来做,既能控制单次请求的体积,也方便定位问题。
- 不要提交带参数的动态 URL,除非那个参数确实对应不同的内容。
?from=xxx、?utm_source=xxx这类追踪参数会让系统认为是不同页面,白白消耗配额,还会制造重复内容。 - 不要提交需要登录才能看的页面、返回 4xx/5xx 的页面、以及已经被删除的地址。
注意:一个页面改版后 URL 没变,是否需要重推?我的经验是需要。URL 不变但内容有实质更新时,主动推送能加快重新抓取。但如果只是改了几个错别字,就没必要浪费配额。
3.3 推送频率、批量与重试的工程化设计
生产环境里,推送不能是"发布成功就同步调一次接口"这种写法。接口有超时、有限流、有偶发失败,同步调用会把发布流程拖慢,甚至因为接口异常导致发布失败,这是本末倒置。
我的做法是把推送做成异步队列。内容发布时只往队列里塞一条记录,由独立的消费者进程去消费,消费失败按指数退避重试,重试三次仍失败则落库标记,等人工介入。这样发布链路和推送链路解耦,互不阻塞。
重试设计上有两个细节值得说。一是区分可重试和不可重试的错误:网络超时、服务端 5xx 属于可重试;URL 格式不合法、站点不匹配这类属于参数错误,重试多少次都没用,应该直接落库。二是避免重试风暴,如果一个批次整体失败,不要立刻重试整批,先降级成单条重试,定位出问题的那几条。
频率上,我一般控制在每秒几个请求的量级,并且在批次之间加一点间隔。没必要追求极限吞吐,配额是按天给的,不是按秒给的,把请求打得太密只会招来限流。
3.4 返回结果逐字段解读
接口返回的是 JSON,字段不多但每一个都有用:
| 字段 | 含义 | 处理建议 |
|---|---|---|
success | 本批次成功接收的条数 | 与提交条数比对,算接收率 |
remain | 当日剩余配额 | 落到监控里,低于阈值告警 |
not_same_site | 不属于该站点的 URL | 检查协议、子域、域名拼写 |
not_valid | 格式不合法或不可抓取的 URL | 检查编码、特殊字符、是否已删 |
quota | 配额不足时返回的相关信息 | 说明当天推超了,剩余的下次再推 |
看到success小于提交条数时,不要只盯着数字,一定要把not_same_site和not_valid两个数组打印出来逐条看。这两个字段是最诚实的诊断工具,很多低级错误——比如把测试环境的域名混进了生产批次——都是靠它们发现的。
remain这个字段我要单独强调一下:它是当天剩余可用量,不是总量。我建议在监控里给它设两个阈值,比如剩余低于 20% 时提醒,低于 5% 时告警,避免关键内容上线时没额度可用。
4. 质量预审:把"推得出去"变成"收得进来"
推送成功只是拿到入场券,能不能进场还得看预审。这一章是我认为整篇内容里最值钱的部分,因为它解决的是"为什么推了不收"这个最普遍的困惑。
4.1 预审到底在审什么:五个维度的自查
把收录质量拆开,我习惯从五个维度自查:内容是否可抓取、内容是否唯一、内容是否有实质信息、页面体验是否合格、元信息是否规范。这五项里任何一项不合格,收录概率都会明显下降。
逐项说。可抓取性是最基础的一关:页面返回的状态码必须是 200,robots 协议不能把该页面屏蔽,<head>里不能有 noindex,主内容不能依赖 JS 异步渲染而首屏空白。我遇到过一个典型问题,前端框架做了全站懒加载,服务端返回的 HTML 里只有一行<div id="app"></div>,抓取程序拿到的是空壳,自然判断为无内容。解决办法是做服务端渲染或预渲染,把核心内容输出到首屏 HTML 里。
唯一性指的是不能有大量雷同页面。列表页、筛选页、分页参数组合生成的页面,最容易踩这条线。我的处理方式是给这类页面加 noindex,只保留有价值的入口页参与索引。
实质信息说白了就是"这页有没有干货"。一个只有三行字的页面、一段从别处复制来的内容、一个纯粹用来承载广告的空壳页,都属于不合格。
页面体验涉及加载速度、移动端适配、是否有多余的弹窗遮挡内容。元信息则是标题、摘要、结构化数据是否规范。这两项后面单独展开。
4.2 内容质量自查清单
我把上面几个维度整理成了一张可以逐条打勾的清单,日常做新版块上线前会过一遍:
| 检查项 | 合格标准 | 不合格的典型表现 |
|---|---|---|
| HTTP 状态码 | 200 | 软 404(返回 200 但内容是"页面不存在") |
| robots 与 meta | 允许抓取,无 noindex | 测试环境遗留的屏蔽规则 |
| 首屏内容 | 服务端输出的 HTML 含主体文字 | 只有框架容器,内容全靠异步 |
| 标题 | 唯一,能概括页面内容,长度适中 | 全站统一标题、标题堆关键词 |
| 摘要 | 与正文一致,能独立表意 | 自动截断的半句话 |
| 正文长度与信息量 | 有独立观点或数据 | 拼接采集、语无伦次 |
| 内链 | 有指向相关内容的有效链接 | 全站只有首页链接 |
| 移动适配 | 移动端可正常阅读,无需横向滚动 | 表格溢出、字号过小 |
| 结构化数据 | 与页面内容一致 | 标记的内容页面上根本看不到 |
| 死链 | 站内链接无 404 | 分页翻到末页后跳空 |
这张表里我特别想强调软 404和结构化数据造假这两条。软 404 是指页面内容已经不存在了,但服务器仍然返回 200 状态码,用户看到的是"内容已删除"之类的提示。这种情况抓取程序会当成有效页面处理,反复来抓,反复拿到空内容,久而久之拉低整站的信任度。正确做法是返回 404 或 410。
结构化数据造假则是指标记里写了评分、价格、作者,但页面上用户看不到这些信息。这属于明确的违规,一旦被发现,不仅该页面受影响,整个站点的结构化数据权益都可能被收回。
4.3 移动适配与页面体验的硬指标
移动端体验在国内搜索场景里的权重很高,这一点不用回避。自查时我看三件事:视口设置是否正确、内容是否需要横向滚动、首屏是否被弹窗占据。
视口这块,<meta name="viewport" content="width=device-width, initial-scale=1">是标配,漏了会导致页面在手机上被缩放成一个缩略图。横向滚动通常出现在宽表格和固定宽度的图片上,解决办法是给表格外层套一个可横向滚动的容器,图片设max-width: 100%。
弹窗这个事值得单说。为了引导下载 App 或者收集信息,很多站点做了全屏遮罩弹窗,用户进来第一眼看到的是广告而不是内容。从体验角度这是硬伤,从收录角度也会被判为低质。我的做法是首屏不弹,滚动到一定位置或停留一定时长后再弹,并且提供明显的关闭按钮。
加载速度方面,我一般盯首字节时间和首屏渲染完成时间这两个指标。图片懒加载、压缩、CDN 分发、减少首屏的阻塞脚本,这几招做完通常能有一半以上的改善。速度不直接决定收录,但它影响抓取预算——服务器响应慢,同样的爬取资源能抓的页面就少。
4.4 标题、摘要与结构化数据的规范写法
标题是搜索结果里的第一印象,也是最容易被滥用的地方。合格的做法是:一页一标题,标题能准确概括内容,核心信息靠前。长度上,中文控制在合理范围内,过长的部分会在展示时被截断,重要的词要往前放。
反面案例我见得太多了:全站标题都是"XX网 - 专业的一站式服务平台",用户根本分不清点进去是哪篇文章;或者标题里堆了一串关键词,读起来不像人话。这两种在质量评估里都是减分项。
摘要的处理上,如果页面本身有规范的描述字段,系统会优先采用;如果没有,会自动截取正文片段。所以要保证正文开头那一段是完整的、能独立表意的句子,别一上来就是"点击查看更多"。
结构化数据的核心原则只有一条:标记的内容必须在页面上真实可见。文章类的页面标Article,包含标题、作者、发布时间、封面图;商品页标商品信息,包含价格、库存状态。标记写完一定要用后台提供的校验工具跑一遍,看有没有必填字段缺失、格式错误。
5. 完整实操流程:从零到第一次成功推送
前面讲了原理和规范,这一章把它们串成一条可执行的流程。我以一个内容站的日常发布场景为例,从写脚本到看数据,全程走一遍。
5.1 用 Python 实现一个带重试的推送器
先给一个可以直接改写使用的最小实现,包含分批、限速、错误分类和日志脱敏:
import os import time import json import logging import requests logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") SITE = os.environ.get("SITE_HOST", "https://www.example.com") TOKEN = os.environ.get("PUSH_TOKEN", "") ENDPOINT = "http://data.zz.baidu.com/urls" # 以平台文档为准 BATCH_SIZE = 1000 INTERVAL = 0.5 MAX_RETRY = 3 def mask(token: str) -> str: if not token or len(token) < 8: return "***" return token[:4] + "***" + token[-4:] def push_batch(urls): """返回 (成功条数, 剩余配额, 不合规列表, 是否可重试)""" payload = "\n".join(urls) params = {"site": SITE, "token": TOKEN} try: resp = requests.post(ENDPOINT, params=params, data=payload.encode("utf-8"), headers={"Content-Type": "text/plain"}, timeout=10) except requests.RequestException as e: logging.warning("network error: %s", e) return 0, None, [], True if resp.status_code >= 500: logging.warning("server error: %s", resp.status_code) return 0, None, [], True if resp.status_code != 200: logging.error("bad request: %s %s", resp.status_code, resp.text[:200]) return 0, None, [], False try: data = resp.json() except ValueError: logging.error("invalid json: %s", resp.text[:200]) return 0, None, [], False success = data.get("success", 0) remain = data.get("remain") bad = data.get("not_same_site", []) + data.get("not_valid", []) if data.get("quota"): logging.error("quota exceeded: %s", data.get("quota")) return success, remain, bad, False def push_all(urls): total_ok, bad_all = 0, [] for i in range(0, len(urls), BATCH_SIZE): batch = [u.strip() for u in urls[i:i + BATCH_SIZE] if u.strip()] for attempt in range(1, MAX_RETRY + 1): ok, remain, bad, retryable = push_batch(batch) total_ok += ok bad_all.extend(bad) logging.info("batch=%s attempt=%s ok=%s remain=%s token=%s", i // BATCH_SIZE, attempt, ok, remain, mask(TOKEN)) if not retryable: break time.sleep(2 ** attempt) time.sleep(INTERVAL) if bad_all: logging.warning("invalid urls: %d, sample=%s", len(bad_all), bad_all[:5]) return total_ok, bad_all if __name__ == "__main__": with open("urls.txt", encoding="utf-8") as f: all_urls = [line.strip() for line in f if line.strip()] ok, bad = push_all(all_urls) logging.info("done. accepted=%d, rejected=%d", ok, len(bad))这段代码有几个刻意的设计。token 从环境变量读,不落代码库;日志脱敏,只打印前后各四位;错误分类,网络类和服务端类错误才重试,参数类错误直接放弃;指数退避,避免失败时把请求打得更密;批次间隔,控制整体速率。
跑之前先准备好 URL 列表文件,一行一个,去除空行和重复项:
# 去重并过滤带追踪参数的链接 grep -v "utm_source" urls_raw.txt | sort -u > urls.txt wc -l urls.txt5.2 站点地图与推送的配合方式
API 推送适合新增内容,sitemap 适合存量兜底,两者配合才能覆盖全站。sitemap 我一般用脚本每天凌晨生成,包含全量有效页面,单个文件控制在合理条数以内,超出就拆分成索引文件。
生成时注意三件事:只放返回 200 且允许抓取的 URL;lastmod要真实反映内容更新时间,不要每次生成都刷成当前时间,那样会让系统认为你在虚报更新;文件编码统一用 UTF-8,不要带 BOM。
# 示例:按天生成并按大小拆分 python gen_sitemap.py --out ./public/sitemap/ --limit 50000 ls -lh ./public/sitemap/sitemap 的提交在后台完成,提交之后不是立刻生效,需要一个抓取周期。我一般提交后隔几天去后台看抓取状态,有错误提示就按提示修。常见的错误是"URL 被 robots 屏蔽"和"文件格式错误",前者检查屏蔽规则,后者用 XML 校验工具跑一遍。
5.3 数据回流与效果监控
推送做完不等于工作结束,得看数据。我盯四个指标:接收率(success 除以提交数)、剩余配额(remain)、索引增量(后台的索引量变化)、抓取异常数(抓取诊断里的失败次数)。
接收率低于九成,说明 URL 本身有问题,去看not_valid的样本。剩余配额掉得太快,要检查是不是有异常的大量推送。索引增量长期为零,那基本可以确定是质量层的问题,回到第 4 章逐项自查。抓取异常数上升,先看服务器是不是有间歇性的 5xx 或者响应超时。
我习惯把这些指标做成一张日报,每天固定时间看一次。数据不用多,但要连续看趋势,单片段的波动没有意义,一周以上的走向才有参考价值。
6. 常见问题与排查技巧实录
下面这些是我在实际操作中反复遇到的场景,按发生频率排序。每一条都附了排查思路,遇到类似现象可以照着走。
6.1 高频问题速查
| 现象 | 可能原因 | 排查动作 |
|---|---|---|
| 接口返回 4xx | token 错误、站点未验证、site参数与验证值不一致 | 比对后台的站点地址与 token,注意协议和 www |
success远小于提交数 | URL 含追踪参数、域名拼写错误、页面已删除 | 打印not_valid和not_same_site逐条核对 |
| 返回配额不足 | 当日推送量已用完 | 查看remain,剩余内容顺延到次日 |
| 推送成功但长期无索引 | 内容质量、抓取受阻、重复页面 | 从可抓取性、唯一性、实质信息三方面自查 |
| 索引量突然下跌 | 站点改版、robots 误改、大量页面失效 | 检查 robots 和 meta、对比改版时间点 |
| 抓取频次下降 | 服务器响应变慢、错误率上升 | 看服务器监控和抓取诊断的失败记录 |
| 标题在结果里显示异常 | 标题过长、堆砌关键词、与内容不符 | 逐页检查标题,改成能准确概括内容的写法 |
6.2 三个真实场景的排查过程
场景一:新站推送全部成功,索引始终为零。后台显示接收正常,配额也在正常扣减,但索引量纹丝不动。按流程排查:先看 robots,没问题;再看页面源码,发现问题了——站点用了前端框架,服务端返回的 HTML 里只有框架容器,正文全靠浏览器端渲染。抓取程序拿不到文字内容,判定为空页面。改成服务端渲染之后,第二批内容上线一周就有索引了。这件事给我留下的教训是:推送前一定要看"抓取程序看到的页面",而不是"你浏览器里看到的页面"。用命令行请求一次,把返回的 HTML 存下来看内容,是最直接的验证方式。
场景二:老站改版后索引量腰斩。改版上线三天,索引量掉了将近一半。对比改版前后的 URL 结构,发现详情页的路径规则变了,旧链接全部 404,新链接虽然也推了,但旧链接的权重和已建立的索引全丢了。补救方式是给旧链接做 301 跳转到对应的新链接,同时在后台提交死链规则做清理。这个坑的关键在于:改版必须做 URL 映射表,把旧路径和新路径一一对应,全部 301,一条都不能漏。
场景三:某个频道的页面收录率奇低,其他频道正常。全站配置一致,唯独一个频道收不进去。逐项比对,发现这个频道的页面模板里多了一个筛选模块,会生成大量带参数的组合 URL,而且这些 URL 都被内部链接指向、都可访问、内容高度雷同。等于给自己造了一堆重复页面,把抓取预算吃光了。处理方式是把筛选组合页全部加 noindex,只保留不带参数的入口页,两周后这个频道的收录恢复正常。
6.3 几条不太好写在文档里的经验
别在周五下午做大批量推送。出了问题要等到下周一才能观察和调整,中间两天的数据是黑盒。我现在的批量操作一律安排在周一到周三。
推送前先跑一遍 URL 去重和有效性校验。我写了个小脚本,推送前把列表里的 URL 逐个发 HEAD 请求,过滤掉非 200 的,再按路径去重。这一步能挡掉大部分not_valid,虽然多花几秒,但省下的是配额和排查时间。
建立自己的"推送台账"。每次推送记录批次号、条数、时间、返回结果,落到一张表里。出问题的时候,能快速定位是哪一批、哪一天、什么类型的页面。没有台账,事后排查基本靠猜。
新内容优先,存量靠 sitemap。配额是有限的,把它花在时效性最强的新页面上,收益最高。存量页面的重新抓取交给 sitemap 和自然爬取就够了。
定期清理死链和失效页。站内积累的 404 页面越多,抓取预算浪费越严重。我每个月跑一次全站链接检查,把死链提交到后台做清理,同时修掉内链里的失效引用。
这个内容后续还可以往两个方向延展:一是把推送系统做成带优先级调度的服务,重要页面走快速通道;二是把质量预审做成上线前的自动化卡点,不达标的内容直接拦住不让发。后者听起来麻烦,但真做过一次之后,你会发现它省下的返工时间远比搭建成本高。