# 保哥笔记 — 技术SEO > 本分片含 35 篇文章,按发布日期倒序。全部分片索引见 https://zhangwenbao.com/llms-full.md **站点**:https://zhangwenbao.com/ **分类**:技术SEO **生成**:2026-09-10 10:30:06 CST --- ## 商品价格不一致的六条报警,扣完之后一条不剩 - URL:https://zhangwenbao.com/product-price-copies-false-positive-audit.html - 分类:技术SEO - 发布:2026-08-23 | 更新:2026-09-07 - 摘要:审计报告里那行价格不一致的红字,到底值不值得排期?先问它按什么配对、扣没扣掉划线价、知不知道这一页走了地区定价。 - 关键词:结构化数据,电商SEO,Shopify > **TLDR**:摘要:从131个站里筛出181个能正常打开的商品页,把同一件商品的价格从四个地方各取一份,按报价层的SKU逐条配对,一共对上519条。相同513条,剩下6条差价全部出自地区定价,扣干净之后真正对不上的是0条,库存说法矛盾的只剩1条。真正该操心的在别处:数据出口把价格发给你,却有85.8%不说那是什么货币;一个商品页上摆着的Product声明有38.0%根本不在说这件商品;13个站把后台库存数量直接发到了公网,其中18条是负数。 > 摘要:从131个站里筛出181个能正常打开的商品页,把同一件商品的价格从四个地方各取一份,按报价层的SKU逐条配对,一共对上519条。相同513条,剩下6条差价全部出自地区定价,扣干净之后真正对不上的是0条,库存说法矛盾的只剩1条。真正该操心的在别处:数据出口把价格发给你,却有85.8%不说那是什么货币;一个商品页上摆着的Product声明有38.0%根本不在说这件商品;13个站把后台库存数量直接发到了公网,其中18条是负数。 这件事的起点,是一次没抓到的错。 做电商技术SEO的人,大多在某份审计报告里见过一行红字:商品页的结构化数据价格与页面价格不一致。工具给的证据看着无懈可击,一边是页面上那个数,一边是JSON-LD里那个数,明晃晃差着几十块。于是排期、开工单、找前端,折腾两周。保哥这回想把这行红字彻底查清楚,就从131个海外独立站里捞商品页,把同一件货的价格从四条互不相干的路径各取一份,摆到一起硬碰硬地比。 结果出乎意料:按商品编号严格配对之后,519条报价里真正对不上的是0条。六条看起来不一样的,扣到最后全是量的方式造成的。这一篇讲的就是那六条假警报怎么一条条被扣掉,以及扣完之后,剩在桌面上的真问题长什么样。 ## 一件商品的价格,在你的站上到底存着几份? 先把牌摊开。一个跑在Shopify上的商品页,同一件货的价格不止一份,而是散在五个地方,来路各不相同。 副本 | 谁生成的 | 长什么样 | 谁在读 | 页面可见文字 | 主题模板 | $1,799.99 | 人 | og:price:amount | 主题的head片段 | 1,799.99 | 社交平台、部分抓取器 | JSON-LD的offers.price | 主题或第三方应用 | 1799.99 | 搜索引擎、AI助手 | 商品地址加.json后缀 | 平台自带,关不掉 | 字符串形式的元 | 任何人 | 商品地址加.js后缀 | 平台自带,关不掉 | 整数179999,单位是分 | 店铺自己的前端脚本 | 前三份是店主这边的产物,改主题、装应用都会动它们。后两份不一样,它们是平台送的,店主没开过,也关不掉——那个一次能拿走250条商品的数据出口 (https://zhangwenbao.com/shopify-products-json-open-data-endpoint-audit.html),就是同一套东西的列表形态。这次要比的,正是这几份彼此之间对不对得上。 还得先说清楚两件与口径有关的事,不然后面的数字都站不住。第一,页面渲染层没有进严格统计。抽样用真实浏览器渲染了十个站之后发现,一个页面上可见的金额里混着分期月供、划线原价、配件单价、礼品卡面额,casper那一页最靠上的可见数字是46美元的月供,跟商品价599美元完全不是一回事。所以严格比对只在三份机器可读的副本之间做,渲染层只用来抽样核对。 第二,采集全程单线程、间隔2秒。131个站一轮跑下来,商品页能正常打开的181个,数据出口还开着的56个站。第二轮把请求顺序整个反过来重跑,顺便让同一个出口连着问两次——先确认它自己跟自己一样,再谈它跟别人一不一样。 ## 按出现顺序比,还是按商品编号比? 第一版脚本差点让这篇稿子从头错到尾。 那天在jackery的储能电源页面上,脚本报了一个漂亮的数字:页面上写着3,149.00,JSON-LD里第一个Product节点写着12139,差3.86倍。这要是真的,就是一条能上标题的重大发现——给人看一个价,给谷歌报另一个价,差近四倍。 然后用浏览器打开亲眼看了一遍。那一页从上往下滚,3,149、4,639、5,479、7,909、12,139,五档套餐的价钱全都明明白白印在页面上;JSON-LD里那五个Product节点,一个不多一个不少,跟五档一一对应。它没有虚报任何东西,只是节点从贵往便宜排,而og:price取的是最便宜那一档。差3.86倍这个数,完全是按顺序取第一个取出来的。 这件事的教训比它本身值钱:当一页上有多个商品节点时,这一页的价格根本不是一个数。爬虫只会取走其中一个,取哪个由取法决定,跟这个站写得对不对没关系。于是整套比对推倒重来,改成按编号配对——把每个节点的SKU抓出来,去数据出口的变体清单里找同一个SKU,找到了才比价格、比库存、比货币。 顺手把这件事量了一下,好确认jackery不是孤例。在能同时拿到og:price和多档JSON-LD价格的页面里,og取到最低那一档的27个,取到最高那一档的1个,还有1个页面的og:price压根不落在JSON-LD的任何一档上。同一页上两个都是写给机器读的价格字段,本身就未必指向同一档货。另有13个页面的JSON-LD只写了一个价,却和og:price不相等,这里面混着地区定价和划线价两种情况,得逐个看才能断,不能一律算成错。 ## 配对要认哪一层的编号 这里还有个更细的坑,是在baseus那台户外摄像头上撞见的。同一个Product节点里,商品层写着sku为S0003401,报价层的offers.sku却写着S0TW002130,两个是不同的变体,价格差30美元,库存一个有一个无。 价格和库存这两个字段,按schema.org对Offer类型的定义 (https://schema.org/Offer)是挂在报价层的,不挂在商品层。所以配对必须以offers.sku为准;拿商品层的编号去配报价层的价,等于把一个节点自己的内部错位,算成了两份副本之间的不一致。这类错位实测中撞到两个站,数量不多,但每一个都会被工具报成价格不符。 ## 先问它自己跟自己一不一样 还有一层不做就不敢下结论的功课。所有跨副本的差异,都建立在一个默认前提上:每份副本在两次请求之间是稳定的。这个前提得自己去验。 做法有两条。一条是让同一个数据出口连着问两次,中间隔着几秒和一次页面请求,比对两次返回的变体清单是否逐字一致;另一条是把整轮请求的先后顺序反过来重跑——第一轮是页面在前、出口在后,第二轮改成出口在前、页面在后。如果一个差异在正序里出现、反序里消失,那它量的就不是数据,是顺序。上一批做HTTP/2帧大小对照时,正是靠反序跑才发现下载窗口那个48%的差距根本不存在,这次把同一套纪律直接搬了过来。 两条都跑完了,结果比预想的干净。51个站做了连问两次这一项,两次返回的变体清单逐字一致的是51个,一个例外都没有。反序那一轮重新配上199条报价,相同197条、不同2条,而这2条正是正序里揪出来的那两个站,一条不多一条不少。再往细里对,49个商品在两轮之间的出口价格一个都没动过。 这一步花掉的时间不算少,一轮下来又是几百个请求。但它换来的是一句能站住的话:后面所有关于差异的结论,都不是抖动、不是缓存、也不是请求顺序变出来的。少了这一步,就只能写成量到了几条差异;有了这一步,才敢写成这几条差异是真的、而且只有这几条。 ## 报出来的那几条不一致,是怎么一条条被扣掉的? 换成按报价层编号配对之后,519条报价对上了,其中513条一模一样,剩6条不同。接下来的活儿就是逐条问:这一条到底是它写错了,还是量错了。 扣除项 | 判据 | 扣掉多少 | 划线价 | 结构化数据里那个价等于出口的compare_at_price | 0条 | 地区定价 | 页面自报货币不是店铺基准货币,或规范地址带地区前缀 | 6条 | 层间错位 | 商品层SKU与报价层SKU指的不是同一个变体 | 配对阶段已规避 | 剩下的真差异 | — | 0条 | 划线价这一关本来是重点防的。商品页上那个被划掉的原价 (https://zhangwenbao.com/strikethrough-price-prior-price-dtc-discount-display.html)非常容易被结构化数据当成现价写出去,一写出去就是几十块的差额。这次一条都没撞上,算是个意外之喜,但检查还是得留着。 六条全部倒在了地区定价这一关,出自两个站,aloyoga三条、misen三条。aloyoga那条最典型:页面上、og:price里、JSON-LD里,三处齐刷刷写着110.0,货币是SGD;而数据出口给出的是78.00。两个数都没错——页面走了地区定价,数据出口不走。请求从一个被判成新加坡的出口IP发出去,站把它路由到带en-sg前缀的地址,页面那份价格跟着换算成新加坡元,而出口那份纹丝不动,还是店铺基准货币下的那个数。 库存那一侧同样干净:523条能配对的库存声明里,522条与出口完全一致,唯一那条矛盾出在beistravel,根子还是同一个——那个节点压根没写商品层的SKU。生鲜替换那一篇 (https://zhangwenbao.com/grocery-substitution-preauthorization-notification.html)里提过一句缺货状态在页面、商品数据和抓取程序眼里是不是同一个,那时候只是提问,这次算是把它量出来了:在这批样本上是同一个。 所以那行红字,在这批样本里一次都没有真正成立过。上一次量爬虫和用户拿到的页面差异 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)时也是这样,74%一路掉到2.2%;这一次更彻底,直接掉到了0。差别在于那一次剩了2.2%,这一次一条不剩。 ## 一个商品页上摆着几十份商品声明,有几份在说这件商品? 既然价格本身没问题,那些让工具误报的节点又是从哪儿冒出来的?答案就在页面结构里。 153个能判定归属的商品页上,一共数出856个Product节点。按SKU回查出口的变体清单,属于本商品的只有531个,剩下325个、也就是38.0%,说的是页面上别的商品——推荐位、搭配购买、看了又看,那些卡片各自带着自己的结构化数据。45.1%的商品页不止一个Product节点,最多的一页有118个。 这里得交代一个口径,不然856这个数会被误读。采集时每页最多只留了前60个节点,181个页面里有3个因此被截断,其中taylorstitch那一页真实节点数是118个、brooklynbedding是84个、thirdlove是61个。所以856是个保守值,真实总量是1026个,而38.0%这个比例算的是留存下来的那部分。 被截断的那两页恰恰最极端。taylorstitch那件衬衫的页面上摆着118份商品声明,抽出来看的前60份里,属于本商品的是0个——一份都没有在描述你点进来看的那件货。allbirds那双跑鞋更好玩,53个节点里13个是本商品的十三个尺码,另外40个是别人的。工具要是不做归属判定,一头扎进去随便捞一个价出来,报错是必然的,不报才是运气。 ## 比价格写错更常见的,是根本没写全 顺着这条线往下量,还有一个更值得管的数:153个商品页里,把自己所有变体都写进结构化数据的有82个,只写了一部分的43个,一个变体都没写的28个。 多尺码多颜色的商品只标一个价,搜索结果里露出的价格区间就是残缺的。这件事在变体商品的Schema与canonical三层治理 (https://zhangwenbao.com/woocommerce-product-variations-seo-schema-canonical-url-deep-dive.html)里讲过原理,实测下来它比价格写错常见得多,偏偏几乎没有工具会报——因为工具只会比对已经写出来的字段,不会替你数少写了几个。 ## 出口把价格发给了你,却不说那是什么货币 把注意力从页面挪到数据出口,第一个跳出来的问题跟价格对不对没关系,跟价格是什么有关系。 1085个变体记录里,标了货币的154条,没标的931条,八成半以上的价格数字是裸着发出来的。另一个出口更干脆:按这个接口的官方说明 (https://shopify.dev/docs/api/ajax/reference/product),它的价格一律是以分为单位的整数,从头到尾没有货币字段,规范里也不打算给。你拿到一个179999,它可能是1799.99美元,也可能是1799.99新加坡元,出口本身不负责告诉你。 这不是纸上谈兵的风险。同一次采集里,从同一个出口IP出发,页面自报的货币收到了五种:USD一百二十四次、SGD二十一次、EUR九次、DKK三次,还有三次是ANG,荷属安的列斯盾。九个商品页的规范地址直接带上了地区前缀,指向en-sg那一版。也就是说,同一个网址,谁来问、从哪儿问,拿到的定价上下文就不同,而那个不标货币的出口对此一无所知。比价工具、竞品监控、喂给购物代理的数据管道,全都在这个缺口上默认成美元。 这一层的判据其实很简单:跨境价格本地化 (https://zhangwenbao.com/currency-formatter-cross-border-price-localization-schema-guide.html)只做在渲染层是不够的。凡是机器要读的地方,价格和货币必须成对出现,缺一个另一个就没有意义。多市场站还要往前一步,让每个地区版本的结构化数据各写各的货币 (https://zhangwenbao.com/woocommerce-multilingual-multicurrency-seo-hreflang-url-schema.html),而不是全站共用一个基准币。 ## 同一个价,一个出口写1799.99,另一个写179999 平台自带的两个出口,来路相同、指向同一件商品,价格的写法却是两套。 一个给的是字符串形式的元,另一个给的是整数形式的分。930条记录全都遵守各自的规矩,没有例外。规范上两边都没错,可它们放在一起,就是一道等着人踩的题。 踩法有两种,方向相反。一种是拿分当元,把179999当成十七万九千九百九十九,商品瞬间贵一百倍;另一种是拿元当分,1799.99当成十八块钱。前者会让着陆页价格与提交数据不一致 (https://support.google.com/merchants/answer/6098295)这条政策直接生效,整批商品被判成价格异常;后者更危险,因为它看着像一次促销。字符串那一版还有第二层麻烦:它是字符串不是数字,直接参与算术运算的话,不同语言的隐式转换各有各的脾气。 保哥自己的判据是,任何跨系统传价格的地方都别传浮点数,也别传裸整数,传一个把金额和货币绑在一起的结构。这跟产品feed该谁管 (https://zhangwenbao.com/product-feed-seo-asset-organic-ai-ownership.html)是同一个道理:数据一旦离开你的页面,接收方对你的单位约定一无所知。列表页那个每千克单价 (https://zhangwenbao.com/unit-price-denominator-eu-rules-product-list.html)踩的也是这个坑,只不过它错在分母上。 ## 后台那个库存数量,是怎么跑到公网上去的? 这一项是采集时顺手撞见的,撞见之后就没法当没看见。 那个AJAX形态的出口,在变体记录里附带一个字段,写的是这个变体当前还剩多少件。131个站里,13个站的304条变体记录把这个数字原样发到了公网上,中位数56件,最大的一条465件。不需要登录,不需要令牌,一条命令的事。 更有意思的是分布的两端:31条是0,18条是负数。负库存意味着卖出去的比记录里有的还多,也就是超卖已经发生了,正等着人工去收拾。这个状态平时只有运营在后台看得到,现在它挂在公网上,谁想看都能看。 要澄清一句:这个字段并不是所有站都发。同一次采集里626条记录没有它,说明它跟库存跟踪的开关以及主题的配置有关,不是平台强制。但反过来说,那13个站多半也不知道自己在发。库存数量本身不算机密,可它连起来能推的东西不少——上新节奏、动销速度、备货深度,竞品拿一个定时任务盯上几周,你的补货周期就摊开了。这类机读地址没有head标签 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html),想拦只能在响应头和服务端做文章。 缺货的另一头也值得顺手看一眼。产品缺货下架之后的收尾 (https://zhangwenbao.com/magento-2-out-of-stock-discontinued-product-seo-301-410-soft-404.html)一直是电商SEO的漏勺,而库存字段是判断该走哪条路的第一手依据——它是暂时缺货还是永久停售,页面该保留还是该410,都得先从这里读。 ## 那么真正该担心的是哪几件事? 把这一轮的账结一下。价格一致性,在这批样本里是个伪问题;真正立得住的问题有四条,按轻重排下来是这样。 问题 | 实测量级 | 后果落在哪 | 变体没写全 | 153页里43页只写一部分,28页一个没写 | 搜索结果的价格区间残缺 | 出口不标货币 | 931条裸价格,占85.8% | 下游管道默认成美元 | 页上混着别人的商品声明 | 856个节点里325个不属于本商品 | 任何按顺序取值的工具都会误报 | 库存数量外泄 | 13个站304条,含18条负数 | 补货节奏和超卖状态被看光 | 这四条有个共同点:它们都不会被现成的审计工具标红。工具擅长比对两个数字一不一样,不擅长回答这两个数字是不是在说同一件事。结构化数据审计工具 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)能把字段缺漏扒清楚,但归属判定、货币上下文、层间对齐这几件事,目前还得自己动手。 再往前看一步,这几条的分量还会变。购物代理读你的站 (https://zhangwenbao.com/agent-readiness-scorecard-dtc-ai-shopping-agent.html)时不会像人一样把页面从上到下看一遍,它多半直接奔着结构化数据和数据出口去。人还能靠常识识破一个标错一百倍的价格,管道不会——它只会照单全收,然后把这个数写进比价结果里。免费商品收录 (https://zhangwenbao.com/google-free-product-listings-merchant-center.html)这条通道同样吃的是这份数据。 ## 三步把四份副本摆到同一屏上 不用装任何东西,浏览器和一条命令就够。挑一个自己站上有多变体的商品页,照下面三步走一遍。 第一步,把两个出口的原文取回来,先看货币和单位: curl -s "https://你的域名/products/某个handle.json" | head -c 2000 curl -s "https://你的域名/products/某个handle.js" | head -c 2000 重点看三处:变体里的价格是带小数点的字符串还是整数分、有没有货币字段、有没有一个写着剩余件数的字段。第三处如果有值,先去后台把库存跟踪的显示关掉,再决定要不要在服务端拦。 第二步,把页面里的结构化数据抠出来,数一数有几个Product节点,再数一数其中几个的SKU出现在第一步那份变体清单里。差额就是页面替别人做的声明。这一步用JSON-LD校验工具 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)过一遍语法,顺便能发现尾逗号之类会让整块失效的毛病;字段该填哪些、哪些是必填,对照商品摘要的字段要求 (https://developers.google.com/search/docs/appearance/structured-data/product-snippet)过一遍就清楚了。 第三步,做一次货币对照:换一个地区的出口去请求同一个商品页,看规范地址会不会变、页面自报的货币会不会变、而两个数据出口那份会不会跟着变。如果页面变了、出口没变,你的下游管道就有一个默认成基准货币的缺口。这一条在只做单一市场的站上不成立,跨境多市场的站必查。页面渲染那一份价格从哪来,可以顺着主题模板拿到的product对象 (https://shopify.dev/docs/api/liquid/objects/product)倒推回去。 最后提醒一句关于工具报告的读法。看到价格不一致这类告警,先问三个问题:它是按什么配对的、扣没扣掉划线价、知不知道这一页有地区定价。三个问题里有一个答不上来,那条告警就先别排期。按页面模板抽样 (https://zhangwenbao.com/ecommerce-seo-audit-template-level-sampling.html)做这套核对,比逐条网址跑一遍省得多。 ## 常见问题解答 ## 我不用Shopify,这篇跟我有关系吗? 有一半关系。两个数据出口是平台特有的,别的系统未必有同样的地址;但四份副本这个结构是通用的——页面渲染一份、og标签一份、结构化数据一份、给前端脚本用的接口一份,WooCommerce、Magento、自研前端全都是这个套路。归属判定、层间对齐、货币上下文这三件事,换个平台一样要做。 ## 审计工具报的价格不一致,是不是可以全部忽略? 不能。这批样本只有181个商品页、519条报价,样本里为零不等于全网为零,尤其是装了大量第三方应用、结构化数据由多个来源拼出来的站,出错概率明显更高。正确的读法是把它降级成待核实:用文中那三个问题过一遍,能解释掉的关掉,解释不掉的再排期。 ## 为什么一定要按offers.sku而不是product.sku来配对? 因为价格和库存这两个字段挂在报价层,不挂在商品层。一个Product节点可以描述一个商品系列,而它的offers指向其中某一个具体变体,这在规范里是允许的。实测中撞到两个站的两层编号指向不同变体,如果按商品层配对,这两条就会被算成价格不一致,而它们其实是节点自己的内部错位。 ## 页面上有推荐商品的结构化数据,算不算写错了? 不算错,是常见做法,问题在于没有边界。规范上推荐位带自己的Product标记是合法的,但如果这些节点跟主商品混在同一层、又不通过主实体之类的字段声明主次,机器就只能靠猜。稳妥的做法是主商品那份单独放,并且让页面的主实体明确指向它。 ## 变体太多,结构化数据要不要每个都写? 写不写取决于价格是否相同。价格一致的多变体,写一个带价格区间的报价聚合就够;价格不同的必须逐个写,否则搜索结果里露出的价格区间是残缺的。实测里28个商品页一个变体都没写,这些站的多规格商品在搜索结果里只能显示一个孤零零的价。 ## 库存数量泄露怎么关掉? 先分清是哪一层的事。数量字段跟着库存跟踪设置走,后台关掉跟踪字段就没值了,但这会影响超卖控制,多数站不会这么干。更实际的做法是在服务端拦:那个出口是固定路径,可以在反向代理层对非同源请求做限制,或者用响应头把它挡在索引之外。要注意它本身是主题脚本在用的,一刀切会把加购功能弄坏,改之前先看自己主题调没调它。 ## 货币这件事,最小的修法是什么? 在结构化数据里把货币字段写成这个页面实际渲染的那个货币,而不是店铺基准货币,这是成本最低也最容易被忽略的一步。做多市场的话,同一件商品在不同地区版本上的结构化数据必须各写各的货币,配合地区版本的规范地址一起提交。数据出口那一侧改不动,只能在下游接收端约定好按什么货币解释。 ## 这批数字能代表我的站吗? 机制能,数值不能。四份副本各有来路、报价层与商品层分属两层、出口不做地区定价、单位一分一元,这几条是结构性的,换个样本一样成立。至于零条真差异、38.0%的节点不属于本商品、85.8%不标货币,只描述这131个站在2026年9月这一次采集里的样子,换一批站、换个时间、换个出口IP,绝对值一定会动。 ## 做这套核对要花多久? 单个商品页十分钟,全站要看你有几套模板。商品页模板通常不超过五种,每种挑一个有多变体的样本走一遍三步,半天能收工。真正费时间的不是采集,是判断——每发现一处差异都得回头问一遍是它错了还是你量错了,这一步没法省,省了就会得到一堆假警报。 ## 权威参考资料 ## 响应头和meta打架的时候,赢的从来不是更严的那条 - URL:https://zhangwenbao.com/http-header-vs-meta-layer-precedence-audit.html - 分类:技术SEO - 发布:2026-08-22 | 更新:2026-08-22 - 摘要:同一件事写在HTTP响应头和HTML里,哪一层说了算?六格iframe实验加674份配对样本,给出编码、防嵌套、收录控制三条线的层级顺序与一张按层归位的对照表。 - 关键词:技术SEO,HTTP响应头,CSP,声明层级 > **TLDR**:摘要:同一条禁令写在响应头和HTML里,浏览器只听响应头的。更反直觉的是同为响应头的两条:X-Frame-Options写着DENY,旁边一条CSP写着允许同源,实测页面照样被嵌进了iframe——更严的那条输给了层级更高的那条。674份页面配着响应头对账下来,403份带X-Frame-Options,其中344份被同一响应里的CSP架空;69个站还在发为已退役浏览器准备的兼容声明。文中给出六格iframe裁决实验、规范只承认的那几个pragma、三层规则的方向性与一张按层归位的对照表。 > 摘要:同一条禁令写在响应头和HTML里,浏览器只听响应头的。更反直觉的是同为响应头的两条:X-Frame-Options写着DENY,旁边一条CSP写着允许同源,实测页面照样被嵌进了iframe——更严的那条输给了层级更高的那条。674份页面配着响应头对账下来,403份带X-Frame-Options,其中344份被同一响应里的CSP架空;69个站还在发为已退役浏览器准备的兼容声明。文中给出六格iframe裁决实验、规范只承认的那几个pragma、三层规则的方向性与一张按层归位的对照表。 8月18日凌晨,给AI代理看的那份索引文件出了第二版,Search Engine Journal报道 (https://www.searchenginejournal.com/llms-txt-v2-formal-markdown-linking-ai-agents/586119/)说它加进了正式的Markdown链接规则,方便代理顺着文件往下找内容。 又多了一层。 一个网站对外说话的地方本来就不少:站点根目录的规则文件、页面里的meta、HTTP响应头,现在再添一份给AI代理的清单。这些层各说各的,多数时候相安无事,直到某两层说了相反的话。 那时候谁赢? 很多人的直觉是"更严格的那条赢",或者"更具体的那条赢"。保哥用一组自建实验和674份配着响应头的真实页面对了一遍账,结论跟直觉差得挺远:赢的既不是更严的,也不是更具体的,而是更靠近传输链路上游的那一条。而上游那条,通常不是你写的。 ## 同一件事写在两层,谁说了算? 先从最容易验证的一层开始:字符编码。它可以写在HTTP响应头里,也可以写在HTML的meta里。 ## 造两个互相矛盾的页面 本机起一个最小的PHP服务,两个测试地址: 第一个,响应头声明charset=iso-8859-1,HTML里写,正文放一段中文。 第二个反过来,响应头声明charset=utf-8,HTML里写,正文同样是那段中文。 加载之后读document.characterSet:第一个返回windows-1252,中文变成层级è£å†³;第二个返回UTF-8,中文正常。 两个方向都指向同一个结论:响应头赢,而且赢得干净利落,HTML里那条连争一下的机会都没有。 ## 为什么必须在本机测 第一版实验放在线上服务器跑,做不出"响应头不带编码"这个场景——PHP自己会补一个,nginx还会再补一个。想造一个干净的对照组,就得找一台中间层最少的机器。 这件事本身就是本文的注脚:你以为响应头是你写的,实际上它是一条流水线的产物,你只是其中一环。 ## 这不是理论,样本里就有4个 168个首页配上同期抓到的响应头,147份带编码声明,其中143份写UTF-8,4份写的是ISO-8859-1。这4个站眼下没出事,因为它们的内容基本是拉丁字符。哪天上了一个带重音符号的产品名,或者接了一批中文评论,问题就来了——而排查的人多半会先去翻HTML,翻半天发现那里写的明明是UTF-8。 ## 对照组:把上游那条撤掉会怎样 光测"两层打架谁赢"还不够,得确认另一件事:赢的那一条是不是真的在起作用,会不会是浏览器自己猜出来的。 所以又做了两个对照页:一个响应头不带编码、HTML里也一条不写,正文照样放中文;另一个响应头不带编码、HTML里写gbk,正文实际是UTF-8字节。 第一个返回windows-1252,中文乱码。第二个返回GBK,乱成另一副样子。浏览器不做内容识别,它只认声明;没有声明就用默认值兜底。这两组一跑,前面那个"响应头赢"的结论才算立住——不然完全可能是浏览器按内容猜对了,跟谁声明的没关系。 ## 那82份不带编码的响应头呢 674份配对样本里,592份响应头带编码,82份不带。这82份完全靠HTML里那条活着。它们目前也没出事,因为编码声明都写在head很靠前的位置。 这里有个隐蔽的依赖关系:同一个页面里重复声明谁生效那篇 (https://zhangwenbao.com/duplicate-meta-tag-first-declaration-wins-audit.html)量过,有33个站把编码声明挤到了1024字节之后——而这33个站的响应头,全都带着编码。两组配置各自成立,没有一个站是靠运气活着的,但这种巧合本身就说明它们依赖的是平台的默认行为,不是自己的判断。 ## 一个页面能不能被嵌进iframe,是怎么判出来的? 编码那一层是"两层",只有两个参赛者。真正热闹的是防嵌套:同一件事可以写在三个地方,而且它们的关系不是简单的覆盖。 ## 六格实验 做了六个测试页,每个页面声明一种组合,然后从同源的父页面用iframe去嵌,看能不能渲染出内容。 页面 | 它声明了什么 | iframe里能看到内容吗 | 第一格 | 响应头 X-Frame-Options: DENY + 响应头 CSP: frame-ancestors 'self' | 能 | 第二格 | 响应头 X-Frame-Options: SAMEORIGIN + 响应头 CSP: frame-ancestors 'none' | 不能 | 第三格 | 只有响应头 X-Frame-Options: DENY | 不能 | 第四格(对照组) | 什么都不写 | 能 | 第五格 | | 能 | 第六格 | | 能 | ## 第一格是全场最反直觉的一格 这个页面同时写了两条防护:一条说谁都不许嵌,一条说同源可以嵌。结果是同源嵌进去了。 写DENY的人本意是最严格的封锁,他大概不知道旁边那条CSP会把自己整个作废掉。MDN在这个字段的说明里写得很直白 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options):如果响应里同时存在CSP的frame-ancestors指令,X-Frame-Options会被忽略。不是取交集,不是取更严的,是直接忽略。 第三格是这条规则的反证:把CSP那条撤掉,只留DENY,页面立刻嵌不进去了。同一个DENY,有邻居的时候是废纸,没邻居的时候是铁门。 ## 第五格和第六格:写在HTML里的那两条,从头到尾没生效 第五格用meta的形式写CSP,指令是frame-ancestors 'none',看起来跟第二格一样严。实测能嵌。原因是CSP规范明确规定 (https://www.w3.org/TR/CSP3/#meta-element),meta形式的策略不支持frame-ancestors、report-uri和sandbox这三个指令,写了直接忽略。 第六格更彻底:X-Frame-Options从来就不是一个合法的pragma,把它写进meta等于写了一行注释。 这两格加起来说明一件事:同一句话,写在响应头里是命令,写在HTML里可能什么都不是。 ## 第四格为什么必须做 第四格什么都不声明,页面被顺利嵌进来。这一格看起来毫无信息量,但它是整组实验的地基。 如果第四格也嵌不进去,说明拦截来自别的地方——父页面的策略、浏览器的设置、或者测试代码本身写错了。那样的话前面三格的"不能"就全是假的。做实验最怕的就是这个:你以为在测A,实际上在测B,而两者恰好给出同样的现象。 这也是给测量补一组基线之后假阳性从74%掉到2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)那次踩过的坑,教训是一样的:先证明你的尺子在没有被测对象的时候读数为零。 ## 把六格结论排成一条链 六格跑完,防嵌套这件事的层级关系就很清楚了: CSP响应头 > X-Frame-Options响应头 > meta里的任何写法(等于零)。 注意中间那个大于号的含义跟通常的"覆盖"不太一样。它不是"两条都读、CSP优先",而是"只要CSP里出现了frame-ancestors这个指令,X-Frame-Options这条头就当不存在"。哪怕CSP里写的是允许所有人嵌,X-Frame-Options的DENY也不会被拿来补位。 另一个容易混的点:这条规则只在frame-ancestors指令出现时触发。如果响应里有CSP、但CSP里没写frame-ancestors,那X-Frame-Options照常生效。样本里165份响应属于"只有frame-ancestors没有老字段",这些站是干净的;344份两条都有,老字段在里面纯属陪跑。 ## 安全头这一层还有别的连带伤害 防嵌套只是加固清单里的一条。同一份清单里还有一条管特性权限的头,加错了会把嵌进来的地图、支付按钮一起变成摆设——照着加固清单加的一行响应头把第三方挂件全废掉 (https://zhangwenbao.com/permissions-policy-iframe-third-party-widget-silent-denial.html)那篇量过这种静默失败。它和本文说的层级问题是同一类:改的人看得见自己那一行,看不见它跟别处的相互作用。 站点上有支付流程的话,CSP这一层还得单独看一遍。53个支付页里45个配了CSP、真正管住脚本的只有5个 (https://zhangwenbao.com/payment-page-csp-factory-default-script-policy.html),那组数据说明配了不等于配对了。 ## meta http-equiv到底能不能当响应头用? 这个属性的名字起得很有误导性。http-equiv字面意思是"等价于HTTP",很多人理解成"在这里写等于在响应头里写"。 实际上它只是一个受严格限制的白名单。 ## 规范认的就那么几个 HTML规范列出的pragma指令 (https://html.spec.whatwg.org/multipage/semantics.html#attr-meta-http-equiv)一共只有几个:内容语言(已标记为废弃)、内容类型、默认样式、刷新、Cookie(已废弃)、IE兼容模式、内容安全策略。除此之外的任何写法,浏览器都不会当成响应头处理。 换句话说,缓存控制、过期时间、机器人指令、防嵌套,这几件在响应头里天天用的事,写进meta全都不算数。 ## 真实站点上都写了些什么 写在meta里的pragma | 首页样本(168) | 内页样本(674) | 响应头里也有同名字段 | 规范承认吗 | IE兼容模式 | 85条 | 401条 / 69站 | 0篇 | 承认 | 内容类型 | 24条 | 24条 / 6站 | 24篇 | 承认 | 页面刷新 | 17条 | — | — | 承认 | 内容安全策略 | 11条 | 0条 | — | 承认(部分指令无效) | 内容语言 | 3条 | 37条 / 8站 | 6篇 | 已废弃 | 缓存控制 | 3条 | 6条 / 1站 | 6篇 | 不承认 | Pragma | 3条 | 6条 / 1站 | 5篇 | 不承认 | 过期时间 | 3条 | 6条 / 1站 | 5篇 | 不承认 | 字体渲染开关 | 1条 | 6条 / 1站 | 0篇 | 不承认 | 客户端提示委派 | 1条 | 6条 / 1站 | 0篇 | 不承认 | 来源试用令牌 | 1条 | 6条 / 1站 | 0篇 | 不承认 | 拼错的兼容模式 | 2条 | 5条 / 1站 | 0篇 | 不承认 | 缓存那三条最典型。写Cache-Control、Pragma、Expires的那个站,响应头里恰好也有对应字段——所以它的缓存行为完全正常,meta里那三行纯粹是摆设。摆设不碍事,但它会让下一个接手的人以为缓存是在这里配的。 ## 拼错的那两条更有意思 有个站把兼容模式写成了x-ua compatible,连字符掉了。这种拼错不报错、不生效、也不会有人来提醒你。同一份样本里还有几个私有字段:字体渲染开关、客户端提示委派、来源试用令牌——它们不在规范的白名单里,浏览器要么另有专门的处理路径,要么直接无视。 ## 缓存那三条为什么特别常见 把缓存策略写进meta是上个时代留下的习惯。二十年前有些浏览器确实会读这几个,后来标准收紧,它们就彻底出局了。但这段代码有极强的生命力——它在无数篇老教程里躺着,一代代复制到新项目。 要判断自己站上的缓存到底由谁说了算,看响应头就够了。浏览器缓存头怎么配才不犯改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)那篇把这一层的字段关系讲全了;如果前面还挂着CDN,边缘缓存的回源与TTL分层 (https://zhangwenbao.com/cdn-edge-caching-strategy-ttl-cache-control-purge-origin-shield.html)那一套决定了最终生效的是哪一份配置。 还有一种更隐蔽的情况:响应头里的缓存字段根本不是你写的。PHP会在开启会话时自动写一行1981年的过期时间 (https://zhangwenbao.com/php-session-cache-limiter-nocache-cdn-audit.html),把整个CDN架空,而应用代码里一个字都没提缓存。这跟meta写了不算数是同一件事的两面——一面是你写了没人读,另一面是没写却有人替你写了。 ## 响应头那一层还有多少字段是没人读的 跨层的账算完,同一层内部也值得清一遍。248个死字段里多数不是站点自己写的 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html),那批数据和本文的meta普查是对称的:一边是HTML里写了一堆响应头不认的东西,另一边是响应头里带着一堆没有接收方的字段。 ## 那69个还在发IE兼容声明的站,在等谁? 内页样本里401条兼容模式声明,分布在69个站上,占有配对响应头的113个站的61.1%。 ## 它对应的浏览器已经退役四年多了 这个字段是给IE看的,告诉它用哪个版本的引擎渲染。微软的生命周期公告 (https://learn.microsoft.com/en-us/lifecycle/announcements/internet-explorer-11-end-of-support)写着IE11在2022年6月15日停止支持,此后桌面版被彻底停用。 今天还在发这一行的页面,等的是一个已经不来的读者。它不占带宽(一行几十字节),不影响渲染,也不会有任何工具报警——所以它会一直待下去。 ## 为什么是69个站而不是6个 这个比例高得有点反常。同一批站里,用最新前端框架、跑着服务端渲染、CSP配得一丝不苟的站,head里照样躺着这一行。 原因大概有三层。最外面一层是模板继承:站点从某个起步模板拉的代码,那份模板可能是2015年写的。第二层是代码审查的盲区——评审会看逻辑、看样式、看接口,很少有人逐行看head里的meta。第三层最根本:这行代码从来没有失败过。它不报错、不告警、不影响任何测试用例,没有任何一个环节会把它标出来。 软件工程里有个说法,代码不会因为放着不动就腐烂。这句话对逻辑代码成立,对声明式的配置不成立——因为它的正确性不取决于它自己,取决于外面那个世界还认不认它。 ## 它和"写错层"是同一类问题的两面 兼容模式这一条其实是合规的:规范承认它,写在meta里也是它的标准位置。它的问题不是写错了层,而是那一层的读者走了。 把这两类放在一起看会清楚很多:一条声明失效有两种方式,要么它写在了不该写的层,要么它写对了层但那层已经没人在读。前一种是即时失效,后一种是慢慢失效。样本里两种都有,而且体量差不多。 ## 删掉它要冒什么风险 基本没有。这个字段只对IE和Edge的IE模式有意义,前者已经停用,后者是企业内网的兼容方案,跟公开的电商站没什么关系。 真要谨慎,可以先看一眼自己站的访问日志里还有没有IE的痕迹。样本里这69个站显然没人做过这件事——它们连是否还有IE访客都不知道,只是那行代码一直在模板里,没人动过。 一行几十字节,删不删都不影响生意。它的价值在于当成一个信号:如果这一行还在,说明这个站的head已经很久没有人系统清理过了。顺着它往下找,通常还能挖出别的陈年配置。 ## 同一类东西还有哪些 样本里能找到的历史遗迹不止这一个:keywords字段28个站还在写,Google早就宣布不用了;微软自家的磁贴配置字段24个站;苹果的Web应用状态栏字段一堆。它们的共同点是当年某个平台需要,后来那个平台变了,代码留下了。 清理这些东西的收益不在性能——几十行meta对加载速度的影响可以忽略。收益在于降低下一次排查的噪音。head里干净的站,出问题的时候两分钟能看完;塞了四十条声明的站,光分辨哪些还有用就得半天。 ## 响应头这一层,实际有多少人在用? 既然响应头压过HTML,那用响应头下指令应该是个好办法。674份带响应头的页面对了一遍账,结果有点出人意料。 ## 三个近乎为零的字段 机器人指令的响应头形式:674份里只有6份带了,而且内容全是允许抓取。带这个头的页面,HTML里一条机器人指令都没写,两层没有一处交叉。 规范网址的响应头形式:674份里0份。这个字段本来是为PDF、图片这类没有head的资源准备的,HTML页面上确实用不着,但0这个数字还是说明了它有多冷门。 编码声明与HTML的冲突:592份响应头带编码,与HTML里的声明不一致的有0份。两层说的完全一样。这也是个负结果——跨层冲突在真实世界里比想象的少,多数时候两层根本没同时说话。 ## 三个零凑在一起说明什么 规范网址响应头0份、编码跨层冲突0份、机器人指令响应头6份——这三个数字放在一起,得出的结论跟本文的主线有点矛盾:既然跨层冲突这么罕见,那讲层级优先还有什么意义? 意义在于,罕见不等于不存在,而且它的分布是极不均匀的。编码那一层冲突为0,是因为绝大多数站点两层写的都是UTF-8——这个共识是二十年才建立起来的。换个字段就没这么幸运:防嵌套那两条同时存在的有344份,占样本的一半以上。 更实际的一点是,跨层冲突少,恰恰是因为多数人根本不知道有另一层可以写。不是配置得好,是没配。等到哪天要用响应头做点什么的时候,才会撞上这些规则。 ## 真正有存在感的是安全那几条 响应头 | 674份里出现 | 说明 | 内容安全策略 | 521份 | meta形式在内页样本里是0 | X-Frame-Options | 403份 | 其中344份同时有frame-ancestors | 只有frame-ancestors | 165份 | 没写老字段,直接用新的 | 内容语言 | 320份 | 与html的语言属性主语言不同的12份 | 内容类型带编码 | 592份 | 82份不带 | ## 344这个数字值得盯一眼 403份响应带着X-Frame-Options,其中344份同时带着CSP的frame-ancestors。按前面那个实验的结论,这344份里的老字段是完全无效的,浏览器读都不读。 它们为什么还在?因为加固清单是叠加的。三年前的清单说要加X-Frame-Options,两年前的清单说要加CSP,执行的人两条都加了,没人告诉他第二条会让第一条作废。删掉老字段是安全的——对现代浏览器毫无影响;留着也不算错,只是给下一个读配置的人多埋一个坑。 顺带一提,响应头这一层内部还有一类问题:同一层里两条字段互相矛盾。142个站里108个在同一份响应里写了打架的字段 (https://zhangwenbao.com/http-response-header-self-contradiction-audit.html),那是同层的事,跟本文这种跨层压制不是一回事,但同样没人报警。 ## 这些头是谁配的,站点自己多半不知道 521份响应带CSP、403份带防嵌套字段,这个覆盖率高得不像是各家站点分别配出来的。逐个看内容会发现,同一家电商平台上的站,安全头几乎一模一样,连指令的书写顺序都一致。 这说明它们来自同一处:平台或者CDN在边缘统一下发。好处是站点什么都不用做就有基础防护;代价是这一层不受站点控制,平台哪天改了策略,你的页面行为跟着变,而你的代码库里一行相关代码都没有。 更麻烦的是排查。发现某个头有问题,第一反应是去翻应用代码,翻不到;再翻Web服务器配置,还是翻不到。Nginx配置每次reload都通过、Googlebot每8次抓取却撞一次301 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)那篇讲的是同一类痛苦:配置层面全都"正常",问题出在几层配置叠加之后的合成效果上。 ## 响应头这一层能做而HTML做不到的事 把两层的能力摆在一起,差别就出来了。 响应头独有的:传输安全策略、内容类型嗅探开关、跨源资源共享、特性权限、防嵌套、条件请求校验字段、缓存指令。这些在HTML里没有对应写法,或者有写法但不生效。 HTML独有的:规范网址、结构化数据、社交分享属性、视口设置。这些没有响应头形式,或者响应头形式只对特殊资源有意义。 两层都能写的其实只有三样:字符编码、机器人指令、内容语言。三样里有两样是响应头压过HTML,剩下那一样在语义上根本不是同一件事。响应头在SEO里能做的那些事 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)算是这一层的系统梳理,配合本文的层级判据看,选起来会快很多。 ## 站点、页面、响应,三层规则的方向性是什么? 抓取和索引这件事横跨三层:站点根目录的规则文件管抓不抓,页面里的meta管收不收录,响应头两件事都能管。 这三层的关系不是覆盖,是有方向的。 ## 先把三层的分工说清楚 这三层经常被混着讲,其实各管各的。 站点根目录那份规则文件管的是"要不要来取这个地址"。它在请求发生之前起作用,抓取方读完规则才决定发不发请求。它管不了索引——一个从没被抓过的地址,照样可能因为别处的链接而出现在搜索结果里,只是没有摘要。 页面里的meta管的是"取到之后要不要收进索引"。它必须先被取到才能起作用,这是它跟第一层最本质的区别。 响应头这一层两件事都能管,而且它比meta早到——响应头先于响应体送达,抓取方读完头就能决定要不要继续读下去。理论上这是最高效的一层,实际上几乎没人用。 ## 下层锁了门,上层的信就送不出去 最经典的一个陷阱:一个页面被规则文件禁止抓取,同时页面里写着不许收录。 结果是不许收录这条永远送不到。抓取被拦在门外,抓取方看不到页面内容,自然也读不到里面的指令。Google在自己的文档里专门提示过这一点 (https://developers.google.com/search/docs/crawling-indexing/block-indexing):要让页面不被收录,就不能同时禁止抓取它。 这不是覆盖关系,是物理上的送达失败。用一句话概括:你把纸条压在了一扇自己锁上的门后面。 ## 真实站点上这么干的多不多 拿161份可解析的规则文件,去核对同一批站点提交在站点地图里的50783条地址,逐条判断Googlebot能不能抓。 结果是只有37条被自己的规则文件挡住,涉及5个站,占万分之七。anker.com有24条,多数是搜索页、订单查询和账户页;mejuri.com有6条账户页;boohoo.com有4条购物车。这些页面本来也不该出现在站点地图里,属于导出程序没做过滤,跟"noindex送不出去"那个陷阱还差一层。 这是个负结果,而且是个让人踏实的负结果:大站在这件事上做得挺干净。真正常见的反而是相反的组合——地址在站点地图里、规则文件也放行、页面上却写着不许收录,这种只是浪费一点抓取,不会出事。 ## 反过来那种组合更常见,但不要紧 规则文件放行、页面上写着不许收录——这是正确的写法,也是最常见的一种。抓取方进得来,读到指令,把页面从索引里拿掉。代价只是每次抓取花掉一点预算,换来的是指令确实送到了。 两条规则该怎么搭配,规则文件和页面指令什么时候用哪个 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)那篇给的判据可以直接照抄:想省抓取预算用前者,想控制索引用后者,两个目的不要用同一个工具去实现。 ## 三层各自的失败模式不一样 层 | 它管什么 | 典型失败 | 站点根目录的规则文件 | 抓不抓 | 指令没有接收方,或写了搜索引擎不支持的指令 | 页面里的meta | 收不收录 | 被禁止抓取时送不出去;或写在head之外 | HTTP响应头 | 两者都能管 | 几乎没人用,能力被闲置 | 第一层的失败模式已经量过一次:规则文件里35.7%的站在写没人读的指令 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)。第二层的失败模式本文和上一篇各覆盖了一半。第三层的失败模式是最特别的——它不是写错,是根本没写。674份样本里带机器人指令头的只有6份,这一层几乎是空的。 ## 拦AI爬虫这件事同样横跨三层 近两年多出来的需求是拦AI爬虫,它和收录控制的层级结构一模一样:规则文件声明意愿、响应头下硬指令、防火墙做物理拦截。这三层怎么选那篇 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)给了一个选型框架,核心判据也是层级——越靠上游的层执行力越强,但改起来越贵。 ## 响应头那一层是唯一能管住没有head的资源的 PDF、图片、订阅源、接口返回的JSON,这些东西没有地方写meta。要让它们不被收录,只能用响应头。这一层的不可替代性就在这儿。这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)那篇专门量过这个场景,样本里的落实情况很不理想。 ## 新冒出来的那两层,会不会重演同一件事? 规则文件里除了允许和禁止,还能写别的东西。161份文件里翻出来这些: 指令 | 出现的站数 | 谁在读 | 抓取间隔 | 129 | Google明确不支持,Bing与Yandex支持 | 站点地图声明 | 144 | 主流抓取方都读 | 主域名指定 | 10 | Yandex的私有指令,已废弃 | 不许收录 | 7条(2个站) | Google在2019年9月停止支持 | 内容信号 | 2 | 2026年才出现的新提案 | 指向AI清单的字段 | 2 | 没有统一规范 | AI使用策略 | 1 | 没有统一规范 | ## 这张表里有三种不同的"没人读" 看起来都是"写了可能白写",成因完全不同,处理方式也该不同。 第一种是从来就不通用:主域名指定这条是某一家搜索引擎的私有扩展,别家从来没支持过,那家自己后来也弃用了。这类东西删掉就好。 第二种是曾经支持后来撤销:规则文件里的不许收录指令属于这一类。它在2019年之前是有效的非正式用法,后来Google宣布停止支持。写这条的人当年没错,是世界变了。这类要迁移——把意图挪到页面meta或者响应头里去,别只是删掉了事,否则那个页面就真的不设防了。 第三种是部分引擎支持:抓取间隔就是这一类,Google不认,别家认。这类不能删,要做的是修正预期,并且在另一个地方补上对Google的控制。 把三种混成一句"这条没用",处理起来就会出错——第二种直接删会留下真空,第三种直接删会失去对其他引擎的控制。 ## 129个站在写一条Google不读的指令 抓取间隔这一条出现在161个站里的129个,占80.1%。Google的规则文件文档里明确写着不支持这个指令,抓取频率要去搜索后台调。写它不算错——Bing和Yandex是认的——但如果你写它的目的是让Google慢点抓,那这一条从来没起过作用。 ## 新的两层正在重复老路 内容信号、指向AI清单的字段、AI使用策略,这三样加起来只出现在5个站上。它们都很新,都还没有统一规范,都被写进了同一个文件里。 给AI代理准备的那份清单文件也是同样的处境:它是一份社区提案,不是任何一家搜索引擎或者模型厂商的正式约定。第二版加了正式的链接规则,工程上更完整了,但"谁会读它"这个问题还是没答案。 历史上每一层新声明都要走一遍这个过程:先有人提出格式,然后有人开始写,最后才知道有没有人读。写一层新声明的成本很低,指望它生效的代价却可能是把该做的事漏掉。在AI清单这件事上,比较稳妥的顺序是先把响应头和页面这两层做对,再去添新的。 ## 判断一层新声明值不值得跟,问四件事 第一,它有没有一个明确的读取方?不是"某某厂商表示关注",是"某某产品的文档里写了它会读"。给AI代理的那份清单目前答不上这一问。 第二,它和已有的层是什么关系?替代、补充、还是并列?如果是替代,老的那层什么时候能撤;如果是并列,两层说的不一样时谁赢——这个问题多数新提案都没定义。 第三,写错了会怎样?有些层写错是静默失败,有些层写错会连累别的东西。规则文件里加一条无法识别的指令是安全的,抓取方跳过就完了;但如果新提案要求你在响应头里加字段,那就得当心跟已有字段的相互作用。 第四,撤回的成本多大?这一问最容易被忽略。一份放在根目录的静态文件,删掉就没了;一条写进CDN边缘规则的响应头,撤回要重新走一遍发布。先做便宜的、可逆的那一层,是所有新标准的正确打开方式。 ## 还有一类不是新层,是老层换了读者 比起真正的新层,更需要留意的是老层来了新读者。规则文件这两年就在经历这件事:一批以前不存在的抓取器开始读它,而它们对指令的解释跟传统搜索引擎不完全一样。 连"读不读"这件事本身都在变。Google有一整类抓取器根本不看规则文件 (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html),这次改名只是把这个事实推到了台前。同一份文件,有的读者逐条遵守,有的读者压根不打开——这已经不是层级问题,是读者问题了。 ## 哪一层该写什么,有没有一张对照表? 有。把前面所有实验和普查的结论收成一张表,按"这件事该写在哪一层"来排。 要表达的事 | 写在哪一层 | 写在别的层会怎样 | 字符编码 | 响应头为准,HTML里再写一遍做保险 | 只写HTML:响应头一变就被压过 | 禁止被嵌套 | 响应头的CSP frame-ancestors | 写meta:完全无效 | 兼容老字段X-Frame-Options | 可留可删,有CSP时它已失效 | 只写它:老浏览器还认,新的不认CSP才认它 | 不许收录 | 页面meta,或响应头的机器人指令 | 写在规则文件里:Google从2019年起不读 | 不许抓取 | 规则文件 | 写meta:抓都抓了,只是不收录 | 没有head的资源不许收录 | 只能用响应头 | 没有别的选择 | 缓存策略 | 响应头 | 写meta:三个字段全都不算数 | 页面语言 | html标签的语言属性 | 响应头那个字段说的是目标受众,不是文本语言 | 规范网址 | HTML的head | 响应头形式只对非HTML资源有意义 | ## 这张表的用法 它不是让你照着把每一行都配齐。多数站点只需要用到其中三四行,其余的保持默认就好。 正确的用法是反过来查:手上有一条已经写好的声明,先在表里找到它,确认它现在待的那一层是不是该待的地方。如果不是,两个选择——挪到对的层,或者删掉。最糟的处理是两层都写一份,因为那样你就永远不知道生效的是哪一份。 还有一种情况表里没列:同一件事在两层都写、而且值相同。这不算错,但要清楚它的真实作用是冗余备份,不是双保险加强。真出问题的时候,改一层不改另一层,问题会以一种非常难查的方式活下来。 ## 排期的时候按什么顺序做 按"错了会怎样"排,跟技术SEO先修哪个那套优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)的思路一致。 第一档是会改变索引行为的:机器人指令写错层、禁止抓取和不许收录同时写。这两种会让页面进不去索引或者出不来。 第二档是会改变安全边界的:防嵌套写在meta里、CSP的关键指令被放在无效位置。它们不影响搜索,但影响真实风险敞口。 第三档是纯冗余的:写在meta里的缓存字段、已退役浏览器的兼容声明、老平台的私有字段。这些什么时候顺手清什么时候清。 ## 语言那一行容易被误解 响应头里的内容语言字段和html标签上的语言属性,看起来在说同一件事,其实不是。前者按规范讲的是"这份文档面向哪些语言的受众",后者说的是"这段文本本身是什么语言"。一个英文写的德国市场页面,两者写得不一样是合理的。 样本里320份带内容语言头的响应,与html语言属性主语言不同的只有12份,其中还有两个站是html上压根没写语言属性。数字很小,说明多数站根本没在这两个字段之间做区分——它们同时被同一套模板输出成了同一个值。 ## 怎么在自己站上把两层对一遍? 一条命令一层,对照着看就行。 ## 先问自己三个问题 动手查之前,把要查的东西想清楚,能省掉一大半无效操作。 第一,这件事我到底想让谁听见?浏览器、搜索引擎、社交平台、AI爬虫,它们读的层不一样。想让浏览器执行的写响应头,想让搜索引擎执行的看它支持哪一层,想让社交平台读的只能写在HTML里。 第二,这件事现在写在哪几层?多数时候答案是"不止一层",而且写的人不知道另一层也写了。 第三,如果两层说的不一样,我希望谁赢?想清楚这个再去改,否则很容易改了不生效的那一条,然后以为改动没用。 ## 先把两层拉出来放在一起 U=https://example.com/ curl -sI "$U" | grep -iE '^(content-type|content-language|x-robots-tag|x-frame-options|content-security-policy|cache-control|link)' curl -s "$U" | sed -n '1,/<\/head>/p' | grep -o -iE ']*http-equiv[^>]*>' 上下两段对着看:有没有同一件事在两处都写了?两处说的一样吗? ## 查那个已经失效的防嵌套字段 curl -sI "$U" | grep -i 'x-frame-options' curl -sI "$U" | grep -i 'content-security-policy' | grep -o 'frame-ancestors[^;]*' 两条都有输出,说明第一条已经被第二条架空。要么删掉第一条,要么确认第二条写得跟你的意图一致。 ## 把meta里那些不算数的挑出来 curl -s "$U" | grep -o -iE ']*http-equiv="[^"]*"' \ | grep -o -iE 'http-equiv="[^"]*"' | sort | uniq -c \ | grep -viE '(content-type|default-style|refresh|x-ua-compatible|content-security-policy)' 剩下的就是规范不认的那些。逐条判断:是该挪到响应头,还是干脆删掉。 ## 批量对一批地址 单页看完要看面。把地址存成文本文件,一行一个: while read -r u; do h=$(curl -sI -m 20 "$u") xfo=$(printf '%s' "$h" | grep -ci '^x-frame-options') fa=$(printf '%s' "$h" | grep -i '^content-security-policy' | grep -c 'frame-ancestors') ct=$(printf '%s' "$h" | grep -i '^content-type' | grep -c 'charset') printf '%s\txfo=%s\tfa=%s\tcharset=%s\n' "$u" "$xfo" "$fa" "$ct" done < urls.txt 第二列和第三列同时为1的,说明那条老字段已经失效;第四列为0的,说明这个地址的编码完全靠HTML撑着。 ## 把响应头这一层的变化盯起来 响应头不在你的代码库里,所以它变了不会有提交记录。想知道它什么时候变的,只能自己存快照: curl -sI -m 20 "$U" | grep -viE '^(date|age|x-request-id|cf-ray|set-cookie|etag|expires)' \ | sort > "hdr-$(date +%F).txt" diff "hdr-$(date -d yesterday +%F).txt" "hdr-$(date +%F).txt" 过滤掉那些每次都变的字段,剩下的就是配置。挂个定时任务每天跑一遍,平台悄悄改了策略的时候你能第一时间看见。这条比事后排查便宜得多——用现成的接口测试工具看响应头 (https://zhangwenbao.com/api-tester-http-status-header-rest-debug-seo-guide.html)适合临时查一个地址,长期监控还是脚本更省事。 ## 验证防嵌套到底生不生效 命令行看不出iframe的行为,得用浏览器。在任意一个页面的控制台里跑: const f = document.createElement('iframe'); f.src = 'https://example.com/'; document.body.appendChild(f); setTimeout(() => { try { console.log('渲染了', !!f.contentDocument.body.innerText.length); } catch (e) { console.log('被拦了', e.name); } }, 2000); 跨源的时候拿不到内容会抛异常,所以这段只适合测同源,或者用来确认"能不能加载"这个粗粒度的结论。要精确判断得看控制台里浏览器自己报的拦截信息。 ## 改完之后怎么确认真的生效了 这一步最容易被跳过,而跨层的改动恰恰最需要它——因为你改的那一层可能压根不是生效的那一层。 编码:改完用浏览器控制台读一次document.characterSet,别只看源码里的meta写对了没有。 防嵌套:改完用一个同源页面真的嵌一次,看能不能渲染。只看响应头有没有那个字段是不够的,因为它可能被旁边的CSP架空。 收录控制:改完在搜索后台用实时抓取工具跑一次,看抓取方读到的指令是什么。它给出的是抓取方视角,跟你在浏览器里看到的可能不一样。 缓存:改完隔几分钟用带随机参数和不带参数各请求一次,对比响应头里的缓存状态标记。 四件事有一个共同点:验证要在生效的那一层做,不在你改动的那一层做。改了HTML就去看渲染结果,改了响应头就去看真实请求,改了规则文件就去看抓取方的反馈。 ## 常见问题解答 ## 响应头和meta都写了编码,会不会有冲突风险? 不会有渲染风险,因为规则很明确:响应头赢。两处都写反而是好事——万一哪天CDN不发编码头,或者页面被另存成本地文件,HTML里那条就顶上了。要注意的是两处别写不一样的值,否则本地打开和线上访问会是两种结果。 ## X-Frame-Options现在还需要写吗? 可以不写。MDN的建议 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options)是用CSP的frame-ancestors替代它。如果你的访客里还有非常老的浏览器,留着也没坏处,但要清楚它在支持CSP的浏览器上是死的。样本里344份响应正处在这个状态。 ## meta里的CSP完全没用吗? 有用,只是能力少一截。脚本来源、样式来源、图片来源这些指令在meta形式下都正常工作。不支持的是frame-ancestors、report-uri和sandbox三个。另外meta形式的策略只能加严不能放松——如果响应头里已经有一条CSP,meta里那条是叠加上去取交集,不会把头里的限制放开。 ## 为什么规范网址的响应头形式一份都没有? 因为HTML页面用不着。这个字段的响应头形式是给PDF、图片这类没有head的资源准备的。674份样本全是HTML页面,0份是符合预期的。如果你的站有大量可下载文件参与搜索,那这一层就该用起来。 ## 抓取间隔这条指令要删掉吗? 不用删。Bing和Yandex认它,删了会失去对这两家的控制。要改的是预期:别指望它对Google有任何作用,要限制Google的抓取频率得去搜索后台设置,或者在服务端做限速。 ## 给AI代理的那份清单文件,现在值得做吗? 成本低就做,但别把它当成防线。它是社区提案,没有哪家模型厂商承诺一定读。真正管用的仍然是规则文件里的抓取权限、响应头里的指令,以及页面本身能不能被读懂。新层可以加,老层不能省。 ## 为什么响应头里的机器人指令几乎没人用? 三个原因叠在一起。一是它得改服务器配置,而meta改模板就行,后者的门槛低得多;二是它作用在整个响应上,要按页面区分就得写条件规则,配置复杂度上一个台阶;三是它不可见——打开源码看不到,只有主动去查响应头才发现,团队协作时容易被遗忘。 所以它主要用在两个场景:一是没有head的资源,二是需要批量处理一整个目录。除此之外,用meta更省事,效果一样。 ## 写在meta里的页面刷新指令还能用吗? 能用,规范承认它,浏览器也执行。但它不适合做跳转——搜索引擎对它的处理不如301明确,而且用户按返回键会陷入循环。样本里17个站在首页写了这一条,多数是做地区选择页的自动跳转。要做跳转还是用服务端的状态码,那一层的语义清楚得多。 ## 层级这套判断,对结构化数据也适用吗? 部分适用。结构化数据只能写在HTML里,没有响应头形式,所以不存在跨层竞争。但它内部有同样的问题:同一个实体可以用两种格式各写一遍,两份内容不一致时消费方怎么挑,各家实现不同。这属于同层冲突,跟本文这条线是并行的另一条。 ## 这些结论对Bing和其他搜索引擎适用吗? 跨层的那部分适用,因为它们由浏览器和HTTP规范定义,跟哪家搜索引擎无关。搜索引擎自己那部分不一定:抓取间隔、规则文件里的收录指令、各家对冲突的处理,各有各的口径。做多引擎的站要分别查一遍各家文档。 ## 为什么样本里meta形式的CSP在内页是0,首页却有11个? 因为首页和内页往往由不同的东西生成。首页更可能是单独做的落地页,有人手工写过head;内页由模板批量输出,模板里没有这一段。11这个数字本身也不大,占首页样本的6.5%左右。 顺带说,这11个站的meta里都没写frame-ancestors,写的是脚本来源和样式来源那些meta支持的指令。所以它们不属于本文说的"写错层",属于选了一个能力较弱但合法的位置。 ## 如果CDN和源站都发了同一个头,会怎样? 看CDN的配置模式。有的是覆盖,有的是追加,有的是源站有就不加。CSP这个头比较特殊:规范规定多条策略同时生效、取交集,也就是每一条都得放行这个请求才算放行。所以两层各发一条的结果通常是变得更严,而不是后一条覆盖前一条。 这件事在本文的实验里意外撞见过一次:线上版本的测试页发出去的响应里有两条CSP,一条是脚本自己写的,一条是服务器配置里的。两条都生效,取的是交集。 ## 怎么知道我的响应头是哪一层加的? 逐层剥。先直连源站绕过CDN,看头少了哪些;再关掉应用层的中间件,看还剩什么。剩下的那部分是Web服务器配置给的。样本里那些整齐划一的安全头,绝大多数是平台或者CDN统一下发的,站点自己配置文件里一行都没有。 ## 权威参考资料 ## 重复的meta标签,浏览器和搜索引擎各按各的规矩挑 - URL:https://zhangwenbao.com/duplicate-meta-tag-first-declaration-wins-audit.html - 分类:技术SEO - 发布:2026-08-22 | 更新:2026-08-22 - 摘要:同一个字段在head里写两遍,谁算数?七类元标记的裁决规则完全不同,本文用真实浏览器逐一验证,并给出三档整改优先级与一段可直接接进流水线的检查脚本。 - 关键词:技术SEO,meta标签,HTML解析,页面审计 > **TLDR**:摘要:337份首页快照里,25.0%的页面把同一件事声明了不止一次,20.2%的页面两条声明说的还不一样。这些重复不是抓取时的偶然——间隔两天的两次快照,166个站的重复清单一条不差。真正麻烦的是裁决规则:编码取第一条,标题取第一条,机器人指令取并集里最严的那条,站点验证码几条同时有效,规范网址多写几条反而可能一条都不算。浏览器实测把这几种结果逐个跑了出来,包括一个把三条声明赶出head的div。文中给出重复率与冲突率的完整口径、七类字段各自的裁决方式、以及一条能在自己站上跑完的自查命令。 > 摘要:337份首页快照里,25.0%的页面把同一件事声明了不止一次,20.2%的页面两条声明说的还不一样。这些重复不是抓取时的偶然——间隔两天的两次快照,166个站的重复清单一条不差。真正麻烦的是裁决规则:编码取第一条,标题取第一条,机器人指令取并集里最严的那条,站点验证码几条同时有效,规范网址多写几条反而可能一条都不算。浏览器实测把这几种结果逐个跑了出来,包括一个把三条声明赶出head的div。文中给出重复率与冲突率的完整口径、七类字段各自的裁决方式、以及一条能在自己站上跑完的自查命令。 8月17日Google那边有个说法挺有意思:同一件事实,把主语和宾语调换位置写,AI给出的答案会跟着变。Search Engine Journal转述的原话 (https://www.searchenginejournal.com/google-subject-object-entity-order-affects-ai-answers/586089/)是,实体出现的先后顺序会影响模型对关系方向的理解,所以文档里怎么排,机器就怎么读。 顺序影响结果,这件事在网页上比在句子里发生得早得多,也直白得多。 一个页面的head里,同一件事被写两遍是很常见的。两个站点验证码、两条主题色、两条社交分享图、偶尔还有两个标题标签。写的人多半不知道自己写重了——一条是主题模板给的,一条是插件给的,还有一条是营销部门临时插进来的代码片段带的。 浏览器不会报错,搜索引擎也不会给你发邮件。它们只是安静地挑一条用,然后把另一条丢掉。重复本身不是错误,重复是把决定权交了出去。 更麻烦的是,这个交出去的决定权,落在了一套很不统一的规则手里。有的字段取第一条,有的取最严的,有的干脆全部作废,还有的几条同时算数。这几条规则分别写在HTML规范、搜索引擎的帮助文档和各家平台的协议说明里,没有哪一份文档把它们并排列出来过。 于是就出现了一种很典型的状况:一个页面上有三处重复,其中一处完全无害,一处会让展示效果变成你没想要的样子,还有一处会改变索引行为——而做这个站的人,三处都不知道。 保哥拿两个时间点的首页快照做了一次普查,337份文档、17423条声明,把每一类声明数了一遍,又用浏览器把几种典型的重复现场跑了一遍,看它到底挑走了哪一条。 ## 一个页面里把同一件事说两遍,到底有多常见? 样本是188个海外品牌站的首页,分两个时间点各抓一次:8月14日凌晨一次,8月16日下午一次。剔掉响应体不足2000字节的失败样本,两次分别剩169份和168份可解析文档。 统计口径只看head里那些语义上应该唯一的声明:字符编码、标题、描述、机器人指令、规范网址、各类社交属性、各家平台的站点验证码,以及html标签自己的语言属性。脚本、样式、注释、noscript和template内部的内容全部先抹掉再统计,免得把JavaScript字符串里的假标签数进来。 ## 这次没有算什么 口径先说清楚,免得后面的数字被误读。 没有算JavaScript运行之后才插进去的声明。抓到的是服务端吐出来的原始HTML,前端框架在客户端补的那部分不在里面。这会让重复率被低估——不少站的元信息是脚本动态写进head的,跟服务端输出的那份撞车。要覆盖这一层得用无头浏览器渲染完再数,成本高一个数量级。 没有算响应头里的同名字段。头和文档谁压过谁是另一件事,本文只在编码那一节碰了一下。 没有算语义相同但字段不同的重复。标题标签、社交分享标题、结构化数据里的名称,三个字段说的是同一件事,它们互相不一致的时候不算"重复声明",但后果一样麻烦。这一类要单独量。 没有把值只差大小写或者尾部斜杠的当成冲突处理——实际上算了,但要知道这里面有噪音。fahertybrand.com的两条主题色是#fcfaf6和#FCFAF6,严格说是同一个颜色,脚本按字符串比对判成了冲突。71条冲突里这类占2条。 ## 四分之一的首页至少重了一处 口径 | 8月14日快照 | 8月16日快照 | 可解析文档 | 169 | 168 | head声明总条数 | 2936 | 2919 | 每篇声明数中位值 | 17 | 18 | 单篇最多 | 43 | 43 | 至少一处重复的文档 | 42(24.9%) | 42(25.0%) | 多出来的声明条数 | 110 | 110 | 至少一处值冲突的文档 | 34(20.1%) | 34(20.2%) | 值冲突的条数 | 71 | 71 | 四分之一。这个比例比我预想的高,但更让人意外的是它有多稳。 ## 两次快照的重复清单一条不差 两次抓取相隔约63小时,中间隔了一个周末。166个站两次都拿到了完整首页,把每个站的重复字段列成集合逐一对照,166个站全部完全一致,一个都没变。 这个百分之百有两层意思。一是这些重复不是抓取时的网络抖动或者页面随机渲染造成的,它们固化在模板里,天天如此。二是这套测量的尺子本身是准的——如果脚本的解析有随机性,两次结果不可能完全对上。 顺带一个细节:同期字符编码声明的字节偏移量有19个站变了。页面内容长度天天在变,偏移量跟着浮动很正常,但重复的字段集合纹丝不动。会动的会动,不该动的不动,这个对照本身就说明尺子没歪。 ## 内页比首页重得更厉害 为了知道首页是不是特例,另外拿了一批内页做对照:113个站的674个内页,多数是产品页和集合页。同一套脚本跑下来,至少一处重复的文档占37.5%,值冲突占30.1%,比首页的25.0%和20.2%都高出一截。 差距的来源不难猜。首页通常是单独做的模板,改动少、盯的人多;产品页是批量生成的,一个字段写重了就是几千个页面同时重。样本里aloyoga.com的6个产品页每一个都有3条分享图声明,指向同一件商品的不同角度照片;glossier.com的产品页分享图宽高写了3组,1374和1377来回跳。 这也解释了为什么首页体检往往过关而站点整体不过关。抽样只抽首页,等于专挑班里成绩最好的那个学生去参加家长会。 ## 顺带量到的三处缺席 数重复的时候顺手也数了缺席,有三个数字比重复率更刺眼。 规范网址:168个首页里48个完全没写,占28.6%;116个自指,4个指向别的地址。首页不写这个字段风险有限,它通常就是站点根地址。但674个内页的缺失率是11.1%,说明电商模板在内页上确实做了处理,首页反而被漏掉了。 H1标签:能完整取到body的55份首页里,39份一个H1都没有,占70.9%。现代电商首页顶部是轮播横幅,标题在图片里或者用div加样式做成大字,视觉上完全看不出少了什么。内页样本这个比例是50.5%。这件事的影响没有十年前那么大,但语义化标签对SEO的真实影响 (https://zhangwenbao.com/semantic-html-tags-seo.html)那篇量过,它在结构提取和辅助技术上仍然有用。 结构化数据:169份首页里76份一块都没有,占45.0%;48份一块,30份两块,12份三块,4份四块。在AI摘要越来越依赖实体识别的今天,这个缺口比多写一条主题色严重得多。想查自己站上有几块、字段缺什么,一次扒清页面五种格式的结构化数据 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)那套办法可以直接套。 ## 重复和冲突不是一回事,差在哪里? 110条多余的声明里,只有71条属于值冲突。剩下的39条是同一个值写了两遍,纯属冗余,谁赢都一样。 这两件事的严重程度差得很远,混在一起谈就没法排优先级了。 ## 写重了但值一样:无害 marinelayer.com的首页有两条规范网址声明,指向的地址完全相同。产品页也一样,抽查的6个产品页每一个都是两条相同的规范网址。这属于模板里两个位置都输出了同一个变量,看着别扭,实际没有后果。 字符编码声明重复7个站,值全都一致。描述重复2个站,值一致。这些都归到冗余那一栏。 ## 写重了值还不一样:要看字段 71条值冲突分布在9类字段上,密度最高的三类是站点验证码、社交分享图和主题色。 字段 | 有该声明的站 | 总条数 | 写重的站 | 值冲突的站 | Google站点验证码 | 54 | 88 | 16 | 16 | Facebook域名验证码 | 26 | 37 | 6 | 6 | 主题色 | 70 | 75 | 5 | 5 | 社交分享图 | 91 | 95 | 3 | 3 | 分享图宽高 | 52 / 50 | 55 / 53 | 2 / 2 | 1 / 1 | 视口设置 | 163 | 165 | 2 | 1 | 机器人指令 | 62 | 65 | 2 | 2 | 字符编码 | 141 | 169 | 7 | 0 | 描述 | 133 | 135 | 2 | 0 | 规范网址 | 120 | 121 | 1 | 0 | ## 七个值得单独看一眼的现场 把71条冲突里最有代表性的几个摊开,比看汇总表直观。 gymshark.com的主题色:一条纯黑,一条纯白。多半是想同时照顾深色和浅色两种系统外观,但这个字段的定义 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta)不支持这种写法——要按外观切换得用媒体查询属性单独声明。现在的结果是永远取第一条,纯黑。 laneige.com和sulwhasoo.com的分享图:同一张图,一条带www一条不带。这两个站同属一个韩国美妆集团,用的是同一套系统,同一个毛病复制了两遍。域名规范化做过了,老配置没清。 kotn.com的分享图:三条声明指向三张不同的图,配套的宽高写了800和600两组值。第一条图配的是第一组尺寸还是第二组,没人说得清。社交平台按第一条取图,尺寸信息却可能取到另一条,预览卡片的裁切就会歪。 traeger.com的视口设置:两条,一条是width=device-width, initial-scale=1,一条是initial-scale=1.0, width=device-width。顺序不同、写法不同,语义完全一样。这属于两套模板拼在一起,谁也没删谁。 cotopaxi.com的Facebook页面关联:三条,三个不同的页面ID。这个字段本身支持多值,写成一条用逗号分隔也行,写成三条也行,不算错。 innisfree.com的Naver验证码:两条,两个不同的值。韩国市场的搜索引擎验证,两个团队各验了一次。 vaude.com的状态栏样式:一条写black,一条写none。none不是这个字段的合法取值,写了等于没写;即便合法,也轮不到它,第一条已经定了。 ## 验证码那16个站其实没做错 站点验证码是个特例。一个域名可以有多个人各自验证所有权,市场部一个、代运营一个、原来做站的外包再留一个,几条并存是设计上就允许的。bellroy.com写了3条,fromourplace.com写了4条,avocadogreenmattress.com的Facebook域名验证写了5条。这些不算病。 把这一类剔掉之后,真正需要处理的值冲突剩下18个站左右。比例一下从20.2%掉到11%上下。先分清哪些重复是设计允许的,再谈治理,能省掉一多半工作量。 ## 值不一样的时候,浏览器到底挑哪一条? 普查告诉你有多少页面在冲突,但冲突之后谁赢,得让浏览器自己回答。 保哥在本机起了一个最小的PHP服务,每个测试地址只输出十几行HTML,专门制造一种冲突,然后用真实的Chromium内核加载,读它解析完之后的结果。为了避开线上服务器会自动补齐响应头的干扰,整套实验都在本地跑,服务端的字符集自动追加也关掉了。 ## 为什么不能在线上测 第一版实验是直接扔到线上服务器跑的,结果一看响应头就知道不行:想制造一个不带字符集的响应头,PHP自己补了一个,nginx又补了一个,压根做不出那个场景。更热闹的是安全策略字段——我在脚本里发了一条,nginx的站点配置里本来就有一条,同一个响应里出现了两条同名的头。 这个小插曲本身是个提醒:你以为你在控制响应,实际上你只是链条上的一环,前后各有人往里加东西。所以实验挪回本机,用一个不做任何加工的最小服务,才能保证测的是浏览器的行为,不是中间层的行为。 ## 每一组都配了对照 制造冲突之后如果结果符合预期,很容易就此收工。但这种收工方式最容易骗自己——万一浏览器根本没读那个字段,而是靠别的路径得出了相同的结论呢? 所以每一组都加了对照。测编码的那组,额外做了一个页面:不写任何编码声明,正文照样放中文。如果这个页面也能正常显示,说明浏览器在做内容自动识别,前面所有结论都得推翻。实测结果是它乱码了,返回的编码是windows-1252——浏览器没有自作主张,它只认声明。尺子成立,后面的结论才站得住。 ## 两个字符编码声明:第一条赢 页面里先写,紧接着写,正文放一段中文。加载之后document.characterSet返回windows-1252,中文变成了那串经典的层级è£å†³。 第一条赢了。而DOM里两个标签都在,一个没少。被忽略不等于被删除,它就摆在那儿,只是没人再看它一眼。 ## 两个标题标签:第一条赢 同一个head里写两个标题标签,第一个是第一个标题,第二个是第二个标题,另外配两条描述。结果document.title返回第一个标题,querySelector取描述拿到的是第一条。标题标签的数量统计仍然是2。 这跟规范里的定义是对上的:文档标题这个属性的定义 (https://html.spec.whatwg.org/multipage/dom.html#dom-document-title)写的就是取文档中第一个标题元素。有意思的是这条规则不限于head——把标题标签写进body、head里一个都不留,取到的仍然是body里那个。 ## 两个规范网址:浏览器不管 写两条指向不同地址的规范网址声明,浏览器把两条都留在head里,不做任何裁决。它本来也不需要——这个字段不是给浏览器用的。裁决权在搜索引擎那边,而Google的公开说法是多条规范网址会被当成一个混乱信号,它可能全部忽略、自己另选一个。关于这个字段本身的性质,canonical是提示不是命令这件事 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html)值得单独看一遍,它解释了为什么写对了也不一定被采纳。 ## 注释掉的那条不算数 顺手做了个对照:把一条规范网址用HTML注释包起来,后面再写一条真的。DOM里只有真的那条。这是意料之中的结果,但对照组的意义不在于它出人意料,而在于它能证明前面几组不是脚本自己看花了眼。 ## 被忽略的那条,工具还是能看见 这里有个容易吃亏的地方。浏览器忽略了第二条编码声明,但DOM里两个标签都在;任何一个用选择器去数标签的检测工具,都会告诉你这里有两条。工具报的是写了几条,浏览器给的是用了哪条,两者说的不是一回事。 做审计的时候这个区别很要紧:工具报出来的重复清单,要先过一遍裁决规则才知道哪些真的有后果。反过来也成立——工具报只有一条的时候,那一条也未必生效,它可能掉在了body里。 这也是为什么本文的普查和浏览器实验必须分开做。普查回答的是"页面上写了什么",用脚本数字节就够;实验回答的是"最后哪一条算数",非得让真正的解析器跑一遍不可。把两者混在一起,得到的既不是源码的事实,也不是渲染的事实,而是一个谁也对不上的中间态。 顺便说一句,浏览器给出的答案也只是三个答案之一——搜索引擎有自己的解析器,社交平台的抓取器又是另一套实现。浏览器的结论可以当作最可靠的参照,但不能当成唯一的裁决。 ## 一张表看完六组实验 制造的冲突 | 浏览器给出的结果 | 能推出什么 | 两条编码声明,先ISO后UTF-8 | 按第一条解码,中文乱码 | 先到先得,且不可挽回 | 两个标题标签 | 文档标题取第一个 | 与规范定义一致 | 两条描述 | 选择器命中第一条 | 同上 | 两条不同的规范网址 | 两条都留在head,不裁决 | 裁决权不在浏览器 | 注释掉的一条加真的一条 | 只有真的那条进DOM | 对照组,尺子有效 | head里没有标题、body里有 | 文档标题取到body里那个 | 取第一个,与位置无关 | ## 为什么是第一条赢,而不是最后一条? CSS里后写的规则覆盖先写的,写惯了样式表的人很容易把这个直觉带到head里来。head里恰好反过来。 ## 解析器是流式的,它没有回头的习惯 HTML解析器从字节流的头部一路往下读,读到一个它关心的标签就当场处理。WHATWG规范里确定字符编码那一节 (https://html.spec.whatwg.org/multipage/parsing.html#determining-the-character-encoding)写得很清楚:一旦确定了编码,后面再出现的编码声明就被忽略。 标题也是同一个思路。规范对文档标题的定义直接写成了取第一个标题元素,不是取最后一个,也不是取head里的那个。 说到底,先到先得是流式处理最省事的实现方式。你要让最后一条赢,解析器就得把整个文档读完才能开始渲染,那样谁也受不了。 ## 但不是所有字段都遵守先到先得 机器人指令是个反例。一个页面里出现多条机器人指令时,Google给出的处理方式 (https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag)不是挑一条,而是把它们合并,冲突的部分取限制更严的那个。样本里ikea.com的产品页就是这种写法,一条写着允许索引和跟踪,另一条写着图片预览尺寸不限,两条合起来才是完整意图,谁也没被丢掉。 byredo.com的首页写了3条机器人指令,suitsupply.com写了2条,逐条看都不构成真冲突。整个样本里没有出现一例同时写着允许索引和禁止索引的页面,这算个好消息——最危险的那种冲突,大站基本不犯。 ## 五种裁决方式,没有一处写在一起 字段 | 多条并存时的结果 | 依据 | 字符编码 | 取第一条,其余忽略 | HTML解析算法 | 标题 | 取文档里第一个 | HTML规范对文档标题的定义 | 描述 | 实现上取第一条,但搜索引擎可能整条不用 | 各家自行处理 | 机器人指令 | 合并,冲突处取更严的 | Google搜索中心文档 | 规范网址 | 可能全部忽略,由搜索引擎另选 | Google搜索中心文档 | 站点验证码 | 多条同时有效 | 各平台设计如此 | 社交分享图 | 消费方各自取第一条或自行挑选 | Open Graph协议 | 这张表是我拼出来的,不是从哪份文档里抄的。它们分散在HTML规范、Google的帮助文档、Open Graph的协议说明和各家平台的验证指引里,没有任何一个地方把它们放在一起讲过。 所以真正的风险不是你写重了,而是你以为所有字段的裁决方式都一样。 ## 五种裁决方式背后是五种不同的处境 这几条规则看着零散,其实各有各的道理,倒不是谁拍脑袋定的。 取第一条的那两个字段,编码和标题,都必须在解析早期就定下来。编码定不下来后面的字节没法解释,标题定不下来标签栏没东西可显示。这类字段的共同点是晚了就来不及,所以规范干脆规定先到先得。 合并取严的那个字段是机器人指令。它管的是能不能收录,这是个不可逆的动作——错误地不收录还能改回来,错误地收录了,内容已经散出去了。这种场合下取更保守的那条是唯一安全的选择。 可能全部忽略的是规范网址。它本来就只是一个提示,Google要在几十个信号里综合判断哪个是主版本。你给两个互相矛盾的提示,等于什么都没提示,它当然可以自己另选。 多条同时有效的是各平台的所有权验证。这个字段的语义不是"这个页面属于谁",而是"这些人都能证明自己和这个域名有关系",本来就是多值的,写几条都不冲突。 最后一类是社交属性。协议允许结构化属性重复,具体挑哪条交给消费方,于是不同平台的行为就不一样了。这一类的裁决权已经不在页面这边,属于下一个话题。 ## 一个反直觉的推论 既然是先到先得,那把重要的声明写在前面就行了吧——这个想法只对了一半。 对的部分:同一个字段写重的时候,你确实应该保证想要的那条排在前面。错的部分:不同字段之间没有优先级关系,把描述提前不会让它更重要。真正跟位置有关的只有两件事,一是同字段的先后,二是它有没有掉出head。除此之外,head里的顺序在SEO上没有任何额外含义。 我见过有人把整个head按"重要性"重排了一遍,指望排名跟着动。结果当然是什么都没发生。位置决定的是谁生效,不是谁更重要。 ## head里放一个div,会发生什么? 前面几组冲突好歹还有个裁决过程。下面这种是连参赛资格都没有。 ## 三条声明被一个div请了出去 测试页面这样写:head里先是字符编码和标题,然后插一个div,div后面才是描述、规范网址和机器人指令,最后正常闭合head再写body。 加载之后数一遍:head里的meta只剩1条,body里多出2条meta和1条link,head里的规范网址数量是0。div之后的三条声明全部落进了body。 原因是HTML规范给head定了一份允许出现的元素清单 (https://html.spec.whatwg.org/multipage/semantics.html#the-head-element),只有base、link、meta、noscript、script、style、template和title这八种。遇到清单外的元素,解析器认为head已经结束了,当场切到body。写在后面的那些声明不是被忽略,是被搬了家。搜索引擎读不读body里的这几条,各家说法不一,但至少你原本的意图是让它们待在head里。 这个现象之前专门量过一次,工具说在head浏览器说在body (https://zhangwenbao.com/head-boundary-canonical-parsed-into-body-seo.html),那篇讲的是检测工具和浏览器的分歧;这里补上的是它在真实站点上的发生率。 ## 真实站点上有多少个这种div 337份快照里踩到这个坑的有7份,涉及4个站:aliexpress.com在第2个字节的位置就出现了一个a标签,flyingtiger_com在第61300字节插了个div,temu.com直接在第6个字节开了body,vaude.com在第6405字节插了div。 比例是2.4%,不算高。但vaude.com的产品页因此掉出去了三条社交属性——分享标题、分享图和分享地址。它的商品被分享到社交平台时,抓到的信息不完整,这个损失是实打实的。 ## 还有一类声明是自己躲起来的 noscript和template这两个标签里的内容不参与正常解析。样本里34个站的这两种容器里塞着173条声明,看上去挺吓人。 逐条拆开之后,164条是样式表链接——这是给禁用JavaScript的访客准备的降级方案,本来就该放在那儿。剩下9条里有2条Google站点验证码和几条电商平台的配置字段。又一个虚惊:数字很大,真正有问题的只有个位数。 内页那批更极端,502条藏起来的声明全部是样式表链接,一条杂质都没有。这种时候报告里那个总数就是个纯噪音,写进汇报材料只会让人白紧张一场。 ## 断点在第几个字节,决定了损失有多大 四个站的断点位置差得很远:aliexpress.com在第2字节,temu.com在第6字节,vaude.com在第6405字节,flyingtiger.com在第61300字节。 断点越靠前,被赶出去的声明越多。但反过来说,断点在第2字节的站,它的head实际上从一开始就不存在,所有元信息都在body里——这种页面通常是单页应用的骨架,元信息本来就打算由脚本在运行时补,服务端吐出来的这份只是个壳。 断点在中间的那种才最容易被忽略:前面一半声明好端端在head里,后面一半掉了出去,从源码上看毫无异样,缩进都是对的。vaude.com就是这种,掉出去的正好是三条社交属性。 ## 被搬进body的声明,搜索引擎还认吗 这是个没有统一答案的问题,得分开说。 Google在自己的文档里明确表示元标记应当放在head里,同时也说过它有能力处理一部分位置不规范的写法。规范网址这个字段Google讲得最直白:只有head里的那条会被采纳,body里的会被忽略。机器人指令的口径类似。至于社交平台,Facebook和Twitter的抓取器实现上通常整篇扫描,body里的属性也能被读到,所以vaude.com那几条掉出去的分享属性未必真的失效。 换句话说,同一个位置错误,对不同的读取方后果不同:搜索引擎那边可能全废,社交平台那边可能没事。这已经不是"位置决定"的问题了,是"谁在读"的问题——那是另一条线。 ## 那些把编码声明写到十几万字节之后的站,为什么没乱码? 普查时有一项数据特别扎眼:168个首页里,字符编码声明的字节偏移量中位值是72,很靠前;但有33个站超过了1024字节,最远的一个在第521316字节。 ## 96.4%的前置字节是内联脚本 站点 | 编码声明的字节位置 | 它前面的脚本字节数 | 脚本占比 | functionofbeauty.com | 521316 | 521042 | 99.9% | getquip.com | 156818 | 156279 | 99.7% | fromourplace.com | 151756 | 151249 | 99.7% | monos.com | 55914 | 21479 | 38.4% | decathlon.com | 9470 | 458 | 4.8% | shopify.com | 1986 | 1858 | 93.6% | 33个站的中位数是:编码声明之前有18974字节的内联脚本,占前置内容的96.4%。把编码挤到后面去的不是别的,就是那一大坨内联进来的初始化数据、同意管理平台的配置和状态预填。 ## 它们全都被响应头接住了 这33个站,我逐个去查了同期抓到的响应头:33个全部带着字符集声明,没有一个裸奔。147个能配上响应头的首页里,143个头里写着UTF-8,4个写着ISO-8859-1,19个没写。 换句话说,那33个页面里的编码声明处在一个很尴尬的位置——它有没有生效根本无所谓,因为上一层已经把这件事定了。这个字段看起来在工作,实际上一直没在工作。 顺着这条线往下还有一串更细的机制问题:解析器到底扫多少字节、检测工具和浏览器的分界在哪里。乱码的分界不在1024字节那篇 (https://zhangwenbao.com/charset-declaration-byte-window-parser-encoding-seo.html)把这一层单独拆开讲过,这里就不重复了。真要排查乱码,从字节层面看一眼实际编码 (https://zhangwenbao.com/hex-codec-utf8-byte-encoding-charset-debug-guide.html)比猜要快得多。 ## 那4个声明ISO-8859-1的响应头 147份配上响应头的首页里,143个头里写UTF-8,4个写ISO-8859-1。这4个站值得单独看一眼,因为响应头的优先级在文档之上——如果它们的页面里有非拉丁字符,而文档里的声明写的是UTF-8,那么头会赢,页面会乱。 本地实验里我把这个场景复现了一遍:响应头声明ISO-8859-1,页面里写UTF-8,正文放中文。浏览器返回的编码是windows-1252,中文变成了层级è£å†³那一串。反过来,头写UTF-8、页面写ISO-8859-1,结果是UTF-8,正常显示。 两个方向都测了,结论一致:头赢,而且赢得彻底,文档里的声明连争一下的机会都没有。那4个站如果内容全是英文,眼下不会出事;哪天上了一个带重音符号的法语产品名,问题就来了。 ## 没有兜底的那19个站 还有19个首页的响应头里根本没写字符集。这19个站完全靠文档里的声明活着。它们目前也没出事——因为编码声明都写在很前面。 这就构成一个有意思的分布:编码声明写得靠后的站,全都有响应头兜底;没有响应头兜底的站,编码声明全都写得靠前。两种配置各自成立,但没有人是靠运气活着的。这个巧合本身说明,那些把编码挤到十几万字节之后的站,用的是同一类电商平台,而那类平台的服务端默认就会发字符集。 换个说法:33个站的编码声明看起来放错了地方,实际上是平台替它们兜住了。这不是它们做对了什么,是它们碰巧在一个做对了的平台上。 ## 这些重复是谁写进去的? 知道了谁赢,还得知道这局是怎么开起来的。337份快照里的重复声明,来源基本能归成四类。 ## 主题和插件各输出一遍 最常见的一类。建站主题自带一套元信息输出,装的SEO插件又输出一套,两边都不知道对方存在。这类冲突有个特征:两条声明在字节位置上离得很近,因为它们都在head的同一个渲染阶段被拼进去。bellroy.com那3条站点验证码分别在1717、1810、1903字节,间隔不到100字节,一看就是同一段模板循环出来的。 CMS装了SEO插件冒出两个canonical怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)那篇把这一类的排查和收敛路径讲全了,这里不再展开。 ## 营销代码片段带进来的 allbirds.com两条Google站点验证码,字节位置分别是290和23763,隔了两万多字节。dreametech.com那两条在149244和162565。离得这么远,说明它们不是同一段代码生成的——一条在模板头部,另一条大概率是某个营销工具的代码块自带的。 ## 建站平台自己注入的那一份 用SaaS建站平台的站点还有第四个来源:平台本身。样本里52个站带着同一家电商平台的三个私有字段——数字钱包标识、结账接口令牌、还有一个会话标记,站主在后台完全看不到它们。 这类字段不会跟你的内容字段冲突,但它们会把head撑得很长,把你自己的声明往后挤。前面说的33个编码声明超过1024字节的站,绝大多数是这种情况:不是站主把编码写晚了,是平台在它前面塞了十几万字节的初始化数据。 ## 不同环境的配置各留了一份 laneige.com和sulwhasoo.com的分享图各写了两条,一条带www,一条不带。同一张图,两个域名写法。这通常是站点做过域名规范化,老配置没清干净。 gymshark.com的主题色更直白:一条是纯黑,一条是纯白。深色模式和浅色模式各留了一条,但这个字段不支持这种写法,浏览器只会取第一条,于是永远是黑的。 ## 拼错的那一类 有一个站的兼容模式声明写成了x-ua compatible,中间的连字符掉了。这种拼错既不会报错也不会生效,静静地在那儿待着。样本里这类拼写不规范的声明有2条。 同一份样本里还有几个更奇怪的写法:bigcommerce.com把6条社交关联地址写成了name="og:see_also"——社交属性该用property而不是name,写成name之后既不属于社交协议,也不是任何一个已知的元标记,属于凭空造了个字段出来。这类东西不会有人来告诉你写错了,它就这么挂着。 ## 怎么分辨一条重复是模板给的还是外挂给的 有个很土但很好使的判据:看两条声明的字节距离。 同一段模板循环出来的,间隔通常在几十到几百字节;两个独立来源拼进去的,间隔常常是几千甚至几万字节。前面那两个例子——bellroy间隔不到100字节,allbirds隔了两万多字节——就是这两类的典型。 知道来源之后再决定找谁改。模板里的重复找前端,一次改完;外挂带进来的得找营销或者投放那边,因为那段代码往往是从第三方后台复制过来的,改模板没用,下次发版又回来了。 还有第三种情况:两条都不是你写的。用建站平台的站点,平台会往每个页面注入自己的一套字段,你在后台看不到它们,只能在源码里看见。这类东西改不了,只能记下来,在做审计的时候排除掉,免得每次体检都被同一条告警骚扰。 ## 哪些重复必须今天改,哪些可以先放着? 把前面的数据揉在一起,处理顺序其实很清楚。别一上来就搞大扫除,先按后果排。 ## 第一档:会改变索引行为的 机器人指令冲突、规范网址指向不同地址、编码声明值不同——这三类直接影响页面能不能被收录、被收录成哪个地址、正文能不能被正确读出来。发现一条改一条,不用排期。 判断标准很简单:如果两条声明说的话,会让搜索引擎做出不同的动作,那它就是第一档。 这一档还有个附加动作:改完之后要验证一次,而且要用浏览器验证,不能只看源码。因为你改掉的可能是那条本来就没生效的,真正生效的那条还在原地。 ## 第二档:会改变对外展示的 分享标题、分享图、分享地址、主题色。这些不影响收录,但影响页面被转发出去时长什么样。gymshark那个黑白冲突已经存在很久了,页面照常打开,只是标签栏的颜色永远是它没想要的那个。这一档可以攒到下个迭代一起改。 分享图有个额外的坑:写多条时消费方通常取第一条,而很多站的第一条是logo,第二条才是真正想推的主图。生成分享图这件事本身也有不少细节 (https://zhangwenbao.com/og-image-maker-linebreak-surrogate-square-crop-guide.html),顺序只是其中之一。 ## 第三档:冗余但无害的 值相同的重复、多个站点验证码、noscript里的样式表链接。这些可以只记在技术债清单上,什么时候顺手清什么时候清。把第三档当成第一档来处理,是很多技术SEO排期表最后没人执行的原因。 ## 一个例外:位置问题优先于重复问题 如果head里有那个div,先处理它。因为它一次性把后面所有声明的位置都毁了,改一处等于修好三条。而重复通常只影响一个字段。 ## 按这三档排,337个快照里剩多少活 拿本文的样本自己走一遍这个排序:71条值冲突里,第一档只有机器人指令那2个站,而且逐条看下来都不构成真冲突,实际是0;第二档是分享图3个站、分享图尺寸2个站、主题色5个站、视口1个站,合计11个站;剩下的全归第三档。 也就是说,看起来20.2%的页面有冲突,真正需要动手的只有11个站,占样本的6.5%左右。如果一开始就把71条打成一张整改表发给前端,那张表大概率会躺到年底。 这个收敛过程本身比结论重要:先按后果分档,再看每一档还剩几条,最后才决定要不要立项。技术SEO的清单如果不做这一步,它的长度只会吓退执行的人。 ## 改之前先确认这一条真的归你管 技术SEO的排期表最常见的失败方式,不是排错了顺序,是排了一堆自己改不动的事。 动手之前先分三类:模板里的、插件里的、平台注入的。第一类自己就能改;第二类要看插件有没有开关,很多SEO插件的元信息输出是可以整体关掉的,关掉之后由主题统一出;第三类基本没辙,记进白名单别再报了。 另外有个顺序上的小坑:先关插件再改模板,中间会有一段时间某些字段完全没有输出。如果站点流量不小,这个空窗期最好挑在低峰,或者干脆先在模板里补齐、确认输出正确了,再去关插件那一路。技术SEO一堆问题先修哪个 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)那篇给的排序框架,在这种时候比凭感觉靠谱。 ## 修不动的时候,换一条路 遇到模板改不动的情况——外包做的、发版流程长、或者干脆源码不在自己手上——可以反过来从插件那一侧收敛:把插件的元信息输出整体关掉,只留模板一路;或者反过来,让模板不输出,全交给插件。关键不是选哪一路,是只留一路。 切换的时候有个顺序上的小坑:先关掉一路再补另一路,中间会有一段时间某些字段完全没有输出。稳妥的做法是先让新的那一路把字段补齐、在预发环境确认输出正确,再去关旧的那一路,别让线上出现空窗。 ## 怎么在自己站上把这些问题查出来? 不需要买工具。下面这些命令在任何一台能跑curl的机器上都能用。 ## 数一数关键字段各写了几遍 curl -s https://example.com/ \ | grep -o -iE '<(meta|link)[^>]*(canonical|name="robots"|name="description"|charset)[^>]*>' \ | sort | uniq -c | sort -rn 输出里每一行前面的数字就是出现次数。大于1并且内容不同的,就是要处理的对象。 ## 看编码声明落在第几个字节 curl -s https://example.com/ | head -c 2048 | grep -bo 'charset' 前面那个数字是字节偏移。查不到就说明它在2048字节之外,再配合下面这条看响应头有没有兜底。 curl -sI https://example.com/ | grep -i '^content-type' ## 查head里有没有不该有的标签 curl -s https://example.com/ \ | sed -n '1,/<\/head>/p' \ | grep -o -iE '<(div|span|p|a|img|iframe|button|dialog)\b' \ | sort | uniq -c 这条会有误报,因为内联脚本和样式里可能出现这些字符串。有输出就手工去看一眼源码,确认它是不是真的标签。 ## 用浏览器给出最终答案 命令行看到的是字节,浏览器看到的是结果。在控制台里跑这几行,拿到的是解析之后的真实状态: document.characterSet document.getElementsByTagName('title').length document.head.querySelectorAll('link[rel=canonical]').length document.body.querySelectorAll('meta').length 最后一行如果不是0,说明有声明掉进了body。这是最快的一个判断。想省事的话,现成的Meta标签检测器 (https://zhangwenbao.com/meta-checker-weighted-seo-audit-guide.html)能一次把整页的元信息拉出来打分,适合做批量初筛;页面结构分析那一套 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)则更偏标题层级和语义标签。 ## 批量跑一遍全站的关键页 单页查完还要看面。把要查的地址存成一个文本文件,一行一个,然后: while read -r u; do n=$(curl -s -m 20 "$u" | grep -c -iE ']*rel="?canonical') printf '%s\t%s\n' "$n" "$u" done < urls.txt | sort -rn | head -20 把第一列大于1的挑出来看。同样的写法换个正则就能查别的字段。这段脚本的价值不在于它多聪明,在于它跑一次的成本接近零,可以每周挂一次。 ## 把这条检查接进上线流程 比事后审计更省事的是不让它发生。在构建流水线里加一步:请求首页和三个典型内页,数几个关键字段的出现次数,超过1就让这一步失败。 #!/bin/bash FAIL=0 for u in "$@"; do html=$(curl -s -m 20 "$u") for pat in 'rel="?canonical' 'name="?robots' 'name="?description'; do n=$(printf '%s' "$html" | grep -c -iE "<(meta|link)[^>]*$pat") [ "$n" -gt 1 ] && { echo "DUP $n $pat $u"; FAIL=1; } done b=$(printf '%s' "$html" | sed -n '/<\/head>/,$p' | grep -c -iE ']*name="?(robots|description)') [ "$b" -gt 0 ] && { echo "INBODY $b $u"; FAIL=1; } done exit $FAIL 不到20行,覆盖了本文说的两类问题:写重了和掉出去了。把检查接进流程,比把问题写进文档有用得多——文档会被忘掉,流水线不会。 阈值可以按站点情况调。允许多个站点验证码的话,就把那个字段从循环里摘出去单独放行;有些平台会固定注入一条自己的声明,把它加进白名单,别让流水线天天为同一件事红一次。检查项的价值来自它红的时候确实有事,天天红的检查最后都会被人加个跳过。 要注意的是这段脚本用的是纯文本匹配,遇到内联脚本里出现同样字符串会误报。真要做严谨的解析,得用带HTML解析器的语言写,或者直接在无头浏览器里跑前面那四行JavaScript。日常巡检用文本版够了,误报手工看一眼就能排除。 ## 同一套判断,还能用到哪些地方? 重复声明只是一个具体场景。它背后那个问法能搬到很多地方去。 ## 四个问题 面对任何一条写在页面上的声明,可以顺着问一遍: 第一,这件事在我这个页面上一共被声明了几次?不只是同一个字段写了几遍,还包括同一件事换个字段说了几遍——标题说一遍,分享标题说一遍,结构化数据里的名称再说一遍。 第二,如果它们说的不一样,谁会赢?是取第一条、取最后一条、合并、还是全部作废?这个答案每个字段都不同,不能凭直觉。 第三,决定输赢的那个依据,跟我的意图有关系吗?如果答案是位置,那就跟意图无关——先写的赢,不是更对的赢。 第四,换一个读它的人,赢家会不会换?浏览器、Google、社交平台、AI爬虫,各读各的字段。 ## 为什么这套规则不可能统一 有人会问:既然这么乱,规范制定者为什么不统一一下? 因为这些字段根本不属于同一个体系。字符编码和标题是HTML自己的,规则写在HTML规范里;规范网址和机器人指令是搜索引擎定义的,规则写在各家的开发者文档里;社交属性是Facebook当年推的一套协议,后来被别家沿用;站点验证码是各平台自己的私有约定。 它们唯一的共同点,是都被塞进了同一个head。一个由四五拨人分别定义、又必须共处一室的空间,规则不统一是必然的,能各自跑起来已经不容易。 所以指望有朝一日出一份统一规范是不现实的。规范网址这个字段本身的跨页场景与冲突诊断 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)就是个例子:同一个字段在不同场景下的行为都不一样,跨字段就更别提了。能做的只有一件事:碰到一个字段,就去查一次它自己的规则,别用别的字段的经验去猜。 ## 把四个问题跑一遍要多久 对单个页面来说,前两个问题用一次curl加一次控制台就能答完,五分钟以内。第三个问题要查字段的规则文档,第一次查会慢,查过一次就记住了。第四个问题最费事,得换身份重新抓一遍。 实际排期的时候,前两个问题应该做成常规巡检,后两个问题在改版和换平台的时候各做一次就够。浏览器扩展那一类工具 (https://zhangwenbao.com/seo-website-technology-stack.html)能把第一个问题的成本压到点一下鼠标,适合日常随手看。 ## 能套上去的其他场景 机器人指令这件事在页面上写一遍、在站点根目录的规则文件里写一遍、还能在响应头里再写一遍,三层的关系不是覆盖而是各管一段。规则文件和页面指令什么时候用哪个 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)是必须先分清的前置问题。 响应头自己那一层里也有同样的毛病。142个站里108个在同一份响应里写了互相矛盾的字段 (https://zhangwenbao.com/http-response-header-self-contradiction-audit.html),那是同一层内部的冲突,跟本文这种页面内的冲突是一个道理。 对于那些压根没有head的地址——接口、订阅源、纯数据文件,声明只能写在响应头里。这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)是另一个独立的话题。 ## 同一件事换个字段再说一遍,也算重复 本文数的是同一个字段写了几遍。还有一种更隐蔽的重复:同一件事用不同字段各说了一遍,而且说的不一样。 一个首页可以有六个地方在自我介绍:标题标签、社交分享标题、推特卡片标题、页面上的H1、结构化数据里的名称、还有站点名称字段。它们本该指向同一个东西,但没有任何机制保证这一点,也没有哪个工具会因为它们不一致而报错。 这一类的裁决规则和本文讲的完全不同——不再是"谁排在前面",而是"读它的人取哪个字段"。搜索结果里显示的是标题标签,分享到社交平台显示的是社交标题,AI摘要里报出来的可能是结构化数据里那个名称。同一个页面,三个读者,三个名字。 这已经是另一条线了,值得单独量一次。 ## 写模板的时候多做一步 最省事的预防办法是在模板层做一次收敛:所有元信息只从一个函数出口输出,插件想加就往这个函数里注册,不许各写各的。这样重复在生成阶段就被拦住了,不用等上线之后再拿脚本去数。 做不到的话,退一步,在构建流程里加一条检查:拉一次首页和三个典型内页,数关键字段的出现次数,超过1就让流水线报警。这条检查写完不到20行,比事后审计划算得多。 ## 常见问题解答 ## 同一个页面写两条描述,Google会用哪一条? 实现层面浏览器取第一条。但Google对描述这个字段本来就不保证采用——它经常根据查询词自己从正文里摘一段。写两条最坏的结果不是选错,是两条都不用。真正决定展示效果的是描述本身写得怎么样 (https://zhangwenbao.com/meta-description-seo.html),不是写了几条。 ## 规范网址写了两条完全一样的,需要改吗? 不急。样本里marinelayer.com就是这个情况,7个页面全是两条相同的地址。值一样的时候不构成冲突信号,属于第三档冗余。但如果你的模板会在某些页面上让这两条取到不同的值,那就变成第一档了,得回去看生成逻辑。 ## 把编码声明放在head最前面,真的有必要吗? 有必要,但理由不是防乱码。33个把它写到很后面的站,页面全都正常显示,因为响应头替它们兜住了。放前面的真实好处是不依赖那个兜底——万一哪天CDN配置变了、或者页面被另存为本地文件,头就不在了。这是一条成本几乎为零的保险。 ## head里的div是怎么混进去的? 多数是第三方代码块自带的。同意管理平台、客服挂件、A/B测试工具,有些会在初始化时往当前位置插一个容器。如果这段代码被放在head里,容器就跟着进去了。排查办法是把head的源码从头看一遍,遇到第一个非法标签就是断点。 ## head里的声明顺序,会影响搜索排名吗? 不会。顺序只决定同一个字段的多条声明里哪一条生效,以及一条声明有没有掉出head。不同字段之间没有权重差别,把描述提到编码前面不会让它更受重视。 唯一跟顺序沾边、又确实有性能后果的是字符编码:把它写在最前面,解析器一开始就能确定怎么解释字节;写在很后面,解析器得先按默认编码往下走,遇到声明再回过头调整。这是渲染速度的事,不是排名的事。 ## 为什么七成首页没有H1也没出事? 因为搜索引擎早就不只靠这一个标签判断页面主题了。标题标签、正文首段、面包屑、结构化数据都在提供同样的信息。H1缺席更像是一个体检指标偏低,不是急症。真正要紧的是别出现另一个极端——样本里有一个站的首页有13个H1,那才是真的把信号搅浑了。 ## 动态渲染的站,这套办法还管用吗? 部分管用。本文的普查只看服务端吐出来的原始HTML,前端框架在客户端补进head的那些声明没算进去。对于纯客户端渲染的站,源码里可能什么都没有,元信息全靠脚本写。 这种情况下命令行那几条查不出东西,得改用浏览器控制台那四行——它们读的是渲染完之后的DOM,客户端补的那部分也在里面。两套办法配合起来看:命令行看服务端给了什么,控制台看最终变成了什么,中间的差额就是脚本干的事。 顺带一提,这个差额本身值得关注。搜索引擎的渲染有排队,脚本补的元信息不一定每次都能被及时读到;社交平台和多数AI爬虫压根不执行脚本,它们看到的只有服务端那一份。 ## 这些数据能代表中文站吗? 样本全是海外品牌站,主流是Shopify和几家企业级电商平台。中文站的技术栈不一样,重复的具体分布肯定不同。但裁决规则是浏览器和搜索引擎那边定的,跟站点在哪儿没关系。方法可以直接套,数字要自己重新量一遍。 ## 检测工具报的重复数,和实际生效的是一回事吗? 不是。工具数的是源码里写了几条,浏览器算的是最终用了哪条。两条编码声明在DOM里都存在,工具会报2条,而实际生效的只有第一条。反过来,掉进body的那条声明工具也可能照样计数,但搜索引擎那边可能根本不认。 做审计的时候,工具的输出应该当成线索而不是结论。拿到重复清单之后,先按字段查一遍裁决规则,再决定哪些进整改列表。 ## 把重复清干净,排名会涨吗? 大概率不会。这类问题的性质是消除不确定性,不是增加权重。清掉一条矛盾的规范网址,收益是搜索引擎不再需要猜你想要哪个地址;清掉一条重复的主题色,收益是浏览器标签栏的颜色变成你想要的那个。 把它当成体检项而不是增长项,预期会准得多。真正会换来流量变化的,是那些改完之后索引行为跟着变的字段——收录范围、规范地址归并,这两类才有可能在数据上看出来。 ## 只有一条声明,是不是就一定安全? 不一定。数量对了,位置还可能不对。样本里那几个站的head里插了div,后面的声明只有一条,但整条掉进了body。工具报"canonical: 1",看着完全正常。 所以查完数量还得查位置,在浏览器控制台跑一行document.head.querySelectorAll('link[rel=canonical]').length,返回0就说明那唯一的一条不在它该在的地方。 ## 权威参考资料 ## 表单字段的四件事:51个站的邮箱框,全写上的只有6个 - URL:https://zhangwenbao.com/form-field-declaration-audit.html - 分类:技术SEO - 发布:2026-08-21 | 更新:2026-09-09 - 摘要:同一个收邮箱的输入框,在51个独立站上有51种写法。有人写全了类型、代填、必填和名字,有人一个都没写,用户在手机上就得自己切键盘、自己一个字母一个字母敲邮箱。这篇按站逐个数了一遍,也给出了先改哪四处。 - 关键词:技术SEO,电商SEO,网页语义化 > **TLDR**:摘要:把55个独立站的191个页面逐页拆开,数了一遍每个输入框身上写了什么。同一个站里重复渲染的框先合并,最后剩下1902个控件、422个真要用户打字的字段。收邮箱的那一格有160个,分布在51个站上——写了type=email的86.9%,写了autocomplete=email的只有45.6%,四件事(类型、代填、必填、名字)全都写上的42.5%。按站算更难看:51个站里,所有邮箱框都写全的只有6个。整批数据里autocomplete出现最多的取值不是任何一个字段名,是off。 > 摘要:把55个独立站的191个页面逐页拆开,数了一遍每个输入框身上写了什么。同一个站里重复渲染的框先合并,最后剩下1902个控件、422个真要用户打字的字段。收邮箱的那一格有160个,分布在51个站上——写了type=email的86.9%,写了autocomplete=email的只有45.6%,四件事(类型、代填、必填、名字)全都写上的42.5%。按站算更难看:51个站里,所有邮箱框都写全的只有6个。整批数据里autocomplete出现最多的取值不是任何一个字段名,是off。 页面上绝大多数东西是站点在单向说话:标题在说、图片在说、价格在说。只有一个地方反过来——输入框。那是用户往里写字的地方,也是这一页上唯一一处需要页面提前交代清楚的地方:这一格要什么。 交代给谁?不是给用户。用户看一眼旁边那行小字就知道该填邮箱。要交代的是浏览器。浏览器手里握着一整套现成的本事:调出带 @ 的键盘、把用户存过的地址一键填进去、在提交前拦下一个明显不成立的邮箱、告诉密码管理器这是新密码不是旧密码。这些本事一件都不需要你写代码,但每一件都需要你在标签上写一句话。不写,它就当你不需要。 这一轮就是去数这句话有没有人写。 ## 浏览器本来准备替这一格做哪几件事? 先把机制摆清楚,后面的数字才有落点。一个输入框上能写的东西不少,真正会触发浏览器动作的是下面这几个,它们各管各的,互相替代不了。 写在哪儿 | 浏览器拿它干什么 | 不写会怎样 | type | 决定用哪种控件、手机上弹哪种键盘、提交前做哪种最基本的格式检查 | 当成一行普通文本,什么都不管 | autocomplete | 认出这一格要的是邮箱、名字还是收货地址,把用户存过的值填进来 | 只能靠猜,猜不准就不填 | required | 空着不让提交,并且把这件事同步进无障碍树 | 星号只有眼睛看得见 | inputmode | 在type不变的前提下换一套软键盘 | 手机上继续弹全键盘 | pattern与maxlength | 提交前挡掉明显不合规的输入 | 全部推给后端和那段JavaScript | 这五样东西有个共同点:它们都是声明,不是行为。你写下来,浏览器照做;你不写,页面照样长得一模一样,用户也照样能填——只是那些本来免费的帮助全都不会发生。视觉上没有任何代价,这正是它们容易被漏掉的原因。 还有一个容易混的点。MDN的autocomplete取值清单 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete)里,取值不是随便起的名字,是标准里定死的一份枚举。HTML标准的表单控件章节 (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html)一共定义了65个取值,去掉section、shipping、billing这类修饰词和on、off两个开关,真正的字段名是54个。写在里面的浏览器认,写成autocomplete="phone-number"这种自己发明的,等于没写。 ## 这一轮量了什么,为什么要先去一次重? 样本沿用手上那批英文独立站:55个站,每站抓首页、一个商品页,再从首页现场找出联系页和账号页各一个,凑成4个页面。实际拿到200并且能解析的是191个页面。取不回来的33个里,15个撞429被限流,13个是404(多数是账号页那条约定路径根本不存在),剩下几个是400、403、500。这些页一律不进分母,不凑数。 每个页面上,把所有input、select、textarea全都读出来,连同它的type、name、id、autocomplete、required、pattern、maxlength、inputmode、placeholder,以及它的名字到底是从label、aria-label还是placeholder上来的,一并记下来。原始数据是4393个控件实例。 然后就撞上了第一件麻烦事。 mackweldon的首页上有6个邮箱框,商品页上也是6个,联系页7个,登录页6个。翻开一看,其中5个每一页都长得一模一样:登录用的、找回密码用的、注册用的,全被主题塞进了同一个抽屉,抽屉挂在每一个页面上。按页面数,这一个框会被数四遍;哪个站的页面抓得多,哪个站的写法就自动获得更大的权重。 所以先去重:同一个站里,控件类型、name、autocomplete、required、名字来源、名字文本、占位符全都一样的,算作同一个字段的多次渲染。4393个实例合成1902个字段。合并的量不小——去重后的字段里,有31.3%是在三个及以上页面上重复出现的。 这个口径本身也是个发现:一个站的表单写得好不好,多数时候不是页级决策,是它主题里那几份模板的事。这一点后面还会再撞见一次。 1902个控件里,绝大多数是商品页上的颜色尺码单选钮和各种勾选项。真正要用户打字的(text、email、search、tel、password、number、textarea这些)是602个。这602个里还得再剔掉180个,剔掉的原因放在后面那节尺子失效里讲,最终422个,来自54个站。 ## 邮箱那一格,四件事都写全的有几个? 先看最能横向比的那一格。422个字段里,能判定为收邮箱的有160个,来自51个站——比例之高说明了一件事:这批站上唯一一件人人都在做的事,是收邮箱。同一件事、五十多种实现,正好当尺子用。至于这个框本身该怎么设计、什么时候弹出来才不招人烦,邮件弹窗那篇 (https://zhangwenbao.com/email-popup-lead-capture-opt-in-conversion-guide.html)与邮件列表从零养起那篇 (https://zhangwenbao.com/dtc-email-list-building-lead-magnet-double-optin-compliance.html)都拆过,本文只管它在源码里说了什么。 四件事分开看: 这一格写没写 | 写了的 | 占比 | type="email" | 139 | 86.9% | 有个正经名字(label或aria,不是只有占位符) | 142 | 88.8% | required或aria-required | 116 | 72.5% | autocomplete="email" | 73 | 45.6% | 四件全写上 | 68 | 42.5% | 单看每一项都不算灾难,凑到一起就塌了一半。而且组合分布很集中:写全的68个之外,第二多的是35个只差autocomplete那一项,第三多的是24个既没autocomplete也没required。四件事全都没写的有7个。 换个算法更难看。按站算,把一个站上所有邮箱框都要求写全,51个站里做到的只有6个:brooklynbedding、casper、dollarshaveclub、hellotushy、oclean、stanley1913。反过来,一个都没写全的站有16个。 顺带把这一格的名字文本也数了一遍,因为它经常被当成随手可以变的东西。160个邮箱框里,写了占位符的122个,原样不同的写法41种,忽略大小写和末尾标点后归一化,还剩27种:Email、Email Address、Your email address、Enter your email here...、your@email.com。可及名称那一列同样是34种原样、23种归一。同一个概念,在同一批页面上有二十多种叫法——这件事对用户没影响,对拿名字去认字段的程序有影响,也正是首页正文可读性那一轮实测 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)里数过的另一层:那次数的是这一格有没有名字,这次数的是它写没写清楚自己要什么。 ## autocomplete用得最多的那个取值,为什么是off? 把范围放大到全部1902个控件,写了autocomplete的只有164个,8.6%。这个数字本身不奇怪——单选钮和勾选项本来就用不上它。奇怪的是取值分布。 164个里,取值合法的105个,写成off的55个,写on的2个,自己发明取值的2个(password和phone-number,标准里都没有这两个名字)。也就是说,整批数据里autocomplete这个属性出现最多的单一取值不是email,是off:email 73次,off 55次,第三名current-password只有7次。 更值得念一遍的是覆盖面。标准给了54个字段名,覆盖到姓名分段、地址分级、信用卡有效期、生日拆成年月日、一次性验证码。这55个站实际用到的是13个:bday-day、bday-month、bday-year、country、current-password、email、family-name、given-name、name、new-password、postal-code、sex、tel。标准写了54格,行业只用了两成半。 那55个off也不是随便关的。按用途拆开,29个是搜索框,其余散落在邮箱、密码、姓名上。搜索框关掉浏览器的历史下拉,理由通常说得通:站点自己做了联想,两层下拉叠在一起确实难看。但邮箱框上那6个off就不太讲得通了——用户存过的邮箱不给填,省下的是他自己那几秒。 这里得说句公道话,off的语义在标准里也有点尴尬:它本意是“这一格不适合自动填充”,浏览器并不保证照做,密码管理器更是长期无视它。所以写off常常连它想要的效果都拿不到,只是让这一格彻底失去了被正确识别的机会。 ## 搜索框为什么是全场最不像框的那一个? 把字段按用途分成几个桶,横着对比一次,差距一眼就看出来了。 这一格在要什么 | 个数 | 站数 | type写对 | 写了autocomplete | 写了必填 | 邮箱 | 160 | 51 | 86.9% | 50.0% | 72.5% | 密码 | 26 | 23 | 100% | 57.7% | 65.4% | 姓名 | 38 | 26 | 100% | 42.1% | 55.3% | 留言 | 21 | 20 | 95.2% | 4.8% | 28.6% | 电话 | 12 | 12 | 66.7% | 50.0% | 16.7% | 数量 | 18 | 15 | 83.3% | 5.6% | 5.6% | 搜索 | 80 | 45 | 30.0% | 33.8%(全是off) | 1.2% | 密码框百分之百写对了type,因为写错就会把密码明文显示出来,第一次自测就会被发现。邮箱框写对86.9%,因为写错了手机上不弹 @ 键,测试的人多半也会察觉。写对的那些,几乎都是写错了立刻能看见的那些。 搜索框恰恰相反。type写成search还是text,页面上看不出任何区别——两者的差别只在于移动端的回车键变成“搜索”、部分浏览器会给一个清除小叉、以及它在无障碍树里的身份。看不出区别,就没人改,于是80个搜索框里56个还是type=text。至于那1.2%的必填,倒是合理,搜索框本来就不该拦人。 顺着这条线往后看还有一层:站内搜索页那一轮实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)发现,四十个电商站里查得到和查不到长得几乎一模一样。入口这一格身份模糊,结果那一页身份也模糊,两头都没人当成一件正经事来写。 搜索这一格另有一层账。它是站上被点得最多的输入框之一,也是搜索框设计那篇 (https://zhangwenbao.com/site-search-bar-ux-design-conversion.html)反复讲过的高转化入口;而它在源码里恰恰是身份最模糊的那个。移动网页与App上提交按钮的那次对照 (https://zhangwenbao.com/ecommerce-app-ux-container-default-compliance-gap.html)量过它的外形差异,这一轮量的是它在标记层的自我介绍——两边的结论正好接上:这个框的实现,被当成了纯视觉问题。 ## 同一个站里的两个邮箱框,写法为什么不一样? 这是本轮最干净的一次自基线。跨站比较总有借口——技术栈不同、团队规模不同、上线年份不同。那就在同一个站里比:同一个站的两个邮箱框,写法一致吗? 51个站里,有两种及以上不同邮箱框写法的是43个。这43个里,四件事写得前后不一致的有37个,86.0%。 不一致的形态高度一致。举几个(用四位数字表示四件事,顺序是type、autocomplete、required、名字): - allbirds:首页、商品页、联系页上的订阅框都是1010,登录页上的那个是1111; - brooklinen:首页与联系页的订阅框1001,登录页1111; - baseus:首页1001,联系页0000,登录页1111; - bollandbranch:三个订阅框全是1011,登录页1111。 规律很扎眼:登录页那个框永远是写全的,首页页脚那个订阅框永远缺一两样。不是同一批人写的,也不是同一天写的。 ## 平台给的那一页,和自己后加的那个框,差在哪? 顺着上一节往下追,把字段按“是谁加上去的”分三档,差距就不是几个百分点了。 这个框来自哪儿 | 字段数 | 站数 | 写了autocomplete | 写了必填 | type写对 | 有正经名字 | 站点自己的表单 | 284 | 54 | 49.3% | 56.3% | 89.3% | 86.6% | 提交给第三方的表单 | 37 | 10 | 8.1% | 18.9% | 87.5% | 94.6% | 不在任何表单里 | 101 | 37 | 6.9% | 5.9% | 33.3% | 89.1% | 三档里最惨的不是第三方,是第三档。那101个字段压根不在任何一个form元素里——搜索框、弹层里的邮箱格、商品页上那个到货通知框,全靠JavaScript接管。这一档里type写对的只有三分之一,autocomplete 6.9%,必填5.9%。一个连自己属于哪张表单都没交代的框,自然也不会交代自己要什么。 第三方那一档有意思在别处:名字写得最好(94.6%),autocomplete最差(8.1%)。这两个数放一起,画像很清楚——那是营销工具生成的订阅表单,它非常在乎表单在视觉上和无障碍上过得去,但完全不在乎浏览器能不能替用户把邮箱填进去,因为那对它的转化归因没有任何帮助。第三方脚本自己会变 (https://zhangwenbao.com/third-party-default-changes-silent-drift-audit.html)这件事在这里同样成立:那一档的写法什么时候改、改成什么样,不由你定。 再按页面类型看一遍,同一件事从另一个角度冒出来: 页面 | 字段数 | 写了autocomplete | 写了必填 | type写对 | 平台默认的登录页 | 29 | 72.4% | 72.4% | 96.6% | 注册页 | 24 | 58.3% | 58.3% | 91.7% | 站内链接过去的账号页 | 106 | 56.6% | 58.5% | 81.8% | 首页 | 164 | 47.0% | 40.9% | 77.3% | 联系页 | 211 | 27.0% | 30.8% | 75.6% | 商品页 | 216 | 33.8% | 34.7% | 73.0% | 顺序基本是按“这一页有多少是平台自带的”排下来的。登录页那29个字段里,name属性写着customer[email]、id写着CustomerEmail的一大片——那是电商平台默认主题里的原件,从模板里出厂就带着autocomplete和required。首页页脚那个订阅框、商品页那个到货通知框,才是各家自己后来加的。 所以本轮真正的结论不是“大家不懂”,而是:这些属性写没写,跟开发者知不知道关系不大,跟这个框是从哪儿来的关系极大。平台默认的模板替你写好了,你自己拼的那个没人替你写。这条线同样解释了为什么robots.txt里那些指令三分之一是白写的 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)、为什么响应头里躺着248个死字段 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html)——出厂默认值的惯性,比任何一份最佳实践都强。 ## 校验这件事,页面到底交给了谁? 把422个要打字的字段过一遍校验类属性,数字冷得有点好笑: - 写了required的142个,33.6%;另有31个只写了aria-required,也就是只告诉了读屏软件,没告诉浏览器; - 写了pattern的21个,5.0%; - 写了maxlength的33个,7.8%; - 写了inputmode的6个,1.4%。 那31个只写aria-required的挺说明问题。写这一行的人显然知道无障碍这回事——无障碍改造那份清单 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)里这一条排得很靠前——但他把它当成了一条无障碍要求,而不是一条功能声明。同一件事写在required上,读屏软件照样读得到,浏览器还顺手帮你拦一次空提交。 再看表单这一级。360张去重后的表单里,有可见可填项的“真表单”120张,其中54张写了novalidate——45.0%的真表单,明确关掉了浏览器的内建校验。 关掉不见得是错。MDN关于客户端校验的那篇 (https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Form_validation)写得很清楚:浏览器自带的那个气泡提示样式改不动、文案不能自定义、多语言站上它按浏览器语言走而不是按页面语言走。想把错误提示做成自己的样子,第一步就得关掉它。这条路径完全正当。 问题在于关掉之后有没有补上。错误提示那一篇 (https://zhangwenbao.com/form-validation-error-message-adaptive-copy-checkout.html)算过另一笔账:后端明明知道用户错在哪,页面上却只剩四个字。两件事连起来看是同一条链:先把浏览器能说的那句话关掉,再把自己该说的那句话省掉,最后用户面对的就是一个不肯说明理由的框。 inputmode那1.4%值得单独说一句。它是这批属性里成本最低的一个——MDN的inputmode说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inputmode)里那一行属性,加上去就能让手机上弹出的键盘换一套。数量框、邮编框、验证码框都用得上。全样本422个字段里写了的6个,其中4个还是数量框。移动端那根手指本来就够忙了 (https://zhangwenbao.com/mobile-gesture-intent-overload-action-vocabulary.html),多按几次切换键盘这件事,没人算进过成本。 ## 这一轮尺子失效了三次 按老规矩,量之前先量尺子。这一轮尺子坏了三次,三次都是在写稿之前抓到的,每一次都会改掉结论。口径变更那篇 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)讲的是同一条线上前后不可比,这里是同一次读数里分母被污染,性质一样:数字不会喊疼,只有你自己去翻明细才知道它坏了。 ## 第一次:同一个框被数了四遍 就是前面讲的抽屉问题。不去重的话,主题里那几个隐藏表单会按页面数量翻倍,谁的页面抓得多谁的权重就大。按签名去重之后,“要打字的字段”从一堆实例收敛到422个,邮箱框从300多个收敛到160个。所有百分比都是在去重之后算的。 ## 第二次:读表单id,读回来一个输入框 脚本第一版在44个页面上直接崩了,报的是“这个值上没有replace方法”。查下去才发现,HTML标准给form元素开了个后门:表单里那些控件的name会被挂到表单对象上,而且优先级高过表单自己的属性。商品页那张加购表单里通常有个装着变体ID,于是读form.id读回来的是那个输入框本身。全样本里有275张表单实例中招,出自33个站。改成getAttribute('id')之后重跑,那44个页面全部回来了。 ## 第三次:跟踪像素往页面里塞了160个输入框 第一版算出来“提交给第三方的表单”有318个要打字的字段,其中242个来自两个站。翻开一看,parachutehome的商品页上有一张form,action指向https://www.facebook.com/tr/,整张表display:none,里面160个type=text的输入框,name是id、ev、dl、rl、ts、ud[external_id]这种——那是跟踪像素把自己的请求参数做成了输入框。它们既没有可及名称也没有占位符,从头到尾没打算给人看。 判据因此收紧了一道:从没可见过、又没有任何说明文字的字段,不算“用户要填的字段”。这一刀切掉180个,其中166个出自那个像素。切完之后,“第三方表单”这一档从318个字段变成37个,画像也跟着反转——原来算出来的是“第三方连名字都不写”(17.2%),真值是“第三方名字写得比谁都好”(94.6%),差的是autocomplete。如果没抓到这一刀,整节结论会写反。 ## 这些数字有几个边界 三条,都得摆在明处。 第一,读数只是一个时刻的快照。页面载入后等9秒左右读一次,这是本轮的口径。另外挑了29个首页做对照:什么都不做、只多等20秒,17.2%的页面form数会变、20.7%的页面可填控件数会变;再替用户点一下那个订阅或搜索入口,56.5%的页面控件数会变,全样本可填控件从42个涨到70个。所以这里所有的百分比,量的是“不点、只等一会儿”那个状态下的页面。换个等法,分母就换了。 第二,样本偏平台。55个站里相当一部分跑在同一个电商平台上,前面那条“平台默认写得好”的结论,本质上是这批平台的默认模板写得好,换一套自研前端未必成立。 第三,这一轮只看声明,没看行为。写了type="email"不等于后端真的验邮箱,写了autocomplete="email"也不保证浏览器一定填得进去——它还要看这一格在不在一个form里、页面有没有别的东西挡着。声明是必要条件,不是充分条件。 ## 照着改,先动哪四处? 按投入产出排,四步,前两步半小时能做完。 第一步,把站上所有收邮箱的框找出来,一个一个补齐四件事。找法很土但管用:全站搜type="text"加email这个词,再搜一遍页脚模板、弹层模板、到货通知模板。本轮51个站里只有6个通过了这一关,这一步的性价比高得离谱。四件事分别是type="email"、autocomplete="email"、required、一个真正关联上的label。 第二步,把autocomplete从“想起来才写”改成模板里的默认项。结账那一套尤其要注意收货与账单要分别加shipping和billing前缀,这件事结账流程那一篇 (https://zhangwenbao.com/checkout-rework-path-vs-first-fill.html)已经拆得很细。做之前先照着标准的54个字段名过一遍,别自己发明取值——本轮就抓到phone-number和password这两个不存在的名字。 第三步,清点一遍不在任何form里的输入框。这一档的各项指标全场最差,而且它们多半是最近两年加的组件。搜索框、订阅弹层、到货通知,只要还在用div拼,就顺手把type和autocomplete补上,成本几乎为零。下拉框那篇 (https://zhangwenbao.com/form-dropdown-control-selection-conversion.html)讲过同一个道理的另一面:能用原生控件解决的,别自己造。 第四步,如果你关掉了novalidate,去看看错误提示补上了没有。关掉本身没问题,关掉之后什么都不补才是问题。顺手把inputmode加到数量框和邮编框上,两分钟的事。 再往前一步的话,值得把这件事塞进组件库而不是塞进checklist。本轮那86%的站内不一致说明得很清楚:靠人记,记不住;靠模板,才记得住。保哥自己那批工具页上的输入框,也是先补进模板才彻底不再漏的——之前每次新加一个页面就漏一次,checklist上写得再清楚都没用。 顺带一提,这件事跟AI时代那套讨论也接得上。智能体读的是无障碍树而不是页面截图 (https://zhangwenbao.com/ai-agent-accessibility-tree-not-pixels.html),而type、required、名字这三样恰好就是那棵树上的节点属性;给代理适配站点 (https://zhangwenbao.com/ai-agent-website-optimization-guide.html)这件事,起点不在于加什么新标记,而在于把二十年前就有的这几个属性写全。语义化标签那篇 (https://zhangwenbao.com/semantic-html-tags-seo.html)的老结论在这里依然成立:机器读到的东西,从来只有你写下来的那部分。 ## 常见问题解答 ## 写不写autocomplete,对SEO排名有影响吗? 没有直接影响,搜索引擎不会因为你写了autocomplete给你加分。它影响的是转化和可用性:用户少打十几个字符,表单完成率就不一样。真要说和搜索的关系,只有间接的一条——这些属性同时也是无障碍树上的节点信息,而读页面的程序越来越多地依赖那棵树。把它当成转化优化去做,别当成排名手段。 ## 我的表单是JavaScript接管提交的,还有必要写这些属性吗? 有,而且更有必要。JavaScript接管的是提交那一步,type、autocomplete、required管的是提交之前的每一秒:弹哪种键盘、能不能一键代填、空着提交时提不提示。本轮那101个不在任何form里的字段,各项指标全场最差,正是因为团队默认“反正JS全管了”。 ## type=email的浏览器校验太松,写了也拦不住乱填的邮箱,还写它干嘛? 它确实很松,只要有 @ 就放行,MDN的input type=email文档 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/email)里明确写了这一点。但它真正的价值在别处:手机上弹带 @ 的键盘、告诉浏览器这一格可以用存过的邮箱去填、在无障碍树里表明身份。校验只是它顺手做的第四件事。 ## 搜索框的autocomplete写成off,到底该不该? 如果你自己做了搜索联想,写off是合理的,能避免两层下拉叠在一起。但要知道两件事:一是浏览器不保证照做,密码管理器基本无视它;二是别把这个习惯顺手复制到邮箱、姓名、地址那些框上。本轮55个off里有6个落在邮箱框上,那几个纯属抄模板抄过头了。 ## 怎么快速查一遍自己站上这些属性写没写? 不用装工具。打开控制台跑一句document.querySelectorAll('input,select,textarea'),把type、name、autocomplete、required打出来看一眼就够了。要注意两个坑:一是同一个框可能在多个页面重复出现,别重复计数;二是页面上可能有跟踪像素注入的隐藏输入框,判据是“从没可见过又没有任何说明文字”,那些不算你的字段。 ## 这些属性会不会因为浏览器差异而不生效? type、required、pattern的支持度早就没有问题了。inputmode在主流移动浏览器上都能用。autocomplete的差异主要在“填不填”的策略上——各家浏览器和密码管理器有自己的启发式判断,你写对了它未必百分之百填,但你不写它基本就只能猜。web.dev那份登录表单最佳实践 (https://web.dev/articles/sign-in-form-best-practices)把这套判断讲得比较全,值得照着核一遍。 ## 权威参考资料 ## sitemap提交的地址,页面自己认不认账? - URL:https://zhangwenbao.com/sitemap-url-three-layer-identity-audit.html - 分类:技术SEO - 发布:2026-08-21 | 更新:2026-08-21 - 摘要:你把地址交给搜索引擎,页面上却写着别收我,canonical又说正主是另一个。这三句话没有一个仲裁者。 - 关键词:技术SEO,Sitemap,独立站运营,索引控制 > **TLDR**:摘要:从116个海外品牌独立站的sitemap里各随机抽6条地址,一共694条,逐条实抓之后跟提交层、交付层、索引层三处的声明对照。结果是561条(80.8%)三处一致,133条(19.2%)至少有一处对不上:31条提交之后跳到了别的地址,28条页面上明写着不要收录,18条直接返回403,16条的canonical指向别处。更值得注意的是那63条非200的地址——换成普通浏览器身份重抓一次,其中18条立刻变成200,说明将近三成的失败不是页面坏了,是它不接待这个身份。 > 摘要:从116个海外品牌独立站的sitemap里各随机抽6条地址,一共694条,逐条实抓之后跟提交层、交付层、索引层三处的声明对照。结果是561条(80.8%)三处一致,133条(19.2%)至少有一处对不上:31条提交之后跳到了别的地址,28条页面上明写着不要收录,18条直接返回403,16条的canonical指向别处。更值得注意的是那63条非200的地址——换成普通浏览器身份重抓一次,其中18条立刻变成200,说明将近三成的失败不是页面坏了,是它不接待这个身份。 前两篇分别量了一份文件内部两条规则打架、一份响应里两个字段打架。这一篇往上走一层:同一个地址被四个地方各声明了一次身份,而这四处分属不同的文件、不同的团队、不同的更新节奏。 八月十七日那条关于llms.md第二版的消息给了这件事一个新注脚——它又加了两种链接关系,可以写在HTML里,也可以写在响应头里。这意味着一个页面的身份声明从四处变成了五处,而它们之间从第一天起就没有任何一致性检查。 所以保哥把这批站的sitemap全拉了下来,随机抽样实抓,看看这几处说的到底是不是同一件事。 ## 你提交的那个地址,交付层还认它吗? 先说最基础的一层。sitemap的语义是我希望你收录这些地址,那么最起码这些地址得能打开。 单站也做过同类抽查,585条网址里48条是坏的 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)而生成程序一次都没报错。 这份文件的写法讲究不少,2400个站踩出来的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)基本都在那份清单里。 这里先交代一个边界:本文只看sitemap里声明的地址,不做全站爬取。两者的差别不小——全站爬取能发现那些没被提交但存在的页面,而本文关心的恰恰是反过来的方向:提交了的这些,到底是什么状态。 ## 样本是怎么建起来的 起点是157份能正常读取的robots.txt,其中143个站按robots协议里的声明方式 (https://www.rfc-editor.org/rfc/rfc9309.html)写了sitemap地址,一共676条声明。每站取前两条去抓,第一层拿回157份,其中116份是协议里定义的索引文件 (https://www.sitemaps.org/protocol.html)、36份是地址清单,剩下几份无法识别。 反方向的检查也有一套,孤岛页面检测的抽样口径怎么定 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)讲的是没被提交的那些。 批量拿地址有现成办法,六种格式的sitemap解析与URL提取 (https://zhangwenbao.com/sitemap-extractor-url-extraction-format-analysis-guide.html)能省掉手工翻页。 同一批robots.txt里还量过规则本身,两条规则撞车时赢的不是先写的那条 (https://zhangwenbao.com/robots-txt-rule-conflict-longest-match-audit.html)是按路径长度判的。 索引文件里又声明了8573个子文件,每站挑最多三个抓第二层。两层合起来共拿到263203条地址,覆盖109个站。抽样时每站至多抽6条、排除掉图片和文档类地址,最终694条覆盖116个站。 抽样时特意排除了图片、样式表、文档这类非页面地址,因为它们的状态判断标准不一样。剩下的全是HTML页面,涵盖商品页、分类页、内容页和各种功能页,跟真实的收录目标基本重合。 ## 打不开的有63条,占9.1% 694条里631条最终返回200,63条不是。分布是403十八条、404九条、302八条、406六条、400六条、429六条、完全连不上四条、410三条、500两条、301一条。 批量确认地址还在不在有现成办法,死链怎么批量查出来再分类提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接套用。 这些状态码各自的含义有张速查表,301、302、404和410该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)能省掉不少争论。 状态 | 条数 | 说明 | 200 | 631 | 正常返回 | 403 | 18 | 拒绝访问,多数是边缘防护 | 404 | 9 | 地址已不存在 | 302 | 8 | 跳转链没走完或循环 | 406 | 6 | 内容协商失败 | 400 | 6 | 请求被判为不合法 | 429 | 6 | 被限速 | 其它 | 10 | 连不上、410、500、301 | 把这张表跟上一批的一组数字放在一起会更有感觉:那次抽了585条某个站的sitemap地址,48条是坏的,比例8.2%,跟这次跨站抽样的9.1%相当接近。单站和跨站两个口径得出同一量级的数字,说明这不是某几个站的毛病。 ## 410这个状态码值得单独看 falconeri.com有三条返回410,意思是这个地址已经永久删除。这其实是个好信号——它说明这个站认真处理了下架页面,用410而不是404告诉对方别再来了。 下架之后那一页该怎么办,集合页没有产品时的三种场景处置 (https://zhangwenbao.com/seo-empty-shopify-collections.html)给了判断依据。 改版之后最容易出这类问题,一次揪出全站404与重定向链 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)是改完必跑的一步。 问题在于同一批地址还留在sitemap里。一边说这个页面永久没了,一边把它提交给搜索引擎,两个声明的时间差可能是几周,也可能是几个月。生成sitemap的程序显然没有读过页面的状态码。 还有一个判断上的细节:410和404在这批数据里我没有合并统计,因为它们表达的意图不同。前者是站方主动声明永久删除,属于处理得当只是没同步;后者可能是主动删除,也可能是路由改了没人知道。两者混在一起会掩盖掉前一类的正面信号。 ## 500那两条更麻烦 intimissimi.com有两条商品页返回500,服务器内部错误。这类地址在sitemap里的危害比404大得多:404是明确的否定答案,搜索引擎知道该怎么处理;500是我暂时坏了,对方会重试,重试的次数还不少。 抓取额度被浪费的账要算清楚,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)按优先级排过序。 服务器出问题时常常悄无声息,抓取速率被调低的那几天日志里一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这种情形。 把持续报500的地址留在sitemap里,等于主动引导对方反复来撞同一堵墙。这也是为什么sitemap的生成不该只依赖数据库里的商品状态,还该带一层实际响应校验。 400那六条也值得提一句。请求被判为不合法,通常是地址里带了服务器不认的字符或者参数组合。这类地址能出现在sitemap里,说明生成程序拼地址时没做转义,而拼出来的东西自己从来没试过。 ## 406这个状态最容易被误解 hoka.com抽到的六条地址全部返回406,意思是服务器没法提供你能接受的内容格式。这是内容协商失败,通常跟请求头里的接受类型有关。六条全中说明这不是个别地址的问题,是整个站对这类请求的统一反应。 请求本身也可能被判不合法,老用户打不开的页面而工具全都返回200 (https://zhangwenbao.com/request-header-too-large-400-431-cookie-seo-blindspot.html)就是这么来的。 内容协商这一层坑不少,出厂只压HTML一种类型、其余字节全额计入预算 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)是常见默认值。 下一节会讲到,406这一组在换了身份之后依然是406,属于真问题而不是身份歧视。 ## 换个身份再问一次,答案会变吗? 这是本篇最重要的一个方法论环节。所有非200的结论,都必须先回答一个问题:是这个地址坏了,还是它不接待我? 身份决定待遇这件事我量过一次,robots说允许、仍有十个站把GPTBot挡在门外 (https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html)是同一层错位。 弄清对面是谁是所有判断的前提,120种爬虫标识的分类与真假验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)可以直接照做。 还有一个容易忽略的因素是请求来源的地理位置。这台服务器在中国境内,很多面向欧美市场的站点对这个区域的请求本来就更严格。同一批地址换一台美国的机器去抓,403的数量很可能不一样。所以严格说,本文的结论是从这个位置、用这个身份看到的样子。 本文的抓取全部只发普通的GET请求、不带任何参数、也不重复访问同一地址,请求节奏也压得很低。这样做的目的是让每一条记录都反映这个地址本身的状态,而不是我们制造出来的负载。做跨站普查时这一点必须自律,否则拿到的数据既不准确,对被抓的站也不厚道。 ## 为什么必须做这个对照 第一轮抓取用的是搜索引擎爬虫的身份标识,但请求来自一台普通的云服务器,地址段跟真正的搜索引擎完全不同。很多站的边缘防护会检查这一点:声称自己是爬虫、地址却对不上,直接拦。 请求方式不对会漏掉字段,用HEAD查说没配缓存头、换成GET那五个全在 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)是踩过的坑。 要看清谁在真抓你的站,五千个站样本里的爬虫伪造与预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)是更硬的参照。 边缘防护到底拦了谁并不好判断,防火墙拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测答案挺意外。 这种情况下拿到的403,反映的是防护规则,不是页面状态。上一批我在别的实验里吃过这个亏,182条被挡住的路径完全无法判定存在性,占了样本的一半。 ## 把63条全部用普通浏览器身份重抓一次 第二轮换成常见的桌面浏览器标识,加上正常的接受类型和语言偏好,其它条件不变。结果是18条变成了200,45条维持原样。 名单上那些名字有没有真来过也能量,266个令牌里只有23.3%真的来过 (https://zhangwenbao.com/crawler-ua-list-named-vs-real-visits-audit.html)是另一组实测。 按身份做拦截要防误伤,拦AI爬虫怎么不把Googlebot一起拦掉 (https://zhangwenbao.com/nginx-ai-bot-blocking-rate-limit-rdns-misblock-account.html)有具体的匹配写法。 第一轮 | 第二轮 | 条数 | 判断 | 403 | 200 | 6 | 拦的是身份 | 429 | 200 | 6 | 限速针对爬虫身份 | 302 | 200 | 5 | 跳转链能走通了 | 301 | 200 | 1 | 同上 | 403 | 403 | 12 | 整站拒绝这台机器 | 404 | 404 | 9 | 真的不存在 | 406 | 406 | 6 | 真的协商失败 | 400 | 400 | 6 | 真的被判不合法 | 这里也得说清对照的局限:换身份只能区分出按标识判的那部分防护,按地址段判的仍然拦得死死的。那12条两轮都是403的,很可能就属于后者,我没法进一步区分它们到底是页面坏了还是这台机器被整体拉黑。 ## 身份造成的失败占了28.6% 18除以63等于28.6%。将近三成的非200结论,如果不做这个对照,就会被写成这个站的sitemap里有坏地址——而事实是那些地址对普通用户完全正常。 中间层改写内容的情况不止一种,自动翻译把yes改成forks而数据看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是同一种沉默污染。 补对照组这件事经常能救命,量出七成页面有差异、补上对照组后只剩两个点 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)是同一类返工。 用别人的工具前先校准,第三方数据准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 这个比例值得所有做类似普查的人记住。任何一次跨站抓取,只要目标站有边缘防护,结论就必须分成两层:这个地址的状态,和这台机器的待遇。 反过来看,那12个换身份也进不去的403更值得站主注意。它们意味着任何一个第三方工具都测不了这些页面,包括排名监控、性能监测、结构化数据校验。防护是必要的,但把所有自动化请求一刀切掉,代价是自己也失去了观测能力。 ## 429那六条尤其说明问题 限速返回429,第二轮换个身份立刻正常。这说明限速规则是按身份标识而不是按请求频率判的——我们两轮的请求间隔完全一样,唯一的变量是那个标识。 有时候拦你的是自家主机,托管环境可能正悄悄拦AI爬虫而监控没报警 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)是同一种失控。 限速规则的反噬可能很大,限速拒掉的第四个请求正好是robots.txt (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html)会让抓取停十几个小时。 这类规则的副作用很直接:真正的搜索引擎爬虫如果撞上同一套规则,也会被限速,而它不会换个身份再来一次。上一批量过一个更极端的例子,限速把robots.txt本身给拒了,导致整站抓取停了十几个小时。 做完这一步还有个副产品:那12个站的防护规则被间接量出来了。它们对声称是爬虫的请求一律拒绝,不管这个请求本身有多规矩。这套策略挡住的不只是我这台机器,还有所有第三方审计工具——包括站主自己买的那几款。 ## 剩下45条才是真问题 刨掉身份因素,694条里真正打不开的是45条,占6.5%。这个数字比9.1%小了将近三分之一,但仍然不算低——每十五条提交的地址里就有一条是坏的。 工具选型别只看功能列表,五大类SEO工具的完整推荐与取舍 (https://zhangwenbao.com/seo-tools-recommendation-2026.html)说清了各自的能力边界。 完整的诊断框架能避免漏项,从抓取、内容到AI可见度的审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以当检查表。 被防护挡住的后果不止拿不到数据,人机验证屏被当成正文索引 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)是更严重的一种。 后面所有的分析都以这个修正后的口径为准。凡是提到交付层有问题,指的都是这45条。 ## 页面自己说不要收录的有多少? 交付层能打开只是第一关。打开之后,页面上还可能明写着一行别收我。 加了标注之后还得等,页面要多久才从搜索结果里消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)有六个场景的实测。 这两个手段该用哪个常被搞反,robots.txt和meta robots各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)里分工写得很清楚。 这里的判定只认明确写着不要索引的那一类,取值里只有不要跟随链接、不要缓存快照之类的都不算。判据卡紧一点,数字会小一些,但每一条都站得住。上一批就吃过判据太松的亏,量出来的问题里一大半是假的。 ## 28条,占能打开那批的4.4% 631条能正常打开的地址里,28条的页面上带着不要索引的声明。响应头里的同类声明是零条——没有任何一个站用响应头这条路来做索引控制。 分页方案选错会连累一大片,五种分页方案的对比与配置 (https://zhangwenbao.com/category-pagination-seo.html)可以先看结论再动手。 该收和不该收得先分开,大量无用页面拖垮流量的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 页面被什么挡在索引外可以一次查清,可索引性体检把几层原因分开列 (https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html)比逐个猜快得多。 这28条分布在若干个站上,其中相当一部分是同一个站的多条。翻开看,最常见的是几类页面:账户相关页、站内搜索结果页、以及一些明显是活动结束后留下的落地页。 还有一种更明确的做法是干脆把这批地址单独放一份sitemap,标注清楚它是回收清单,等确认从索引里消失之后整份删掉。这样意图是清楚的,任何一个接手的人都能看懂,而不是混在正式清单里让人猜。 把这28条按站看,分布也很有信息量:其中一大半集中在少数几个站,说明它们是整批处理的产物,比如某次活动结束后统一给一批页面加了标注。零星出现在各站的那几条,反而更可能是真的遗漏。 ## 这算不算矛盾,得看意图 严格说,提交给搜索引擎又标注不要索引,是两个方向相反的信号。但实务中它有个正当解释:先让对方抓到这一页,读到不要索引这条指令,然后把它从索引里去掉。想让一个已收录的页面消失,这是标准做法。 生成器说格式正确的时候,它其实只查了三件事 (https://zhangwenbao.com/sitemap-generator-xml-lastmod-priority-validation-guide.html)剩下的还得自己看。 两种手段能不能一起用是高频疑问,noindex和canonical同时用的九种场景 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)逐个给了答案。 判断的关键在于时间。如果这批地址是最近才加上标注的,那它们留在sitemap里合理;如果标注已经挂了半年,sitemap还在天天提交,那就是生成程序压根没读页面。 还有个更快的判断:拿这批地址在搜索引擎里查一下还在不在索引里。如果早就不在了,那标注已经生效,sitemap里的记录纯属残留;如果还在,那说明这轮回收还没走完,留着是对的。这个查法几分钟就能出结果。 ## 怎么区分这两种情况 看sitemap里那条记录的最后修改时间。如果它跟着页面一起更新过,说明生成程序至少读到了页面的变化;如果那个时间是很久以前,或者干脆是每天自动刷新的当天日期,那就没有参考价值。 时间格式这一层坑不少,各处各要什么格式 (https://zhangwenbao.com/date-formatter-iso8601-sitemap-lastmod-rfc2822-guide.html)有一份速查。 百万级商品的地址怎么组织,分片、进出场与lastmod诚实度 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)是一整套工程实践。 那个时间字段的格式也有讲究,从sitemap的lastmod到结构化数据的日期 (https://zhangwenbao.com/timestamp-converter-unix-epoch-sitemap-lastmod-guide.html)都得转对。 上一批我量过一个相关的现象:一份sitemap里抽了585条地址,48条是坏的,而生成它的程序一次都没报错。程序不报错的原因很简单——它只是把数据库里状态为已发布的记录导出来了,从来没访问过这些地址。 判断某类页面该不该进提交清单,有个简单的问法:这一页有没有一个具体的搜索需求在对应它?商品页有,分类页有,帮助文档有;站内搜索结果、筛选组合、分页第二十页往后,通常没有。答不上来的那些先别提交,留着看自然表现。 ## 站内搜索结果页出现在sitemap里,是另一个问题 28条里有几条指向站内搜索结果。这类地址本来就不该进sitemap——它们数量无限、内容重复、对用户没有独立价值。页面上标注不要索引是对的,错的是它们被提交了。 筛选组合产生的地址更难缠,分面导航的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)单独拆过一遍。 站内搜索地址到底该不该禁,四种方案的对比与适用场景 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)讲清了各自的副作用。 这种组合暴露的是生成规则太宽:把所有能生成URL的页面类型一股脑扔进去,再靠页面上的标注去兜底。兜底当然有用,但每一条都要花掉一次抓取。 顺带说,这两条路的优先级在规范里是有规定的:两处都写时按更严格的那条执行。也就是说页面上写允许收录、响应头写不要收录,结果是不收录。这跟前一篇量过的响应头矛盾是同一类规则,只是这次跨了两个位置。 ## 响应头那条路一个人都没走 索引指令除了写在页面里,还可以写在响应头里 (https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag)。后者的好处是能给非HTML的资源用,比如PDF、图片、接口返回。这批样本里响应头这条路是零使用。 同一份响应里两个字段打架也有实测,142个站里108个至少有一处自相矛盾 (https://zhangwenbao.com/http-response-header-self-contradiction-audit.html)是上一篇的结论。 没有标签可写的地址怎么办,接口和feed拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)量的就是这一层。 这跟我上一批的一个发现对得上:接口和数据源这类没有标签可写的地址,实际上没有任何一个站给它们配了索引控制。能力存在,但没人用。 ## canonical指向别处意味着什么? 第三层是规范网址声明。631条能打开的地址里,523条的canonical指向自己,73条压根没写,35条指向了别的地址。 它是提示不是命令这一点很关键,八种误用与Google自选规范页的逻辑 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html)解释了为什么常常不生效。 这个标签的基本用法先理清,九个决策场景加完整设置指南 (https://zhangwenbao.com/canonical-url-seo-guide.html)能覆盖大部分情形。 刨掉的那一部分其实也有可改进的地方:既然最终地址跟提交地址不同,那sitemap里就该直接写最终地址,省掉一次跳转。对单条地址来说这点开销可以忽略,对几十万条的站来说,省下的是实打实的抓取额度。 ## 把跳转因素刨掉之后是16条 35这个数字要修正。其中有一部分是页面发生了跳转,最终地址跟提交地址不同,而canonical指向的正是最终地址——那属于正常行为。刨掉这一类,真正意义上的指向第三方地址是16条。 首页那一层也量过,132个首页有23%自己跟自己矛盾 (https://zhangwenbao.com/canonical-self-declaration-conflict-google-selected.html)是同一类对照实验。 最终由谁说了算有明确逻辑,Google选择规范网址的九条决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)可以照着排查。 16条听着不多,但性质很硬:你提交了A,A自己说正主是B。搜索引擎大概率会去收录B,而A在你的sitemap里白占一条。 还有个细节:这批地址里有几条的canonical写的是相对路径。规范允许这么写,浏览器和抓取器都会按当前地址解析,但只要页面被别的地址访问到,解析结果就跟着变。稳妥的写法一律用完整地址,这样无论从哪里被读到,指向都是确定的。 ## 73条没有canonical的更值得看 没写canonical不算错,规范也不要求必须写。搜索引擎会自己挑一个它认为最合适的版本,通常就是被抓到的那个地址。 同一商品的几十个地址该合还是该拆,产品变体的URL与索引策略 (https://zhangwenbao.com/product-variant-seo-url-canonical-indexation-strategy.html)需要先想清楚。 重复内容的成因得先分类,八类成因地图加诊断清单 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)比一刀切有效。 但对于电商站来说,不写canonical风险不小:同一个商品在不同分类路径下、带不同筛选参数时,会产生一堆内容相同的地址。没有canonical,选哪个全看对方判断,而对方的判断依据里包括内链数量、外链、地址长度这些你未必控制得住的因素。 那73条没写canonical的地址里,有相当一部分是内容型页面,地址结构简单、没有参数变体,不写确实没什么风险。真正需要担心的是商品页——同一件商品在不同路径下能生成好几个地址,不表态等于把选择权交出去了。 ## 自指才是sitemap地址该有的状态 一个地址被放进sitemap,等于你在说这是我希望被收录的版本。那么它的canonical理所当然应该指向自己。523条做到了这一点,占83%。 分页地址的规范化尤其要小心,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)有具体做法。 这份文件的作用常被高估,提交网站地图到底能不能提升排名 (https://zhangwenbao.com/does-sitemap-improve-google-ranking-myth.html)得先把预期放对。 剩下的17%要么没表态,要么指向别人。这两种情况都会让提交这个动作打折扣:前者是让对方替你决定,后者是自己否定了自己的提交。 还有一个数字可以并排看:那批首页里有23%自相矛盾,这批内页是17%要么没表态要么指向别人。两个数字的口径不同不能直接比,但方向一致——声明这件事的出错率,在任何层面上都不是个位数。 ## 上一批量过首页的同类问题 那次的对象是132个站的首页,结论是23%的首页canonical自相矛盾。这次抽的是内页,比例低一些,原因大概是内页的canonical通常由模板统一生成,而首页经常有人手工改过。 两套模板各写一份也很常见,插件和主题各冒出一套canonical怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同类清理。 写在哪里也决定生不生效,工具说在head、浏览器说在body该信哪边 (https://zhangwenbao.com/head-boundary-canonical-parsed-into-body-seo.html)是一次真实排查。 两批数据合起来能看出一个规律:越是被人手工碰过的页面,声明出错的概率越高。模板生成的东西虽然笨,至少是一致的。 ## 提交之后跳到别的地址,算不算问题? 31条地址在抓取时发生了跳转,最终落在别的地址上,占能打开那批的4.9%。这一类的判断要分情况。 跳转链本身也要单独查,两个方向的301跳转怎么配 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)有完整实战。 跟随跳转各家实现不同,工具报的死链和Googlebot抓的从来不是同一批 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html)就是这么来的。 还有一种介于三者之间的情况:跳转目标带上了追踪参数或者会话标识。这类地址每次访问都不一样,收录价值为零,而且会在报告里制造大量重复。它们通常来自某个营销工具的自动改写,站方甚至不知道自己的地址被加了尾巴。 ## 三种跳转,性质完全不同 第一种是地址规范化,比如去掉末尾斜杠、补上语言前缀,跳转目标跟原地址基本是同一个页面。这种属于轻微不整洁,改一下sitemap生成规则就行。 临时性的跳转要有收尾计划,A/B测试怎么做才不影响SEO (https://zhangwenbao.com/ab-testing-page-seo.html)里有官方表态和清理动作。 被自动加上的参数也要处理,URL里那个srsltid参数的四种处置办法 (https://zhangwenbao.com/google-srsltid-parameter-seo.html)是现成对照。 跳转目标带参数是另一种麻烦,给内链加UTM参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)是流量分析与抓取的取舍。 配置通过不代表没事,Googlebot每八次抓取就有一次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类隐形代价。 第二种是内容合并,原地址的内容被并进了另一个页面,跳转目标是个不同的页面。这种应该把sitemap里的记录直接换成目标地址。 第三种是按访问者所在地区跳转,同一个地址在不同地方拿到不同的目标。这一种最麻烦。 这类跳转还有个更隐蔽的后果:它让所有的第三方审计工具都测不准。工具服务器在哪个国家,就看到哪个版本;同一份报告在不同工具那里结论不同,而站主根本不知道差别来自地理位置。 ## nomadgoods那六条全跳到了中国区 抽到的六条地址,全部从根路径跳到了带中国区前缀的路径。原因很清楚:抓取请求发自中国境内的服务器,站点按来源地区自动跳转。 地区声明与真实资源常常对不上,236条地区声明背后只有6个真页面 (https://zhangwenbao.com/hreflang-region-code-declared-vs-real-pages.html)是一个极端例子。 按IP自动跳语言版本的代价很大,半数页面会因此进不了索引 (https://zhangwenbao.com/international-seo-ip-redirect-geolocation-language-switcher-ux.html)是实测出来的结果。 这意味着提交给搜索引擎的那个地址,任何一个来自特定地区的访问者都拿不到。搜索引擎的抓取器如果从某个地区发起请求,看到的也是跳转后的地址,而不是你提交的那个。 ## 按地区自动跳转的代价,上一批算过 那次的结论是按访问来源自动跳转语言版本,会让国际站的半数页面进不了索引。原理是搜索引擎的抓取通常来自固定的几个地区,一跳转,别的地区版本就永远没机会被抓到。 写了标注也未必被当成独立页面,Google只把它们当规范页的别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)是另一层现实。 正确的多版本标注怎么写,return tags对称与x-default实操避坑 (https://zhangwenbao.com/hreflang-implementation-return-tags-x-default-canonical-mistakes.html)有完整清单。 正确做法是给用户提示而不是强制跳转,同时用语言声明标注各版本的关系。这件事的技术难度不高,难的是说服业务方——强制跳转的转化率数据通常更好看。 ## flyingtiger那几条是另一种情况 它有几条地址带着井号后面的片段,比如门店定位页加上具体某家店的标识。抓取时片段部分不会发给服务器,所以最终落在了不带片段的同一个页面上。 前端路由与抓取的关系要弄清,八类抓取与索引影响实战 (https://zhangwenbao.com/pwa-seo-service-worker-crawl-indexing-impact-mechanism.html)解释了片段为什么不算地址。 地址本身的写法有讲究,影响抓取与排名的九个URL细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)是一份实操清单。 这类地址进sitemap是没有意义的——对服务器来说它们全是同一个地址。想让每家门店都被单独收录,得给每家店一个真正的独立地址,而不是靠前端片段区分。 还有第三个问题值得问:这次跳转是永久还是临时?永久跳转意味着原地址不该再出现在任何提交里;临时跳转说明原地址还会回来,留在sitemap里可以接受,但要给它一个复查时间。样本里两种都有,而sitemap里的记录看不出区别。 ## 判断跳转要不要处理,看两个问题 第一,跳转目标是不是也在sitemap里?如果在,那原地址就是多余的,删掉即可。第二,跳转是不是对所有访问者一致?不一致的话,问题的根不在sitemap,在跳转规则本身。 跳转规则通常写在同一个文件里,重写、缓存、规范化与HSTS六层治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)可以一起看。 换架构之后这套东西得重搭,sitemap、重定向这些不会自动跟过来 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是常见上线失分点。 ## 被自己的robots.txt挡住的有几条? 这一节的结论是个负面结果,但我认为它比正面结果更有价值。 同一批样本上量过分组,给单个爬虫开组会丢掉通配组全部规则 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)中招比例高得离谱。 这份文件写废了后果不小,整站从谷歌搜索结果里消失的那类事故 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)多半从一行规则开始。 ## 694条里只有2条 拿每个站自己的robots.txt规则去判自己sitemap里的地址,判定为禁止抓取的只有2条。比例是0.3%,而如果扩大到26万条全量地址、每站抽300条来跑,命中率是0.05%。 筛选类地址该不该禁要分情况,三类判别法与处理策略 (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)给了处置办法。 哪些页面真该挡有判断依据,电商该屏蔽的七类页面与Shopify实操 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)逐类给了理由。 这个数字远低于我的预期。自己提交的地址被自己挡住是各种审计清单里的经典高危项,实测下来在这批成熟站点上几乎不存在。 顺便说,测试目录被提交这件事本身也值得记一笔。那批地址的路径里明明白白写着沙箱两个字,说明它们是内部预览用的,却和正式页面一起被导出了。生成规则按状态筛而不按路径筛,就会漏进这类东西。 ## 那两条也不全算失误 全量抽样里被挡住的14条,其中philips.com有8条落在一个明显是测试用的目录下——那个目录本来就该被挡,错的是它们被提交了。theordinary.com那两条指向站内搜索结果页,被挡住反而是对的。 拿这个文件解决它管不了的事很常见,用robots.txt拦UTM参数的危害 (https://zhangwenbao.com/robots-txt-disallow-utm.html)就是一个典型。 测试环境的东西泄漏出去代价不小,测试站被索引后的八步清除与四层防御 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)是完整方案。 真正称得上失误的没几条。这跟我做这个实验之前的假设完全相反。 还有第三个原因:现在主流的建站平台会自动生成sitemap,而它们生成时用的就是平台自己的路由规则,跟平台默认的robots.txt天生对齐。真正容易出问题的是那些自己写生成脚本、又单独维护robots.txt的站,而这类站在样本里是少数。 ## 为什么这一项在实际中很少发生 想了想,原因大概有两个。一是sitemap和robots.txt通常由不同的系统生成,前者是内容管理系统导出的、后者是运维配置的,两者覆盖的地址空间本来就不太重叠——运维挡的是后台、接口、参数地址,内容系统导出的是正式页面。 虚拟文件和物理文件谁优先常被搞混,这两层的优先级与AI爬虫拦放 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)讲得比较清楚。 平台替你做的事情不少,托管、自建还是纯代码怎么选 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)把各自代价摊开了。 二是这类问题一旦发生,后果非常显眼:整批页面掉出索引,报告里会直接标红。所以它属于那种发生了就会被立刻发现并修掉的问题,长期存活率很低。 顺带说,这一项之所以长期留在清单里,多半是因为它太好理解了——自己挡自己,任谁都觉得荒唐。而真正高发的那几类,比如提交后跳转、页面标注不要收录,解释起来要多说三句话,就没那么容易被写进检查表。清单的构成往往取决于哪一条最好讲,而不是哪一条最常发生。 ## 负面结果为什么值得写出来 因为审计清单不会自己更新。一项检查被写进清单之后,很少有人回头验证它现在还是不是主要矛盾。结果是每次审计都花时间在一个0.3%命中率的项目上,而真正有19.2%命中率的三层不一致却没人查。 清单之外的问题更值得警惕,被忽略的那几类技术SEO失灵原因 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的正是这种局面。 检查项该按什么顺序排,五百个站实测排出来的技术SEO优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)可以当排期底稿。 把负面结果发出来,至少能让下一个做审计的人重新排一下顺序。 ## 三层信号加起来,一致率是多少? 把前面几层合在一起算总账。判定标准是:能正常打开、没有跳转、页面没标不要索引、canonical没指向别处、没被robots挡住,五条全过才算一致。 抓取报告怎么读也有讲究,五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你分清是谁的问题。 官方报告里的状态词各有含义,八种未编入索引状态的决策路径 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)对照着看才不会误判。 ## 561条一致,133条至少有一处对不上 694条里561条五条全过,占80.8%;133条至少有一处不过,占19.2%。也就是每五条提交的地址里,有一条的几个声明说的不是同一件事。 口径不清的指标最容易误导,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭框架。 指标定义清楚才谈得上对比,三个平台三百个站的收录速度实测 (https://zhangwenbao.com/seo-kpi-guide.html)是一份口径统一的样本。 失分项 | 条数 | 占样本 | 提交后跳到别的地址 | 31 | 4.5% | 页面声明不要收录 | 28 | 4.0% | 交付层返回403 | 18 | 2.6% | canonical指向别的地址 | 16 | 2.3% | 交付层返回404 | 9 | 1.3% | 其它状态码 | 29 | 4.2% | 被自己的robots.txt挡住 | 2 | 0.3% | 不过有一类组合值得单独盯:跳转加上canonical指向别处。这两项一起出现时,通常说明这个地址已经彻底被弃用了,只是没人把它从提交清单里拿掉。那6条属于最该优先处理的一批。 ## 绝大多数是单项失分 133条里同时踩中两项的很少,最常见的组合是canonical指向别处加上发生跳转,只有6条。这说明这些问题基本是各自独立的,不存在某一类问题会连带引发另一类。 相互牵连的问题要另一种拆法,五个维度的信号区隔实战 (https://zhangwenbao.com/keyword-cannibalization-fix-guide.html)处理的是彼此干扰的情形。 好处是修起来可以分头进行,坏处是没有一个万能的修法能一次解决大半。 ## 把身份因素刨掉,一致率会更高一点 前面说过403那18条里有6条是身份造成的,429那6条也是。把这12条从失分里刨掉,一致率会从80.8%上升到约82.6%。 验证一条结论有没有效有个笨办法,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)比讲道理管用。 换个口径结论可能完全不同,三类站点的聚合自然流量实测 (https://zhangwenbao.com/aggregate-organic-traffic-seo-metric-keyword-dead.html)就是一次口径切换。 我在正文里保留了未修正的数字,因为对搜索引擎来说,它的抓取器同样可能撞上这些防护规则。修正后的数字更接近技术真相,未修正的更接近实际后果。两个都有用,但必须标清楚是哪一个。 另一个角度是修复难度。文件内部的冲突改一行就行,责任人也明确;三层不一致要动的可能是内容管理系统的导出逻辑、前端模板、以及防护规则,分属三个团队。比例低不代表容易修,往往正相反。 ## 跟前两篇的数字放在一起看 一份文件内部两条规则打架,36.2%的路径中招;一份响应里两个字段打架,76.1%的站中招;跨文件的三层身份不一致,19.2%的地址中招。 这类欠账攒起来相当可观,技术债怎么排查和分批偿还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了可执行的顺序。 同一条线上还有一篇,有多少条指令压根没有接收方在读 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)量的是更早的一层。 越往上走,比例反而越低。原因不难理解:层数越多、跨越的团队越多,出问题的地方也越显眼,越容易被业务侧发现。真正长期没人管的,恰恰是那些藏在单个文件内部、谁看了都觉得没问题的地方。 ## 出问题的站是零星几条,还是整站都这样? 把133条失分按站分组,能看出一个很关键的区别:有些站是偶尔漏一条,有些站是抽到的六条全中。 跨团队协作有具体抓手,后端工程师配合SEO的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)是从真实账本里总结的。 要推动全站规则改动没那么容易,甲方拒绝建议八成源于身份冲突 (https://zhangwenbao.com/enterprise-seo-evolutionary-framing-eight-steps-rebuild.html)给了重写汇报的办法。 需要说明的是六条抽样的统计力有限。一个站六条全过,不能证明它整份sitemap都干净,只能说问题密度不高;反过来六条中一条,也可能只是运气不好。跨站比较用命中站数是稳的,单站结论必须扩大抽样才能下。 ## 116个站里40个至少有一条 抽样全部干净的站76个,占65.5%;至少一条有问题的40个,占34.5%。三分之一的站在六条随机抽样里就能撞出问题,说明这不是罕见现象。 同一批域名上量过验证类字段,142个站里只有52个回得出304 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)口径卡得很死。 同一批站还量过首页可读性,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)是另一组抽样。 这13个站里,问题类型也各不相同:有的是六条全跳转,有的是六条全返回同一个状态码,还有的是六条都带着同样的声明。类型一致本身就是最强的信号——随机抽样能抽出同一种表现,只能说明它是全站规则的产物。 这里也要留个尾巴:六条全中的站里,有几个的问题类型是403和406,而那正是身份因素最重的两类。把身份修正考虑进去之后,真正六条全是内容侧问题的站会少几个。系统性这个判断本身也需要先过一遍身份这道闸。 ## 13个站是六条全中 更值得看的是那13个站:nomadgoods、peakdesign、hoka、article、gymshark、loccitane、otto、sezane、shein、ugreen、wayfair、weber、yeti,抽到的六条无一幸免。 统一规则会统一出错,默认配置变更却没人通知 (https://zhangwenbao.com/third-party-default-changes-silent-drift-audit.html)的漂移比例并不低。 全站规则出问题往往在结构层,架构搭错了爬虫根本找不到商品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是更上游的问题。 六条随机抽样全中,几乎不可能是巧合。它意味着问题出在某个统一规则上——要么是全站按地区跳转,要么是整站对这类请求返回同一个状态码,要么是模板统一带了不该带的声明。 还有个折中的处理:先把系统性的那批从sitemap里整体摘出来,单独放一份文件,等规则改完再合回去。这样至少不会一边提交一边浪费抓取额度,代价是要多维护一份清单,而且必须记得回收。 ## 系统性和零星的修法完全不同 零星几条通常是内容侧的遗留:某个页面下架了没同步、某次活动结束后留了个尾巴。修法是把sitemap的生成逻辑接上页面状态,一次搞定。 规则叠加之后排查更难,应用栈精简与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)给了可执行顺序。 这类失分往往第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同批经验的汇总。 系统性的那批要动的是全站规则:跳转策略、防护规则、模板里的声明。这类改动影响面大、需要走完整发布流程,而且往往牵扯业务决策——比如按地区跳转到底要不要保留。 分组之后还能顺手做一件事:把同一个站的失分类型也统计出来。类型集中说明是单一规则,类型分散说明是维护松散。前者找一个人改一处就行,后者要立流程,两种情况给出的建议完全不同。 ## 先看是不是系统性,能省掉大量无用功 所以做这类审计的第一步不该是逐条修,而是先按站分组看分布。同一个站命中三条以上,基本可以判定是规则问题,去查规则比去修那三条地址有效得多。 能交给机器的就别靠人记,哪些SEO工作能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条边界。 分组统计这件事日志里也要做,读懂Googlebot抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)给了分析路径。 这个判断只需要一次分组统计,几秒钟的事,但它决定了后面的工作量是三小时还是三天。 还可以换个角度看这批干净的站:它们并不都是技术最强的那几个。里面既有大集团也有小品牌,共同点是站点结构简单、页面类型少。复杂度本身就是这类问题的主要来源,能砍掉的复杂度都是收益。 ## 反过来,76个干净的站说明什么 值得强调的是三分之二的站六条全过。这说明把这几层做一致并不难,也不需要什么特殊技术,只要生成sitemap的时候读一眼页面状态就行。 开发期就该埋好这些点,自建站开发阶段的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)能省掉上线后的返工。 上线检查表该包含什么,前十二周从技术地基到内容蓝图 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)是一份排好序的清单。 做到的和没做到的差别,往往只是有没有人把这件事列进上线检查表。 ## sitemap这一层本身,有多少是拿不到的? 前面聊的都是sitemap里的地址。往回退一步:这份文件本身有多少能被正常读到? 不同系统的生成方式差别不小,免插件做sitemap的改造与分页 (https://zhangwenbao.com/discuz-portal-sitemap.html)是另一个平台的做法。 自己生成这份文件要注意什么,动态优先级、分页与缓存策略 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)有完整实战。 这676条声明里还有个小现象:不少站声明了好几份sitemap,其中一部分是历史遗留的旧文件,内容早已不更新。robots.txt里的这几行同样属于写完就没人再看的东西,跟前一篇量过的那些无接收端字段是同一种沉积。 ## 143个站声明了,676条声明 157份能读到的robots.txt里,143个站在里面写了sitemap行,一共676条,去重后每站平均四五条。14个站一条都没写——这不算错,sitemap可以只在搜索引擎后台提交,但少了一条被发现的路径。 除了提交文件还有主动推送,三种推送方式的实战对比 (https://zhangwenbao.com/baidu-post-real-time-push-tool.html)可以并行用。 这份文件里还有别的例外规则,通配组的星号对广告爬虫不生效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)是最容易漏的一条。 另一个可以对照的数字是:这20个站在上一批的响应头实验里,同样是失败率最高的一群。跨实验的重合度这么高,基本能确认它们的防护策略是统一的、长期的,不是某次配置调整的临时结果。 ## 20个站第一层就拿不到 按声明去抓,186条里157条成功,24条返回403、2条404、3条完全连不上。折算到站,有20个站的sitemap一份都没抓到。 还有一种思路是干脆收费,要不要向AI爬虫按次抓取收钱 (https://zhangwenbao.com/cloudflare-pay-per-crawl-charge-ai-bots.html)已经有平台在做了。 防护该做在哪一层,robots、UA识别、WAF三层的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比只改一处靠得住。 这20个站里有相当一部分是知名大牌,包括好几个西班牙快时尚品牌。它们的共同特点是防护严格——同一批站在别的实验里也是最难抓的那批。 ## 这里必须重复一遍身份的问题 这些403同样存在身份因素。用搜索引擎身份从一台普通服务器发请求,被拦是很正常的结果。真正的搜索引擎抓取器地址在对方的白名单里,大概率能正常拿到。 原始记录留下来才好复查,日志怎么收集成可检索的结构 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是越早做越好的事。 把日志按对象拆开看会很清楚,八类爬虫标识的二十二周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)是一份可对照的样本。 所以这20个站不能被判定为sitemap有问题,只能说这批数据在它们身上是缺失的。本文所有比例的分母都相应缩小到实际拿到数据的那批站,而不是157。 子文件的组织方式也值得一提。做得好的站按内容类型分片,商品一份、分类一份、内容一份,每份的更新频率不同;做得糙的按数量硬切,每五万条一个文件,改一个商品可能牵动好几份文件的最后修改时间。后者会让对方无法判断该重抓哪一份。 ## 索引文件里的8573个子文件 116份索引文件里一共声明了8573个子sitemap,最多的一个站声明了2171个。这个数量级说明大站的地址管理已经完全程序化,人不可能逐个看。 定时表达式记不住就用生成器,把巡检、推送和清缓存都自动化 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)是很划算的投入。 生成与校验都可以交给定时任务,备份、sitemap、缓存、证书一条龙 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)脚本可以直接改。 程序化本身没问题,问题是程序只做了导出这一件事。要让它同时校验状态,成本其实不高——每条地址发一个轻量请求就够,而且可以增量做。 ## 还有一个跨主机的小发现 抽样里有一个站的sitemap指向的全部是另一个主域名下的地址,301条。这种写法本身是允许的,前提是那个域名的所有权能被验证。但从维护角度看,它意味着两个站的地址管理耦合在了一起,改一边要记得改另一边。 跨域的归属声明要写清楚,一稿多发怎么不被副本反超 (https://zhangwenbao.com/content-syndication-seo-canonical-attribution-mechanism.html)给了做法。 多域名怎么组织是更上层的决策,建一个大站还是多个品牌小站 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)会影响后续所有工作量。 ## 新加的那层声明,有人写了吗? 八月中旬llms.md出了第二版规范 (https://llmstxt.org/),新增两种链接关系:一种指向页面的Markdown版本,一种指向覆盖这个页面的说明文件。两种都能写在HTML里,也能写在响应头里。 要进AI的候选池得先过技术这关,五步技术优化的实战顺序 (https://zhangwenbao.com/technical-optimization-crawler-friendly-ai-citations-2026.html)把门槛列清楚了。 想知道AI爬虫真正在乎什么,从代码逆向出它的抓取偏好 (https://zhangwenbao.com/ai-crawler-reverse-engineering-fetch-behavior-llms-strategy.html)比看官方说明更实在。 顺带一提,检索这两种声明并不难:在页面头部区域搜链接关系的取值就行,几行代码的事。真正麻烦的是判断它指向的那个地址是不是有效——这一点等有站真的写了之后才有得测。 ## 631个页面里,零个 我在抓回来的631个页面里逐个搜了这两种声明。指向Markdown版本的零个,指向说明文件的零个。一个都没有。 这层声明的读者已经换了,AI爬虫抓取量超过Googlebot好几倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)改变了很多判断。 一项标记该不该做可以看采纳数据,官方第一次公开的全网使用统计 (https://zhangwenbao.com/schema-org-usage-statistics-priority-guide.html)比凭感觉堆类型强。 这个结果并不意外——规范八月十日才发布,抓取是八月下旬做的,中间只隔了十天出头。零采用率反映的是时间,不是态度。 要让这个基线有用,得把口径写死:抓哪一批站、每站抽几条、认哪几种写法算数、什么时候抓的。少写一条,半年后的对比就没法做。这也是我在正文里反复交代口径的原因之一。 ## 但它给了一个很好的基线 正因为现在是零,它成了一个干净的起点。半年后再跑同一套脚本,就能算出这半年里有多少站接上了这层声明,以及接上的是哪一类站。 监控工具各家口径差别很大,二十款监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)得先看它们怎么算。 长期观测要先把闭环搭起来,四步把引用率监控做成闭环 (https://zhangwenbao.com/monitor-measure-iterate-ai-citation-optimization-2026.html)可以套到别的指标上。 做这种长期观测最难的是找到起点。绝大多数技术采纳曲线,等到有人想起要量的时候已经过了早期阶段,只能从中段开始估。 这类新声明层的价值判断有个通用问法:它的读者是谁、那个读者有没有承诺读它、以及读了之后会不会改变什么。前一篇量robots.txt字段有效性时用的就是这套问法,答案是绝大多数字段过不了第二问。新层现在的处境跟当年那些字段刚出现时很像。 ## Google那边的表态很直接 官方说法是搜索本身不使用这些文件 (https://www.searchenginejournal.com/llms-txt-v2-formal-markdown-linking-ai-agents/586119/),维护它既不会帮你也不会害你。这句话把这层声明的性质定得很清楚:它是给别的读者准备的,不是给搜索引擎的。 不同引擎的偏好并不一样,四大AI搜索引擎的分引擎策略 (https://zhangwenbao.com/ai-search-engine-geo-optimization-strategy.html)是更靠前的一步。 判断某项标记有没有人读是同一个问题,结构化数据对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)里有官方说法和实测。 值不值得做,取决于你的内容有多少被AI助手引用、以及那些引用带不带来实际收益。这件事每个站的答案不一样,没法一概而论。 不过普及不等于写对。上一批我量过这层声明的另一面:某个站声明了236条地区版本,背后真实存在的页面只有6个。写了不等于对应的资源存在,这跟本篇讲的三层不一致是同一类问题,只是发生在别的字段上。 ## 语言版本声明倒是普及得很好 顺带量了一下多语言声明:631个页面里315个带了,占接近一半。这层声明已经是国际站的标配了,跟前面那层零采用形成鲜明对比。 生成器给的代码要复核,粘上去就是一份单向标注 (https://zhangwenbao.com/hreflang-generator-sitemap-return-tag-bidirectional-guide.html)是常见问题。 多语言标注可以自动生成,用脚本从爬虫结果生成多语言sitemap (https://zhangwenbao.com/ai-script-hreflang-xml-sitemap-multilingual.html)省掉手工维护。 差别在哪?语言声明直接影响哪个版本会展示给哪个国家的用户,收益立刻可见;新那层的收益既不确定也不可测。技术采纳的速度,最终还是由收益的可见度决定的。 确定唯一真相来源这件事说起来简单,落地时的难点是谁来当那个源。内容管理系统最有资格,因为页面状态本来就在它手里;但实践中robots.txt归运维、跳转规则归前端、防护规则归安全,没有一个系统能看到全貌。所以更现实的做法是定期做一致性比对,而不是指望某一处天然正确。 ## 第五层加进来之后,一致性检查更难了 现在一个页面的身份可能被五个地方声明:sitemap、robots.txt、页面上的索引指令、canonical、以及新的说明文件。它们分属五套系统,更新节奏各不相同。 多份声明怎么合成一个实体,@graph与知识图谱怎么搭 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)是另一套合并规则。 信号打架时怎么定夺,六类消歧信号的管控实战 (https://zhangwenbao.com/entity-disambiguation-mechanism-seo-signal-control.html)给了处理顺序。 不一致不是偶发故障,是这套架构的常态。真正该做的不是追求五处永远一致,而是明确哪一处是唯一真相来源,其它几处都从它生成。 ## 自查该按什么顺序做? 把这套检查落到自己站上,六步就够,顺序不能乱。 判断一个站的技术欠账有多深,三类站点的高ROI修复清单 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以当快速评估表。 常规全站审计有覆盖边界,桌面爬虫能查出的十二类问题清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)可以对照看缺哪块。 这一步还该顺手核对一件事:robots.txt里声明的地址,跟你在搜索引擎后台提交的那份是不是同一个。两处不一致的情况比想象中常见,尤其是站点做过改版或者换过生成工具之后。 ## 第一步:确认sitemap本身拿得到 用命令行拉一次robots.txt里声明的每一条sitemap地址,看状态码。这一步经常就能发现问题:声明的地址写错了、文件挂在一个已经废弃的域名下、或者被防护挡住。 官方后台里能挖的东西比想象中多,用过滤器精准拆分品牌流量 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)是个被低估的功能。 快速看一眼收录情况有个老办法,site命令怎么用、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)得先知道它的边界。 拿不到就没有后面的事。这也是为什么它必须排第一。 抽样时最好按页面类型分层:商品页、分类页、内容页、功能页各抽一部分,而不是完全随机。完全随机的话,地址数量最多的那类会占据绝大部分样本,而问题往往集中在数量少的那几类上。 ## 第二步:抽样,别全量 大站的sitemap动辄几十万条,全量校验成本太高而且没必要。每个子文件随机抽几条,覆盖各种页面类型即可。抽样时把随机种子写死,这样每次跑的是同一批地址,结果可比。 抽样跑实测是这类结论的常规做法,46个电商站里4个的商品链接根本没被读到 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)也是这么量出来的。 抽样与对照的思路在别处也通用,别让本来就会买的人冒领功劳 (https://zhangwenbao.com/incrementality-testing-marketing-measurement-guide.html)那套测法值得借鉴。 本文用的口径是每站至多6条,是为了跨站对比;自查的话每站抽一两百条更合适。 请求本身也有讲究:跟随跳转但限制次数,超过五六跳就当异常记下来;设一个合理的超时,太长会让整批跑不完;响应体只留前面一部分,头部区域的信息足够判断这几层,全文下载纯属浪费。这三条能让一次几百条的抽样在几分钟内跑完。 ## 第三步:一次请求拿齐三层信息 对每条抽样地址发一次请求,跟随跳转,同时记下:最终状态码、跳转次数、最终地址、响应头里的索引声明、页面里的索引声明、canonical。一次请求全部拿到,别分几轮。 页面骨架层面也有一次性体检,揪出标题层级、图片alt与语义标签短板 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)适合改版后跑。 看清一个地址的真实响应有顺手工具,用接口测试工具查状态码与响应头 (https://zhangwenbao.com/api-tester-http-status-header-rest-debug-seo-guide.html)比在线评分靠谱。 记得保存原始响应,方便事后复查。存下来的东西比结论有价值——结论会因为判据变化而改,原始数据不会。 对照的身份也别只换一个。条件允许的话跑三组:搜索引擎标识、普通浏览器标识、以及完全不带标识。三组结果放在一起,能把防护规则的判断依据大致还原出来——是看标识、看频率,还是看请求头的完整程度。 ## 第四步:做身份对照 把所有非200的地址挑出来,换一个普通浏览器身份重抓一次。变成200的那些从失分里刨掉,单独归为一类:这个地址正常,只是不接待爬虫身份。 同一家的抓取器也不都守同一套规矩,有一整类抓取器压根不看robots.txt (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)这次改名把它推到台前。 新出现的抓取器要单独认一遍,Google-Agent是什么、怎么识别和应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是最近才需要处理的问题。 这一步在本文里刨掉了28.6%的失败。跳过它,结论会系统性地夸大问题。 这一步还能顺手校准优先级:命中数最多的那几个站往往就是流量最大的那几个,因为它们页面多、结构复杂。按命中数排序基本等同于按影响面排序,不用另外算权重。 ## 第五步:按站分组,先判系统性还是零星 把失分按站分组。同一个站命中三条以上就去查规则,别急着修地址。本文样本里13个站是六条全中,那13个站真正需要处理的是一条规则,不是七十八条地址。 排期这件事在大促期间尤其要紧,大促与日常SEO的八维度差异 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)给了完整时间轴。 分组之后该派给谁也要想清楚,内容、技术、外链三类分工与团队配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)是同一个协作问题。 接回去的方式不必复杂。最省事的做法是维护一份排除清单,生成时过一遍;稍微讲究一点的是在导出前对每条地址发一次轻量请求,非200的直接不写。后者对几十万条的大站成本偏高,可以只对最近改动过的那部分做。 ## 第六步:把结论接回生成程序 最后一步也是最容易被跳过的:把校验逻辑接进sitemap的生成流程,让下次导出时自动排除掉那些状态不对的地址。 自动化流程会走形,那批页面早已进了索引 (https://zhangwenbao.com/ai-automation-runtime-rot-guardrails.html)说的就是没人复查的后果。 这类小脚本自己写最快,用Vibe Coding做SEO小工具的八步避坑 (https://zhangwenbao.com/vibe-coding-seo-tool-tutorial.html)讲的就是自养工具。 不做这一步,这次修完的东西下个月又会回来,因为生成程序还是老样子。审计的价值不在于修了多少条,在于有没有把判据固化进流程。 ## 这批数据里,哪几处口径差点搞错? 照例交代方法论上的坑,给想复现的人省时间。 样本量大不代表结论可用,三千条数据揭开的认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)说明该信什么不该信什么。 同一个名字各家算法不同到处都是,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 ## 第一处:没做身份对照,结论会夸大三成 这是本批最大的一处。第一轮抓完直接算,非200的有63条;做完对照才知道其中18条是身份问题。如果不做,会得出交付层失败率9.1%的结论,而实际是6.5%。 两个数字对不上先怀疑口径,工具排名为何与实际不一致 (https://zhangwenbao.com/webmaster-tool-query-website-keywords-ranking-and-baidu-search-results-are-inconsistent-reasons.html)给了六步排查法。 没有记录就没有结论,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)那套挖法可以直接套用。 更糟的是它会误伤具体的站:那六个403变200的站会被写进有问题的名单,而它们的页面对普通用户完全正常。 这个坑的成因很典型:判据是在看到数据之前定的,而数据里存在一种当初没想到的正常情况。所以任何一版统计跑完,都得随机翻二三十条明细人工看一遍——不是为了验证结论,是为了发现自己漏掉了哪种情况。 ## 第二处:canonical指向别处要先刨掉跳转 原始统计是35条指向别处。翻明细才发现其中一批是因为页面跳转了,canonical指向的是跳转后的最终地址——那是完全正确的行为。刨掉之后是16条。 标签类地址的处理也要单独定,标签页URL优化与301重定向实战 (https://zhangwenbao.com/shopify-tag-url.html)是一个具体例子。 不同页面类型该给什么声明有差别,五类页面的配置差异 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)可以直接照搬。 判据是拿canonical跟提交地址和最终地址两个都比一遍,只有两个都不等才算问题。第一版脚本只比了提交地址,虚高了一倍多。 ## 第三处:抽样上限决定了谁的比例被算进去 每站至多抽6条,是为了不让地址有几十万条的巨型站压过只有几百条的小站。如果按地址总数比例抽,最后的数字基本就是那三五个巨型站的数字。 把指标拆层看更清楚,社媒指标拆成四层漏斗 (https://zhangwenbao.com/social-media-metrics-funnel-vanity-vs-business.html)是一种可搬用的拆法。 指标怎么选决定了你看到什么,砍掉虚荣指标只盯真信号 (https://zhangwenbao.com/vanity-metrics-north-star-omtm-ecommerce.html)是同一种取舍。 这个选择有代价:小站的六条抽样统计意义有限,一条失分就是16.7%。所以站级结论我只用了命中数,没用比例。 ## 第四处:sitemap的两层结构不能只抓一层 116个站的sitemap是索引文件,里面套着子文件。第一版脚本只抓了第一层,结果拿到的全是索引文件本身,一条真实地址都没有。 解析结构化文本别靠肉眼,把JSON-LD调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)省下不少比对。 解析器的边界要自己试出来,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)是同一类静默失败。 补了第二层之后才有了26万条地址。做这类抓取时,先看拿回来的是索引还是清单,这个判断必须写进脚本,不能靠肉眼。 ## 第五处:一个不报错的PHP坑 输出统计时,双引号字符串里变量名后面紧跟中文标点,标点会被当成变量名的一部分。这批犯了两次,两次都是关键数字凭空消失。修法是所有插值一律用花括号包起来。 有些字节级问题症状很明显,一个看不见的字节头就能让页面白屏 (https://zhangwenbao.com/notepad-edit-saved-code-generate-bom-resulting-web-page-error-white-screen-solution.html)是另一种极端。 脚本层面的小疏忽代价可能很大,上传目录还能跑PHP的五种加固写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是另一类低级但致命的问题。 还有一层原因是这类实验的结论有保质期。所有数字都是2026年8月下旬那几天的快照,站点每天都在改。半年后重跑同一套脚本,比例大概率会变,而变化本身才是更有价值的数据——前提是这次的口径写得足够清楚,让那时候的人跑得出可比的结果。 ## 为什么把这些写出来 因为9.1%和6.5%这两个数字放进文章里都很有说服力,读者无从判断哪个对。把判据、剔除规则、修正过程摊开,是唯一能让人放心引用的做法。数字本身不值钱,能被复现的数字才值钱。 把过程写出来比只给结论有用,从AI搜索到结构化数据的实施策略 (https://zhangwenbao.com/geo-strategy.html)也是一步步摊开的。 数据分析入门先建立习惯,三类工具与排名追踪的日常做法 (https://zhangwenbao.com/seo-data-concept.html)比学工具更重要。 ## 常见问题解答 ## sitemap里的地址返回404,影响大吗? 影响的是抓取效率而不是排名。搜索引擎会浪费一次抓取额度去撞一个不存在的地址,量大的时候会明显拖慢新页面的发现速度。本文样本里404占1.3%,比例不高;更值得注意的是500,那会引发重试,浪费的额度是404的好几倍。 ## 页面写了不要索引,还留在sitemap里对吗? 短期是对的,长期不对。想让一个已收录页面消失,必须让对方抓到并读到那行指令,所以保留一段时间是标准做法。但如果这个标注已经挂了几个月、sitemap还在天天提交,就说明生成程序没有读页面状态。判断办法是看那条记录的最后修改时间有没有跟着变。 ## canonical指向别的地址,这条还该不该提交? 不该。提交等于说这是我希望被收录的版本,而canonical说正主是另一个,两个声明互相拆台。正确做法是把sitemap里的记录换成canonical指向的那个地址。本文样本里刨掉跳转因素后有16条属于这种情况。 ## 抓自己的站需要做身份对照吗? 需要,尤其是站前面挂了边缘防护的时候。防护规则经常按身份标识判,用爬虫标识从公司网络发请求,很可能被自家防护拦下。本文的对照实验里,63条失败中有18条换个身份就正常了,占28.6%。 ## 被自己robots.txt挡住的地址真的很少见吗? 实测确实少见。694条抽样里只有2条,扩大到全量每站抽300条也只有0.05%。原因是sitemap和robots.txt通常由不同系统生成,覆盖的地址空间本来就不太重叠,而且这类问题一旦发生后果非常显眼,很快会被修掉。审计清单里把它列为高危项,跟实际风险已经不太匹配。 ## llms.md第二版那两种声明现在有人用吗? 本文抓的631个页面里一个都没有。规范八月十日发布,抓取在八月下旬做,中间只有十天出头,零采用反映的是时间不是态度。Google那边明确说搜索本身不使用这些文件,维护它既不会帮你也不会害你,所以是否要做取决于你的内容有多少被AI助手引用。 ## 这套检查多久做一次合适? 抽样版每月一次,全量版每季度一次。更重要的是把校验逻辑接进sitemap的生成流程,让不合格的地址在导出时就被排除掉。不做这一步的话,这次修完的问题下个月还会原样回来,因为生成程序没变。 ## 权威参考资料 ## HTTP响应头自相矛盾:142个站里108个在犯 - URL:https://zhangwenbao.com/http-response-header-self-contradiction-audit.html - 分类:技术SEO - 发布:2026-08-20 | 更新:2026-08-21 - 摘要:两个字段说了相反的话,页面照常打开,控制台一声不吭。你以为配好的那条,可能早就被规范判掉了。 - 关键词:技术SEO,HTTP响应头,独立站运营,内容安全策略 > **TLDR**:摘要:把142个海外品牌独立站首页的最终响应头逐字段拆开对照,108个站(76.1%)至少有一处自己跟自己打架的声明。并存不等于都生效,规范给的下场有三种:同名字段发两次会被合并成一条,两代指令并存会有一条自动作废,语法写错则整条字段直接被丢弃。最典型的一组是有5个站把内容安全策略的写法塞进了X-Frame-Options,浏览器不认这种取值,结果那行防嵌套声明等于没写。还有3个站在脚本策略里同时写了strict-dynamic和一长串白名单域,其中一个站列了82个域,按规范全部被忽略。 > 摘要:把142个海外品牌独立站首页的最终响应头逐字段拆开对照,108个站(76.1%)至少有一处自己跟自己打架的声明。并存不等于都生效,规范给的下场有三种:同名字段发两次会被合并成一条,两代指令并存会有一条自动作废,语法写错则整条字段直接被丢弃。最典型的一组是有5个站把内容安全策略的写法塞进了X-Frame-Options,浏览器不认这种取值,结果那行防嵌套声明等于没写。还有3个站在脚本策略里同时写了strict-dynamic和一长串白名单域,其中一个站列了82个域,按规范全部被忽略。 上一篇量的是robots.txt里两条规则撞车的事,判决依据是路径长度。有读者问了个好问题:同一份HTTP响应里两个字段说反话,是不是也有类似的裁决表? 有,而且比robots.txt那套复杂得多。robots.txt只有一条仲裁规则,HTTP这边每个字段各有各的合并逻辑,有的合并、有的作废、有的直接把整行丢掉。保哥把两周前抓的那批响应头翻出来重新过了一遍,专挑自相矛盾的地方看。 样本是142个最终返回200的站点首页,字段名去重233种。下面的数字都以这142个站为分母。 ## 一份响应里同时写两条相反的指令,有多常见? 先给总数:108个站至少有一处,占76.1%。命中一类的38个站,命中两类的66个站,命中三类的4个站。也就是说四分之三的站点在自己的响应头里放了至少一处会被规范判掉的声明。 响应头能做的事情比多数人以为的多,X-Robots、缓存与Vary的实战机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)是一份系统梳理。 上一篇量的是另一份文件里的同类问题,两条规则撞车时赢的不是先写的那条 (https://zhangwenbao.com/robots-txt-rule-conflict-longest-match-audit.html),判决依据是路径长度。 ## 什么算矛盾,什么不算 判定之前得先划清界限。同一个响应里出现两个跟缓存有关的字段,本身不叫矛盾——Cache-Control和Expires可以共存,只要它们说的是同一件事。叫矛盾的是它们说的不是一件事:一个说别存,另一个给了个一年后的过期时间。 判据不清会让问题被夸大,大量无用页面拖垮流量的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 声明与实际行为的落差我量过一次,说会变的有3个、真变的有17个 (https://zhangwenbao.com/vary-header-declared-vs-actual-response-variation.html)就是那批数据。 缓存那几个字段的配合最容易写岔,怎么配才能既秒开又不出改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)讲得比较细。 同理,X-Frame-Options和内容安全策略里的frame-ancestors可以共存,那是为了照顾老浏览器。但如果一个写着谁都不许嵌套、另一个允许自家子域嵌套,那就是两份互斥的意图挤在同一个响应里。 这个比例乍看吓人,实际要分层理解。里面有一大半来自平台默认下发的模板,站主既没写过也删不掉;真正由站主自己写出来的那部分,重算之后是51个站,占35.9%。后面会专门拆这一层。 ## 十二种形态,按覆盖面排开 把142个站的响应头逐个拆完,一共归出十二种形态。前两种各占40.1%,是绝对的大头,剩下十种加起来才三成多。 形态分类清楚才好逐类处理,分面导航产生的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)是同一种拆法。 服务器上那些配置项值得逐条核一遍,影响SEO的二十项服务器配置清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着对。 同一批响应头里还量过另一件事,248个死字段里多数不是你写的 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html)而是平台统一下发的。 形态 | 站数 | 占比 | 规范给的下场 | 同名字段发了两次且取值不同 | 57 | 40.1% | 合并成一条 | 已废弃指令与取代它的新指令并存 | 57 | 40.1% | 老的那条不再有独立作用 | 同一个Cookie写了两套到期时间 | 22 | 15.5% | Max-Age赢,Expires被忽略 | 缓存指令内部打架 | 11 | 7.7% | 最严格的那条赢 | 防嵌套的新旧两版说的不一样 | 10 | 7.0% | 支持新版的浏览器只看新版 | Expires与max-age说的不是一个时间 | 8 | 5.6% | max-age赢 | X-Frame-Options写成了新语法 | 5 | 3.5% | 取值非法,整行丢弃 | 只报告模式里写了会被忽略的指令 | 4 | 2.8% | 该指令在这个模式下无效 | 白名单被strict-dynamic作废 | 3 | 2.1% | 整串域名被忽略 | preload写了但条件不满足 | 2 | 1.4% | 提交列表会被拒 | 跨域通配与凭据并存 | 2 | 1.4% | 浏览器拒绝整个请求 | 两代上报指令并存 | 1 | 0.7% | 新的那条赢 | 另一个边界是本文只看首页。响应头经常按路径规则下发,商品页、结算页、静态资源各有各的配置,首页干净不代表全站干净。选首页是因为它是唯一每个站都必然存在、且不需要猜地址的页面,代价是覆盖面窄。 ## 为什么这些东西一个都没被工具报出来 市面上查安全响应头的在线工具有一堆,它们的检查逻辑基本是同一套:这个字段有没有、取值在不在推荐清单里、评个分。这套逻辑天然看不见矛盾——因为矛盾是两个字段之间的关系,而工具是逐个字段打分的。 看清一个地址的真实响应有顺手的办法,用接口测试工具查状态码与响应头 (https://zhangwenbao.com/api-tester-http-status-header-rest-debug-seo-guide.html)比在线评分靠谱。 工具给的分数不等于事实,第三方数据到底准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 更麻烦的是评分机制会奖励矛盾。你把X-Frame-Options和frame-ancestors都写上,两项都得分;写得对不对、有没有互相拆台,评分表里没有这一栏。于是照着评分工具做优化,做出来的往往正是这批并存声明。 还有一类容易被误判成矛盾的情况得排除掉:同一个字段在跳转链的不同段里取值不同。跳转响应和最终页面本来就该有不同的缓存策略,把它们混在一起统计只会得出一堆假问题。本文所有数字都只看最终那一段2xx响应。 ## 响应头本身有多大 顺带量了一下体量。这142个站的响应头字段行数中位是27行,最少的4行,最多的42行;字节数中位3204,最小98,最大17951。矛盾字段本身占不了几个字节,所以清理它们的理由从来不是性能。 服务器上那些数值配置有反噬,限速拒掉的第四个请求正好是robots.txt (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html)会让抓取停十几个小时。 头部压缩在不同协议下差别很大,同样是4096的表HTTP/3早678字节就丢光了红利 (https://zhangwenbao.com/qpack-dynamic-table-zero-http3-header-compression-seo.html)是实测出来的。 请求方向的字节账更值得看,同一份Cookie每次请求都重发一遍 (https://zhangwenbao.com/http2-hpack-cookie-request-header-bytes-seo.html)本来是可以只发一次的。 真正的代价是别的:一是审计时的假信号,二是它挤掉了本该配上的那些字段。一个站的安全响应头预算不是无限的,你在那儿写两遍互相拆台的防嵌套声明,就没人再去看跨域隔离那几项配没配。 ## 两条并存,规范给的三种下场分别是什么? 这是本文最该记住的一节。并存的结果不是一种,是三种,而且它们的后果差别极大。 两个手段该用哪个也常被搞反,robots.txt和meta robots各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)里分工写得很清楚。 状态码那一层也有类似的取舍表,301、302、404和410各自该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)能省掉不少争论。 ## 第一种:合并成一条 HTTP的字段语法允许同一个字段名出现多次 (https://www.rfc-editor.org/rfc/rfc9110.html),语义上等价于把各行的值用逗号连起来。所以发两个Vary,一个写Accept、一个写accept-encoding,等价于发一个写着两者的Vary。这不是错误,只是写法不整洁。 字段堆太多还会撑爆请求,老用户打不开的页面而工具全都返回200 (https://zhangwenbao.com/request-header-too-large-400-431-cookie-seo-blindspot.html)就是这么来的。 这个字段写多了会把缓存切碎,决定收录哪一版的不是你的配置 (https://zhangwenbao.com/vary-header-cache-fragmentation-googlebot-version-seo.html)而是十分钟前路过的那个用户。 需要留意的是这条规则有例外。Set-Cookie就不能这样合并,它的取值里本来就带逗号,所以规范专门给它开了口子——每一行是一个独立的Cookie。这也是为什么Set-Cookie永远是响应头里行数最多的那一块。 ## 第二种:其中一条自动作废 这是最容易出事的一类,因为两条声明都合法、都会被解析,只是有一条按规范被无视了。缓存那一组最典型:同时给了Cache-Control的max-age和Expires,规范明确要求以max-age为准 (https://www.rfc-editor.org/rfc/rfc9111.html),Expires只在没有max-age时才被看。 多层缓存下的取舍更复杂,回源、TTL分层与缓存键怎么配 (https://zhangwenbao.com/cdn-edge-caching-strategy-ttl-cache-control-purge-origin-shield.html)有一份完整实战。 验证类字段配错的代价也不小,没改过的页面对爬虫重发了几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)是同一类浪费。 Cookie上也有一模一样的一对:同时写Expires和Max-Age,Max-Age赢。样本里22个站的Cookie两样都写了,多半是为了兼容极老的浏览器,代价是那个Expires值成了摆设——如果两者算出来的时间不同,你以为的过期时间就是错的。 顺带说个容易混的点:作废和丢弃不是一回事。作废是这条声明被解析了、也被理解了,只是按规范让位给另一条;丢弃是它根本没被当成有效声明。前者你至少知道行为是可预期的,后者等于凭空少了一个字段。 ## 第三种:整条字段被丢掉 最狠的一种。字段取值不符合语法,浏览器不会去猜你的意思,直接当这行不存在。X-Frame-Options只认两个取值,写别的就属于非法取值;内容安全策略里某个指令写了不认识的关键字,那条指令会被整个跳过。 有些字节级问题症状反而很明显,一个看不见的字节头就能让页面白屏 (https://zhangwenbao.com/notepad-edit-saved-code-generate-bom-resulting-web-page-error-white-screen-solution.html)是另一种极端。 同样的静默失败在结构化数据里更狠,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)而页面照常显示。 这一类的可怕之处在于它没有任何反馈。控制台不一定报,工具不一定查,你只能通过实际行为发现——而防嵌套这种东西平时根本不会有人去试。 这三种下场还有一个共同点:全都不产生任何错误提示。页面照常打开,控制台通常也是安静的,只有在你真的去试那个被声明约束的行为时才会显形。这跟语法错误完全不同——语法错误至少有人会告诉你。 ## 三种下场对应三种排查方法 合并类只需要整理,不影响行为,优先级最低。作废类要查两条声明说的是不是同一件事,不一致就以规范判赢的那条为准,把另一条改成一致或者删掉。丢弃类必须实测,因为静态看是看不出来的。 常规全站审计有覆盖边界,桌面爬虫能查出的十二类问题清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)可以对照看缺哪块。 资深团队栽跟头往往在结构性问题上,被忽略的那几类技术SEO失灵原因 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的就是这种局面。 一堆问题先修哪个得有依据,五百个站实测排出来的技术SEO优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)可以当排期底稿。 我给客户做检查时的顺序就是倒过来的:先查丢弃类,再查作废类,最后才顺手整理合并类。花的时间也差不多是这个比例,丢弃类要一条条实际发请求验证。 ## 同一个头发两次,浏览器会听哪一次? 57个站命中了这一类,是并列第一的形态。展开看会发现它几乎全是同一个来源。 配置每次reload都通过不代表没事,Googlebot每八次抓取就有一次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类隐形代价。 取响应头的姿势不对会漏字段,用HEAD查说没配缓存头、换成GET那五个全在 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)是踩过的坑。 ## 五十多个站的表现一模一样 这57个站里有绝大多数是同一种写法:两行Vary,一行写着Accept,另一行写着accept-encoding。连大小写风格都一致——前一行首字母大写,后一行全小写。这种一致性只能来自同一套平台代码。 平台决定的东西不止响应头,架构搭错了爬虫根本找不到商品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是更上游的问题。 平台默认给的东西要先认清,Shopify的128种结构化数据类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)也是同一个问题。 选平台时就该问清楚默认配置,托管、自建还是纯代码怎么选 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)把各自代价摊开了。 按规范这两行合并成Vary: Accept, accept-encoding,行为完全正确,没有任何损失。它只是把一件本可以一行说完的事说了两遍,而且两遍风格还不统一。 ## 有一个站的两行说的是不同的事 真正值得看的是那些不属于这套模板的。bershka.com发了两行Cache-Control:一行写着no-cache、no-store、must-revalidate,另一行只写no-cache、no-store。合并之后等价于三个指令都在,那个must-revalidate不会因为第二行没提就消失。 在边缘层改东西越来越常见,在CDN边缘改SEO的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)给了几种现成形态。 多层架构下每层都可能插一手,多层缓存如何同时左右体验指标与抓取 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)讲了各层的分工。 这种情况通常说明响应经过了两层:应用层写了一版,前面某个代理或者边缘节点又加了一版,两边都没检查对方写过没有。合并结果碰巧是安全的,但下次某一层改成了相反的指令,问题就出来了。 ## 三行cache-status暴露了整条链路 另外两个站发了三行cache-status,分别来自平台的持久缓存层、框架层和边缘层,每一行报告自己那一层的命中情况。这种写法是规范鼓励的——它本来就设计成多层各写一行。 缓存层数一多就得逐层看,索引器、缓存与Redis调优怎么讲透 (https://zhangwenbao.com/magento-2-performance-tuning-indexer-cache-redis-varnish-production-mode.html)是一个完整案例。 把链路上的记录收拢起来才好排查,日志怎么收集成可检索的结构 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是越早做越好的事。 顺带说,这也是一个很好的排查素材。三行摆在一起,能一眼看出请求穿过了几层缓存、每层是命中还是回源。可惜大部分站只有一层缓存,或者干脆不发这个字段。 ## 什么时候两行会真的出事 合并规则的前提是这个字段的语法允许逗号分隔的列表。对不允许列表值的字段,两行就是灾难——比如Content-Length发两次且值不同,规范要求当成错误处理,中间设备可能直接断开连接。 压缩协商配错同样会静默失分,出厂只压HTML一种类型、其余字节全额计入预算 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)是常见默认值。 协议层的错误常常悄无声息,抓取速率被调低的那几天日志里一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这种情形。 样本里没有出现这种情况,因为这类错误会立刻导致页面打不开,早就被发现了。真正长期存活下来的矛盾,都是那些不影响页面正常显示的。 ## 缓存那几个字段为什么最容易写岔? 缓存这一块有两组独立的矛盾:一组发生在Cache-Control内部,一组发生在它和Expires之间。前者11个站,后者8个站。 这些字段通常写在同一个配置文件里,重写、缓存、规范化与HSTS六层治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)可以一起看。 同一批域名上量过验证类字段,142个站里只有52个回得出304 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)口径卡得很死。 ## 不许存储和存一年,同时写在一行里 Cache-Control的取值是一串用逗号隔开的指令,它们之间没有语法上的互斥要求,所以什么组合都写得出来。样本里最常见的组合是private加no-store加no-cache加max-age=0,四个指令堆在一起,10个站是这个写法。 压缩与缓存经常被混为一谈,免插件压缩HTML与GZIP叠加怎么做 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)分清了两件事。 缓存判断写错的表现很隐蔽,首页一直是旧数据、一个字符改对缓存判断 (https://zhangwenbao.com/dedecms-mobile-index-html-update-solution.html)就是这类问题。 这一串里真正起作用的只有no-store,它的语义是任何缓存都不得存储这个响应,其它三个说的事情它全包了。private是说共享缓存别存、私有缓存可以存,跟no-store直接冲突;no-cache是说可以存但每次要回源验证,同样被no-store覆盖。 反过来看,真正需要精细控制的站会怎么写?样本里做得最干净的几个,首页只写一条Cache-Control,取值是private加max-age=0,意思是浏览器自己可以缓存但每次都得验证,共享缓存别碰。一条说清楚一件事,别的什么都不加。 ## 为什么大家爱这么写 这串东西是有历史来源的。不同年代的浏览器对缓存指令的支持程度不一样,早年确实需要把几个指令都写上才能保证行为一致。这套写法被写进了各种教程和框架默认值,一路抄到了今天。 框架默认值抄进来的东西不少,头部那几行dns-prefetch和emoji代码怎么去掉 (https://zhangwenbao.com/wordpress-cancels-loading-of-google-dns-prefetch-and-s-w-org.html)是同一种清理。 这类失分往往第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同批经验的汇总。 抄来的配置攒久了就是欠账,技术债怎么排查和分批偿还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了可执行的顺序。 今天它不会造成实际损失,因为最严格的那条会赢,结果是安全的。但它掩盖了一个问题:写这行的人未必知道自己想要哪一种行为。等到哪天需要把首页改成可以被边缘缓存几秒钟,他会不知道该删哪几个词。 ## Expires写着1984年,Cache-Control写着现在 另一组更有意思。8个站的Expires和Cache-Control说的不是一个时间,其中casetify.com的Expires写着1984年1月11日——那是Netscape时代用来表示立即过期的经典写法,比很多读者的年纪都大。 时间戳的零点经常被当成占位值,从sitemap的lastmod到结构化数据的日期 (https://zhangwenbao.com/timestamp-converter-unix-epoch-sitemap-lastmod-guide.html)都得转对。 时间格式这一层坑不少,ISO 8601、sitemap与HTTP头各自要什么格式 (https://zhangwenbao.com/date-formatter-iso8601-sitemap-lastmod-rfc2822-guide.html)有一份速查。 otto.de写的是1970年1月1日,也就是时间戳的零点。还有几个站直接写了一个减一。这些写法在纯Expires时代都是有效的立即过期表达,今天它们和同一响应里的max-age=0并存,按规范以max-age为准,Expires被完全忽略。 站点 | Cache-Control | Expires | 谁生效 | casetify.com | max-age=0, no-cache, no-store, must-revalidate | 1984年1月11日 | max-age=0 | otto.de | private, no-cache, no-store, max-age=0 | 1970年1月1日 | no-store | segway.com | no-store, no-cache, must-revalidate, max-age=0 | 三十天后 | no-store | bolia.com | no-cache, no-store | 减一 | no-cache/no-store | ## segway那条最值得说 前面几个站的Expires写的是过去时间,跟max-age=0意图一致,属于写法冗余。segway.com不一样:它的Expires写的是三十天之后,而Cache-Control写着不许存储。两个字段的意图完全相反。 老技术还在链路上跑这件事很常见,那套跳转脚本下线之后留下的迁移账 (https://zhangwenbao.com/baidu-uaredirect-js-dedecms-jumps-to-mobile.html)是个完整复盘。 老设备与新协议共存是常态,整站都开了HTTP/3而最关键那个请求还走HTTP/2 (https://zhangwenbao.com/http3-alt-svc-discovery-first-request-crawler-seo.html)就是例子。 链路上还有谁在读你的响应,AI爬虫抓取量已经超过Googlebot好几倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)改变了很多判断。 按规范当然是no-store赢,浏览器不会存。但如果链路上有一个只认Expires的老代理,它就会把这个页面存三十天。这种设备在企业内网和某些运营商网络里还真不少见。 顺便说个判断技巧:看到一串四五个缓存指令堆在一起,先问写它的人想要哪一种行为。答不上来就说明这串是抄来的,可以整段换成一条明确的指令。答得上来的话,让他把那句话写成注释放在配置旁边,比什么审计都管用。 ## 缓存字段该怎么写才不留隐患 我的建议很简单:只写Cache-Control,不写Expires。后者存在的唯一理由是兼容HTTP/1.0,而今天的链路上纯1.0设备已经稀有到可以忽略。多写一个字段不但不能提高兼容性,反而制造了一个需要长期保持同步的副本。 换架构之后这套东西得重搭,sitemap、重定向这些不会自动跟过来 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是常见上线失分点。 这类改动需要后端配合,后端工程师配合SEO的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)是从真实账本里总结的。 要是因为某些历史原因必须保留Expires,那就让它和max-age算出来的时间严格一致,并且把这件事写进部署检查里。人工维护两个必须同步的值,早晚会漂。 ## 拒绝嵌套这件事,为什么两套写法会打架? 防止别的站把你的页面套进iframe,历史上有两套写法:老的X-Frame-Options,和内容安全策略里的frame-ancestors。10个站的两套写法说的不是一回事。 内容被别人拿去用是同一类风险,一稿多发怎么不被副本反超 (https://zhangwenbao.com/content-syndication-seo-canonical-attribution-mechanism.html)给了归属声明的做法。 页面被别的东西顶替的后果很严重,人机验证屏被当成正文索引、规范网址判给了别站 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)是真实事故。 ## 这是少数几个跟搜索真有关系的安全字段 Google那边对安全响应头的态度 (https://www.searchenginejournal.com/google-says-x-frame-options-matters-for-seo/580126/)一直很清楚:绝大多数跟搜索没关系。唯一被点名说有关系的就是防嵌套这一类——因为别人把你的内容嵌进他的页面,可能会让那一页跟你抢排名。 整套加固该做哪些项,权限分离、目录迁移与应急响应的生产级清单 (https://zhangwenbao.com/dedecms-site-security-settings-in-linux-environment.html)可以对照排期。 安全字段里另一个值得配的是强制加密,HSTS怎么配、preload提交流程与回滚路径 (https://zhangwenbao.com/https-hsts.html)有完整步骤。 所以这一组值得单独花时间。它既是安全配置,又是少数几个能直接影响可见度的响应头。 ## 新版存在时,老版会被完全忽略 规范写得很直白:支持frame-ancestors的浏览器必须忽略X-Frame-Options。不是取交集,不是取更严格的,是完全忽略。这一点和缓存那边的最严格者胜完全不同,很多人会记混。 两种手段能不能一起用是高频疑问,noindex和canonical同时用的九种场景 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)逐个给了答案。 有些声明本来就只是提示不是命令,canonical是提示不是指令的八种误用 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html)解释了为什么它常常不生效。 于是就有了样本里最刺眼的两个例子。dji.com的X-Frame-Options写着deny,也就是谁都不许嵌,而同一个响应的frame-ancestors写着自己所有子域都可以嵌。现代浏览器只看后者,那行deny等于没写。gillette.com是同样的组合。 ## delonghi把本地开发地址留在了线上 更有戏剧性的是delonghi.com:X-Frame-Options写着deny,frame-ancestors写的是自己加上localhost的任意端口。localhost那一项显然是开发阶段为了调试加的,上线时没删。 流程走形通常从第二周开始,那批页面早已进了索引 (https://zhangwenbao.com/ai-automation-runtime-rot-guardrails.html)说的就是没人复查的后果。 开发环境的东西带到线上代价可能很大,测试站被索引后的八步清除与四层防御 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)是完整方案。 它实际造成的风险很低,因为攻击者的localhost指向的是他自己的机器。但这一行说明了一件事:这份策略从开发环境一路带到线上,中间没有任何人重新读过它。 这类问题在多品牌集团里尤其常见。同一套响应头模板被复制到几个站点,其中某个站点的开发环境配置连同调试用的来源一起被带到了线上,而复制它的人根本不知道那一项是干什么的。样本里那对同集团品牌的P3字段取值一模一样,就是同一种复制的产物。 ## 还有一批是把新语法写进了老字段 5个站的X-Frame-Options里塞了一串完整的网址。onepeloton.com写的是sameorigin后面跟着四个具体地址,其中一个还带着明显的临时部署域名。anker.com、eufy.com、soundcore.com、insta360.com也是类似写法。 装太多东西之后冲突排查更难,应用栈精简与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)给了可执行顺序。 模板重复带来的冲突很常见,插件和主题各冒出一套canonical怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同类清理。 这是把frame-ancestors的语法照搬到了X-Frame-Options上。可后者只认两个取值,别的一律算非法。非法取值的处理是整行丢弃,所以这五个站的这行声明一个字都没生效——它们同时还有frame-ancestors,所以实际防护没塌,但那一行纯属白写。 还有个细节值得留意:这五个站里有四个属于同一个消费电子集团旗下的品牌矩阵。同一份写错的模板被复制到了四个站上,而每个站的运维大概都以为这是总部审过的标准配置。模板复制这件事会把一个人的疏忽放大成一批站的问题。 ## 这一组的正确写法只有一句话 写frame-ancestors,把X-Frame-Options保持成最简单的deny或sameorigin,或者干脆不写。两者的意图必须一致,且老字段不要试图表达新字段才有的能力。 判断一个站的技术欠账有多深,三类站点的高ROI修复清单 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以当快速评估表。 完整的诊断框架能避免漏项,从抓取、内容到AI可见度的审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以当检查表。 需要允许某几个具体来源嵌套时,只能靠frame-ancestors。这时候老字段该写什么?写sameorigin是最稳的——支持新版的浏览器会忽略它,不支持的会退回到最保守的行为。 ## 把新语法写进老字段,会发生什么? 上一节最后那个现象值得单独展开,因为它是三种下场里最隐蔽的一种:整条字段被丢掉,而且没有任何提示。 写在哪里也会决定生不生效,工具说在head、浏览器说在body该信哪边 (https://zhangwenbao.com/head-boundary-canonical-parsed-into-body-seo.html)是一次真实排查。 有些地址连声明的地方都没有,接口和feed拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)是同一类结构性缺口。 ## 浏览器不会猜你的意思 HTTP字段的解析规则是严格的。取值不符合语法,处理方式是当这个字段不存在,而不是尽力理解。这跟HTML的容错解析完全相反——HTML里标签写错了浏览器会想办法补救,HTTP头里写错了就是没有。 解析与渲染各步都可能丢东西,抓取和渲染DOM分几步、哪一步会丢 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)讲得比较完整。 容错解析这件事在HTML那边完全不同,语义化HTML到底影响不影响抓取 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)拿样本页跑过一遍。 这个差异经常被搞混。写前端的人习惯了浏览器帮忙纠错,写响应头时会下意识以为差不多就行。实际上这一层没有差不多。 还有一个信号值得留意:如果一个字段的取值里出现了另一个字段才有的语法元素——分号分隔的指令、带引号的关键字、完整网址——那多半就是搬错了地方。这个特征用一条正则就能扫出来,适合放进上线前的检查脚本。 ## 怎么发现这类问题 静态检查基本无效,因为字段确实在响应里,工具能看到它。唯一可靠的办法是实测:真的构造一个嵌套页面试一下,或者打开开发者工具看控制台有没有关于该字段的警告。 页面被什么挡在索引外可以一次查清,可索引性体检把几层原因分开列 (https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html)比逐个猜快得多。 页面骨架层面也有一次性体检,揪出标题层级、图片alt与语义标签短板 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)适合改版后跑。 Chrome对非法的X-Frame-Options取值会在控制台留一条警告,写得还挺清楚。问题是没人会为了检查一个响应头专门去开控制台看,而这条警告只在真的发生嵌套尝试时才出现。 ## 内容安全策略里也有同类陷阱 一条指令里写了浏览器不认识的关键字,那个关键字会被忽略;如果整条指令的语法坏了,整条指令被跳过,但同一份策略里的别的指令照常生效。所以一份策略可能有一半在工作、一半是死的,而从外面看它是完整的。 第三方悄悄改默认值我量过一次,默认配置变更却没人通知 (https://zhangwenbao.com/third-party-default-changes-silent-drift-audit.html)的漂移比例并不低。 白名单漂移是这套策略的老毛病,白名单上明明写着那个域名、浏览器还是拦了 (https://zhangwenbao.com/csp-script-src-allowlist-drift-third-party-silent-block.html)是一次完整排查。 这也是为什么严格的内容安全策略必须配报告端点。没有报告,你永远不知道哪几条在真的拦东西、哪几条从来没被触发过。 这里还有一层容易被忽略的风险:同一个字段在不同规范版本里的合法取值可能变过。曾经存在过的allow-from写法早就被各家浏览器移除了,但它仍然出现在不少年代久远的教程里。照着老教程写出来的配置,语法上像模像样,实际是一行被丢弃的死字段。 ## 写字段前先去查一遍取值清单 说起来朴素,但这类问题的成因就是没查。X-Frame-Options的合法取值只有两个 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options),写第三个就是错;Referrer-Policy的合法取值有八个,写错一个整行失效。这些清单都在文档第一屏,花不了三分钟。 各家工具读同一个页面结论未必一致,十款技术栈检测扩展的实测对比 (https://zhangwenbao.com/seo-website-technology-stack.html)能看出差异有多大。 生成器给的预设也未必跟规范对齐,通配符判定会和标准打架的那几种情形 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)值得先看一眼。 更值得建立的习惯是:任何一个响应头字段改动上线后,用命令行拉一次真实响应,把改动的那一行原样贴出来看。人眼看一遍能抓住绝大多数手误,比任何工具都快。 ## 内容安全策略里那82个白名单域,为什么一个都不生效? 这是本批最戏剧性的一处。3个站在脚本策略里同时写了strict-dynamic和一长串白名单域名,其中bollandbranch.com列了82个,burrow.com列了38个,italic.com列了31个。 默认加载的东西本身就该定期清,关掉用不上的那几个默认脚本 (https://zhangwenbao.com/wordpress-window-wpemojisettings.html)是同一种瘦身。 跨域相关的字段还会影响监控,页面上近一半资源在监控里是一排零 (https://zhangwenbao.com/cross-origin-timing-allow-origin-web-vitals-blind-spot.html)就是被这类字段挡的。 ## strict-dynamic的语义就是作废白名单 这个关键字的设计目的 (https://w3c.github.io/webappsec-csp/)是解决白名单模式的老问题:白名单越列越长、越长越不安全。它的规则是一旦出现,同一条指令里所有基于地址的来源全部被忽略,只有带正确nonce或哈希的脚本才被信任,而且这些脚本动态加载的其它脚本会自动继承信任。 边缘防护的效果没那么确定,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测答案挺意外。 分层防护的思路在别处也一样,robots、UA识别、WAF三层的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比只改一处靠得住。 所以strict-dynamic和白名单不是叠加关系,是替代关系。写了前者,后面那一串域名在支持它的浏览器里一个字都不看。 把这三个站的白名单长度排开看也有意思:82、38、31。这个量级说明它们都到了白名单模式的极限——域名多到已经无法评估风险,正是引入strict-dynamic的典型动机。所以它们其实是走在正确路上的团队,只是没把上一代的东西收干净。 ## 82个域名意味着什么 那82个域名是一份完整的第三方脚本清单:分析工具、A/B测试、客服插件、支付、推荐引擎、广告像素。整理这份清单大概花了不少时间,每一个域名背后都对应着一次沟通和一次上线。 这些脚本背后是一整套数据链路,把各渠道花费拉进来算统一ROAS (https://zhangwenbao.com/ga4-import-ad-cost-data-non-google-blended-roas.html)说明了它们为什么必须留着。 每加一个第三方都是一次决策,怎么给店铺装上行为分析工具 (https://zhangwenbao.com/shopify-microsoft-clarity.html)是其中最常见的一类。 而它们全部被同一行里的一个关键字作废了。这不是安全事故——strict-dynamic本身更安全——但那份清单的维护成本白花了,更要命的是维护它的人以为自己在做一件有意义的事。 ## 兼容性考虑是它的正当理由,但要写清楚 公平地说,同时写两者有一个正当理由:不支持strict-dynamic的老浏览器会退回到白名单模式。规范也是这么设计的,属于渐进增强。 把约定写成文字永远划算,达标定义、违约责任与四类经典纠纷 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)是另一个场景的同一道理。 共同维护一份规则文件要立规矩,共享与个人怎么分、规则冲突听谁的 (https://zhangwenbao.com/claudemd-team-collaboration.html)是一套可搬用的做法。 问题在于这三个站的白名单里都没有注释说明这是兼容路径,团队里新来的人看到那一长串域名,只会以为它是当前生效的规则,继续往里加。做兼容退路可以,但必须在部署脚本或文档里写明白,否则它就会变成一份没人知道是死的活清单。 ## 还有一种写法是纯粹的自相矛盾 另一个组合更直接:同一条指令里既写了nonce又写了unsafe-inline。规范规定有nonce或哈希时,unsafe-inline被忽略。这个组合同样有兼容意图,但风险方向相反——它让人误以为内联脚本还能跑,上线后发现某个内联片段被拦了,排查半天。 优先级这类提示有明确的生效条件,浏览器资源优先级的机制与实战 (https://zhangwenbao.com/fetchpriority-priority-hints-resource-loading-optimization.html)讲清了边界。 资源提示写了未必被读,Googlebot为什么不读你的preload (https://zhangwenbao.com/why-googlebot-ignores-resource-hints.html)说明了哪些提示其实无效。 这次样本里这个组合是0个站,10个用了nonce的站里没有一个同时写unsafe-inline,说明用nonce的团队通常懂得比较深。倒是24个站直接写了unsafe-inline而没有nonce,那属于另一个话题了。 ## 只报告不拦截的那份策略,有多少是空转的? 内容安全策略有一个只报告不执行的模式,用来在正式上线前观察会拦掉什么。样本里5个站发了这个模式的策略,其中4个站有问题。 监控闭环怎么搭是通用问题,四步把引用率监控做成闭环 (https://zhangwenbao.com/monitor-measure-iterate-ai-citation-optimization-2026.html)可以套到别的指标上。 写了却没人读这件事我专门量过,有多少条指令压根没有接收方 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)比例比想象中高。 ## 在只报告模式里,有两条指令是被规范忽略的 frame-ancestors和sandbox这两条,在只报告模式下不生效,规范明文写了。原因也合理:这两条的效果是阻止加载或改变文档的沙箱状态,没法只报告不执行。 验证一条建议有没有效有个笨办法,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)比讲道理管用。 观察模式在别处也有讲究,A/B测试怎么做才不影响SEO (https://zhangwenbao.com/ab-testing-page-seo.html)里有官方表态和收尾动作。 byredo.com、govee.com、rab.equipment、vaude.com都在只报告策略里写了frame-ancestors。写的人多半想的是先观察一下有谁在嵌我的页面,可惜这条恰恰是观察不到的。 ## 更尴尬的是三个站连报告端点都没配 只报告模式的全部价值在于收到报告。byredo.com、rab.equipment、vaude.com三个站的策略里既没有report-uri也没有report-to,响应里也没有对应的端点定义字段。 收上来的数据要能读懂才有用,读懂Googlebot抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)给了分析路径。 没有记录就没有结论,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)那套挖法可以直接套用。 这意味着这份策略既不拦截,也没有任何人收得到它产生的报告。它在响应里占着几百个字节,纯粹是一份自我安慰。 ## 上一批量过一组类似的数字 这个现象和上一批量的网络错误上报是同一类。当时的结果是64个站启用了错误上报,全部只挂在旧版的端点定义上,而新版定义只有2个站在用,两者交叉之后没有一个站配对上。声明与接收端分离,是响应头里的常态。 同一批样本上还量过分组,给单个爬虫开组会丢掉通配组全部规则 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)中招比例高得离谱。 名单上那些名字有没有真来过也能量,266个爬虫令牌里只有23.3%真的来过 (https://zhangwenbao.com/crawler-ua-list-named-vs-real-visits-audit.html)是另一组实测。 区别在于那一批是新旧版本没接上,这一批是压根没配。前者还能说是迁移没跟上,后者只能说是抄了一半。 ## 只报告模式的正确用法 先配端点,再写策略,最后才观察。顺序反了就是空转。观察期建议至少两周,覆盖一次完整的营销活动周期——很多第三方脚本只在活动期间才加载。 能交给机器的就别靠人记,哪些SEO工作能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条边界。 观察期该覆盖一次完整活动周期,大促与日常SEO的八维度差异 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)给了完整时间轴。 观察完之后要做的事是把只报告改成正式执行,而不是让它一直挂着。样本里那5个站没办法判断挂了多久,但从策略内容的陈旧程度看,至少不是这个月才加的。 ## 这些矛盾是谁写的,你还是平台? 统计到一半就能看出来,这批矛盾里有相当大一块不是站主写的。判断依据很简单:完全相同的写法在几十个毫不相干的品牌上同时出现。 托管环境替你做的决定不止一处,主机可能正悄悄拦AI爬虫而监控没报警 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)是同一种失控。 平台层面的例外规则也要留意,通配组的星号对广告爬虫不生效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)是最容易漏的一条。 ## 两个占比40.1%的形态,都是平台指纹 57个站发两行Vary,57个站在策略里同时写升级不安全请求和阻止混合内容。这两组的站点名单高度重合,而且这批站在上一批的响应头体检里也是同一群——它们共用同一个托管电商平台。 批量生成的地址最容易被忽略,博客标签页怎么避免权重稀释 (https://zhangwenbao.com/shopify-blog-tag-seo.html)给了处理方法。 平台生成的东西要单独处理,集合页没有产品时该怎么办 (https://zhangwenbao.com/seo-empty-shopify-collections.html)有三种场景的分别处置。 把这两类从总数里刨掉,剩下自己写出来的矛盾还有多少?重算之后是51个站,占35.9%。这个数字更接近站主自己该负责的部分。 这里得说句公道话:平台下发这些字段本身不算错。它要照顾几十万家店铺、各种年代的浏览器,选一份保守的通用配置是合理的工程决策。问题出在它不告诉店主自己下发了什么,也不提供关掉某一项的开关。 ## 被废弃的那条指令,站主删不掉 阻止混合内容这条指令早就被升级不安全请求取代了,前者的行为是拦截,后者是自动改写成安全连接。两者并存时,后者先起作用,前者基本没有机会触发。 平台还在往响应链路上加新东西,要不要向AI爬虫按次抓取收钱 (https://zhangwenbao.com/cloudflare-pay-per-crawl-charge-ai-bots.html)已经有平台在做了。 该不该留下一个已经没用的东西,FAQ富结果被砍之后那段标记还写不写 (https://zhangwenbao.com/google-drops-faq-rich-results.html)是同一道选择题。 这条是平台在响应头模板里统一下发的,店主既没写过它,也没有权限删。上一批量响应头里那批没有接收端的字段时,遇到的是完全一样的局面:站主连清理的权限都没有。 还有个更省事的判断:看这个字段在你自己的配置文件里搜不搜得到。搜得到就是自己写的,搜不到还出现在响应里,那它一定是链路上某一层加的——可能是平台,也可能是边缘防护或者反向代理。这三层各自会加什么,值得单独整理一份清单。 ## 怎么快速判断一处矛盾是不是平台给的 三个办法。第一,把那一行原样贴进搜索引擎,看看有没有一堆别的站出现同款;第二,看这个字段的取值风格跟你自己写的那些是不是一致,平台下发的通常大小写和空格风格与众不同;第三,直接换一个同平台的店铺地址抓一次响应头,一比就知道。 另一套代理的行为也值得对照,mod_proxy全景与HTTPS配置 (https://zhangwenbao.com/apache-proxy.html)跟前者的差异不小。 反向代理那一层经常会加字段,proxy_pass的斜杠、重写与WebSocket全场景配置 (https://zhangwenbao.com/nginx-proxy.html)说明了它能改什么。 确认是平台的之后,能做的事情不多,但至少可以从自己的待办清单里划掉,同时在文档里记一笔,免得下次审计又被同一条报出来。 还有一个判断维度是看这条声明有没有随业务变过。平台下发的字段在所有店铺上完全一致、多年不变;自己写的那些会带着业务痕迹,比如某个促销活动留下的临时来源、某次合规整改加上的策略。带痕迹的那些才是你真正需要维护的。 ## 自己写的那批,集中在哪几类 刨掉平台指纹之后,剩下的分布是:Cookie双到期22个站、缓存内部打架11个站、防嵌套两版不一致10个站、Expires与max-age不一致8个站、老字段写新语法5个站。 结构化数据里也有大量白写的字段,112个独立站里17个在犯的商家名称错误 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是一份对照。 有些声明必须两层都写才算数,一键退订少写一层就整个域名限流 (https://zhangwenbao.com/one-click-unsubscribe-header-body-two-layers.html)是代价最直接的一例。 这五类有个共同点,它们都发生在需要人做判断的地方。平台可以替你下发一份通用策略,但你的Cookie存多久、首页能不能被缓存、允许谁嵌你的页面,这些只能自己定——而定的时候没人查规范。 ## 清掉这些矛盾,能省多少字节? 先把这个问题堵死,免得有人拿性能当理由去说服老板。 有一条硬边界可以本地复现,Googlebot那个2MB抓取上限怎么测 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)有现成的检查器。 字节预算这件事在页面层更要命,46个电商站里4个的商品链接根本没被读到 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)是实测结果。 ## 算一笔账 响应头字节数中位是3204,最大的那个站17951。矛盾字段本身,一行Vary大概二十来个字节,一行Expires三十几个,X-Frame-Options五十上下。全清理掉,一个典型站点能省一百多个字节。 把字节换算成成本是另一个视角,从页面碳足迹到爬虫抓取的同一套规范 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)给了完整算法。 性能到底怎么影响排名得先说清,页面速度与核心指标的优化优先级 (https://zhangwenbao.com/page-speed-seo.html)免得把力气花错地方。 一百多个字节在一次页面加载里连零头都算不上。上一批算过一个类似的数字:那批无接收端的字段合计8145字节,占响应头总字节的1.74%。拿性能当理由,站不住脚。 还有一个不太被提起的代价是招人与交接。一个新同事接手这套配置,第一件事是读懂它;读到两条互相拆台的声明时,他要么去查规范,要么就照着现状继续加。前者花时间,后者让问题继续长大。 ## 真正的代价是三样别的东西 第一是审计噪声。每次做安全检查,这些矛盾都会以某种形式冒出来,要么被工具报成问题,要么被人看到之后花时间确认,年复一年。 推不动改动往往不是技术问题,甲方拒绝建议八成源于身份冲突 (https://zhangwenbao.com/enterprise-seo-evolutionary-framing-eight-steps-rebuild.html)给了重写汇报的办法。 注意力分配本身就是决策,内容、技术、外链三类分工与团队配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)是同一个协作问题。 第二是误判风险。你以为防嵌套配好了,实际上生效的是另一条;你以为Cookie三十天后过期,实际按另一个值算。这类误判只有在出事那天才会暴露。 第三是它挤占了注意力。一个团队能分给响应头的时间是固定的,用来维护两份互相拆台的声明,就没时间去看跨域隔离、权限策略这些真正还缺的东西——样本里权限策略的覆盖率只有4.2%。 顺带提醒一句:改响应头这件事的回滚成本远比看上去高。它通常写在服务器配置或者边缘规则里,改一次要走完整的发布流程,而且影响面是全站。所以别为了清理整洁性问题单独发一次版,攒到下次动那块配置时一起做。 ## 那到底改不改 我的判断是分三档。丢弃类必须改,因为那是真的没生效;作废类看情况,如果两条声明的意图一致就留着不管,不一致就必须统一;合并类不用管,等下次动那块配置时顺手整理。 判断一样东西该不该留有通用问法,用第一性原理做工具选型 (https://zhangwenbao.com/seo-tools-martech-replacement-trend-2025.html)说的就是删掉会不会出事。 最终由谁说了算有明确逻辑,Google选择规范网址的九条决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)可以照着排查。 唯一需要立刻动手的是那五个把新语法写进老字段的站,以及那三个只报告却收不到报告的站。前者是配置没生效,后者是白占字节。 ## 自查该按什么顺序做? 把这套检查落到自己站上,顺序是固定的,因为前一步能筛掉后面大部分工作。 开发期就该埋好这些点,自建站开发阶段的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)能省掉上线后的返工。 从零起步的话顺序更重要,前十二周从技术地基到内容蓝图 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)是一份排好序的清单。 ## 第一步:把最终响应完整拉一次 注意是最终响应,不是第一次响应。多数站首页会经过一到两次跳转,中间那几跳的响应头跟最终页面的完全不同。用命令行工具跟随跳转,把最后一段单独存下来。 跳转链本身也要单独查,两个方向的301跳转怎么配 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)有完整实战。 跟随跳转这件事各家实现不同,工具报的死链和Googlebot抓的从来不是同一批 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html)就是这么来的。 还有一个坑是只发HEAD请求。有些服务器对HEAD和GET返回的字段不一样,上一批就遇到过用HEAD查出来说没配缓存头、换成GET之后那五个字段全在的情况。一律用GET,把响应体丢掉就行。 ## 第二步:按字段分组,找同名重复 把所有字段名列出来做一次计数,大于一的挑出来。排除掉Set-Cookie、Link这些本来就允许多行的,剩下的就是候选。看它们的取值一不一致,不一致的记下来。 整理文本这件事别靠肉眼,把JSON-LD调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)省下不少比对。 结构层面的一次性体检也有工具,一次扒清内外链结构与扣分项 (https://zhangwenbao.com/link-analyzer-internal-external-audit-guide.html)适合改版后做。 这一步能顺手发现链路结构:同一个字段被写了两次,通常说明请求穿过了两个都会写这个字段的层。知道有几层,后面排查会快很多。 这三对之外还有一对值得顺手看:跨域相关的那两个字段。允许来源写成通配符、同时又允许携带凭据,浏览器会直接拒绝整个跨域请求。样本里2个站是这个组合,属于配置了等于没配置的典型。 ## 第三步:查三对经典冲突 缓存那一对、防嵌套那一对、Cookie到期那一对。这三对覆盖了样本里绝大多数自己写出来的矛盾,检查逻辑也简单,各自只需要比对两个值说的是不是一件事。 统计侧的字段配置同样要对,默认追踪不到的那部分流量怎么补 (https://zhangwenbao.com/geo-ga4.html)需要过滤器加渠道分组。 Cookie这一层还有合规要求,评论区那个Cookie提示怎么汉化并默认勾选 (https://zhangwenbao.com/save-my-name-email-and-website-in-this-browser-for-the-next-time-i-comment.html)是个小而全的例子。 检查时注意规则不一样:缓存和Cookie是最严格者或者新指令胜,防嵌套是新版存在则老版被完全忽略。三对三种规则,别混着记。 ## 第四步:把策略里的关键字逐个查一遍 内容安全策略是最容易堆出矛盾的字段,因为它是一整套语言。重点查三处:有没有strict-dynamic和白名单并存、有没有nonce和unsafe-inline并存、有没有在只报告模式里写那两条会被忽略的指令。 信号之间打架时怎么定夺,六类消歧信号的管控实战 (https://zhangwenbao.com/entity-disambiguation-mechanism-seo-signal-control.html)给了处理顺序。 多份声明怎么合成一个实体,@graph与知识图谱怎么搭 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)是另一套合并规则。 查完之后如果发现有兼容意图的组合,别删,在部署脚本里加一行注释说明这是给老浏览器留的退路。注释是给下一个人看的,而下一个人才是真正的风险来源。 实测的时候记得区分浏览器。不同浏览器对非法取值的处理宽严不一,有的会尽力解析出一个合理值,有的直接丢弃。以最严格的那个为准来定结论,因为你的用户里总会有用那个浏览器的。 ## 第五步:实测那些静态查不出来的 丢弃类只能靠实测。做一个最小的测试页,用iframe嵌一次自己的页面,看能不能嵌进去;打开控制台看有没有关于字段取值非法的警告。整个过程五分钟,但它是唯一能验出整行被丢掉的办法。 浏览器还会悄悄改你的页面,自动翻译把yes改成forks而数据看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是同一种沉默污染。 这类小脚本自己写最快,用Vibe Coding做SEO小工具的八步避坑 (https://zhangwenbao.com/vibe-coding-seo-tool-tutorial.html)讲的就是自养工具。 如果站点有多个模板类型,商品页、列表页、内容页各测一次。响应头经常是按路径规则下发的,首页配对了不代表商品页也对。 做这张表还有个附带好处:它能让你在跟平台方沟通时有据可依。指着表里那一行说这个字段是你们下发的、我们删不掉、它和我们的配置冲突,比泛泛地说安全头有问题有效得多。 ## 第六步:把结果写成一张表,定期重跑 输出建议做成每站一行:字段行数、矛盾类别数、各类明细。存档之后每月重跑一次,只看数字有变化的那几行。响应头是很少变的东西,一旦变了要么是自己改了配置,要么是平台改了模板,两种都值得看一眼。 存档与巡检可以一条龙,备份、sitemap、缓存、证书都自动跑 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)脚本可以直接改。 定期重跑交给定时任务,把巡检、推送和清缓存都自动化 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)是很划算的投入。 ## 量这批数据的时候,哪几个判定差点搞错? 照惯例交代口径,这一节是给想复现的人省时间的。 口径不清的指标最容易误导,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭框架。 判据松紧决定结论性质,量出七成页面有差异、补上对照组后只剩两个点 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)是同一类返工。 这个修正带来的连锁反应不小。69这个数字如果直接写进结论,会让读者以为将近一半的站有严重问题;而实际情况是其中大部分只是写法冗余,行为完全正确。判据的松紧直接决定了结论的性质,不只是决定数字大小。 ## 第一处:把合并当成了矛盾 第一版脚本把所有同名重复字段都算成矛盾,数出来69处。后来意识到多数是Vary的两行,而按规范那是合法的合并写法,行为完全正确。 换个口径看数据结论可能完全不同,三类站点的聚合自然流量实测 (https://zhangwenbao.com/aggregate-organic-traffic-seo-metric-keyword-dead.html)就是一次口径切换。 同一个名字各家算法不同到处都是,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 修正之后的口径是:只统计取值不同的同名字段,并且在结论里明确标注这一类的下场是合并而不是冲突。数字从69降到57,更重要的是性质变了——它不是错误,是不整洁。 这一条在上一批也吃过亏,当时是把抓取失败的响应体也当成了有效样本,分母虚高了四份。两次的教训是同一个:抓取阶段和分析阶段必须分开,中间用一份带状态码的记录连接,让分析脚本自己决定哪些能用。 ## 第二处:分母必须是最终的2xx响应 抓回来的文件里包含跳转链上的每一段响应。如果不加区分地统计,会把跳转响应的字段和最终页面的字段混在一起。跳转响应通常只有几个字段,会把中位数拉低;而且它的缓存策略跟最终页面完全不同。 样本干不干净得先验一遍,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)就是清洗之后的数字。 抽样口径直接决定结论真假,孤岛页面检测的抽样口径怎么定 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)是同一类方法论问题。 所以脚本里第一步就是切出最后一段以HTTP开头的响应块,只有状态码是2开头的才进分母。142这个数字是这么来的,比抓取的站点总数少。 ## 第三处:判断策略指令时要区分两种模式 内容安全策略有正式和只报告两个字段,它们的名字很像,取值语法也一样,但规则不同——有两条指令在只报告模式下被忽略。脚本一开始把两个字段合在一起解析,导致那4个站的问题没被识别出来。 报告里的状态词各有含义,五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你分清是谁的问题。 名字像的两个东西行为未必像,五类页面的meta robots与canonical配置差异 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)可以直接照搬。 分开解析之后才发现只报告模式里的这类空转。这类细节的教训是:名字像的两个字段,行为未必像,写脚本时宁可分开处理。 ## 第四处:一个PHP的低级坑 输出统计的时候,双引号字符串里变量名后面紧跟中文标点,那个标点会被当成变量名的一部分,PHP允许高位字节出现在标识符里。结果是最关键的那个数字变成空白,还附赠一条未定义变量警告。 有报错反而是好事,这个致命错误的五步排查修复 (https://zhangwenbao.com/fatal-errorcall-to-a-member-function-getinnertext-on-a-non-object-in.html)至少有明确的起点。 脚本层面的小疏忽代价可能很大,上传目录还能跑PHP的五种加固写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是另一类低级但致命的问题。 这批犯了两次才反应过来,修法是所有插值一律用花括号包裹。写多语言输出的脚本时值得注意,它不报错,只是让数字消失。 ## 为什么把这些写出来 因为69和57这两个数字放进文章里都很有说服力,读者没有办法判断哪个是对的。把口径、剔除规则、修正过程摊开,是唯一能让人放心引用的做法。 指标定义清楚才谈得上对比,三个平台三百个站的收录速度实测 (https://zhangwenbao.com/seo-kpi-guide.html)是一份口径统一的样本。 样本量大不代表结论可用,三千条数据揭开的认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)说明该信什么不该信什么。 ## 常见问题解答 ## 同一个响应头字段发两次,浏览器听哪一次? 两次都听。HTTP的字段语法规定同名字段多次出现等价于把取值用逗号连起来,所以两行Vary等于一行写了两个值。例外是Set-Cookie,它的取值本身含逗号,规范专门规定每行独立。真正会出事的是不允许列表值的字段发两次且取值不同,比如Content-Length,那属于协议错误。 ## Cache-Control和Expires同时写,以哪个为准? 以Cache-Control的max-age为准,Expires只在没有max-age时才被读。样本里8个站的两者说的不是一个时间,其中一个站的Expires写着1984年、另一个写着1970年,都是老年代表示立即过期的写法。建议只写Cache-Control,多一个字段就多一份需要长期同步的副本。 ## X-Frame-Options和frame-ancestors都写了会怎样? 支持后者的浏览器必须完全忽略前者,不是取交集也不是取更严格的。样本里10个站的两者不一致,包括一个X-Frame-Options写着谁都不许嵌、而策略里允许自家所有子域嵌的组合,那行deny等于没写。正确做法是让两者意图一致,老字段只写deny或sameorigin。 ## 为什么我的X-Frame-Options写了一串网址却不生效? 因为这个字段只认两个取值,写别的属于非法取值,处理方式是整行丢弃。样本里5个站把内容安全策略的语法搬了过来,写成sameorigin后面跟几个具体地址,结果那行一个字都没生效。需要允许特定来源嵌套只能用frame-ancestors。 ## 策略里同时写strict-dynamic和白名单域名有意义吗? 只有兼容意义。支持strict-dynamic的浏览器会忽略同一条指令里所有基于地址的来源,只信任带nonce或哈希的脚本;不支持的浏览器才退回到白名单。样本里3个站这么写,最长的一个列了82个域名。这么做可以,但必须在文档或部署脚本里注明它是兼容退路,否则会有人继续往那份死清单里加东西。 ## 只报告模式的策略要注意什么? 两点。一是frame-ancestors和sandbox在这个模式下被规范忽略,写了也观察不到;二是必须先配好报告端点再写策略,否则既不拦截也收不到报告。样本里4个站踩了第一点,3个站踩了第二点,其中三个站两点都占。 ## 清理这些矛盾能提升性能吗? 几乎不能。响应头字节数中位是3204,矛盾字段合计一百多字节,占比可以忽略。值得清理的理由是另外三个:减少审计噪声、避免你以为生效的那条其实没生效、以及把注意力腾给真正缺失的字段——样本里权限策略的覆盖率只有4.2%。 ## 权威参考资料 ## 分类页越老越荒废?19405个实测,最乱的是三年前建的那批 - URL:https://zhangwenbao.com/collection-age-published-at-audit.html - 分类:技术SEO - 发布:2026-08-20 | 更新:2026-09-08 - 摘要:站上的分类只增不减,没人说得清哪些还有用。57个海外电商站的19405个分类按年份排开之后,该从哪一批开始清理,答案跟直觉不一样。 - 关键词:技术SEO,电商SEO,Shopify > **TLDR**:摘要:把57个英文电商站的19405个分类按建立年份排开,2025年和2026年建的占49.1%,2018年及更早的只剩1042个,最老的一个立于2012年。荒废程度并不随年龄递增:2018年及更早那批里空分类只占7.1%,98.1%规规矩矩写在sitemap里;反而是2022到2024这三年建的5935个,空的占17.8%,进sitemap的只有79.2%,两项都是全样本最差。促销打折类命名的分类空掉的概率是29.7%,接近整体的三倍。 > 摘要:把57个英文电商站的19405个分类按建立年份排开,2025年和2026年建的占49.1%,2018年及更早的只剩1042个,最老的一个立于2012年。荒废程度并不随年龄递增:2018年及更早那批里空分类只占7.1%,98.1%规规矩矩写在sitemap里;反而是2022到2024这三年建的5935个,空的占17.8%,进sitemap的只有79.2%,两项都是全样本最差。促销打折类命名的分类空掉的概率是29.7%,接近整体的三倍。 分类页这东西有个特点:建的时候只要点几下,删的时候却没人敢动。于是它只增不减,一年一年往上堆。堆到最后,没人说得清站上到底有多少个分类、哪些还有用。 上一次数过一遍,这57个站合计开了19405个分类,而出口、sitemap和首页导航这三份清单没有一份对得上 (https://zhangwenbao.com/collection-three-lists-mismatch-audit.html);再往前一次量的是从首页出发两跳能走到多少件商品 (https://zhangwenbao.com/product-two-click-reachability-audit.html)。那两次量的都是空间,这次换一个维度:时间。每个分类都带着自己的建立日期,把它们按年份排开,能看出来的东西比想象中多。 ## 这些货架,都是哪一年搭起来的? 数据仍然来自各站公开的分类清单接口,每个分类自带published_at字段。按Shopify官方的collection对象文档 (https://shopify.dev/docs/api/liquid/objects/collection),它记的是这个集合对外可见的时刻,另有一个products_count记当前视图下的商品数——本文说的“空货架”,就是后者为0。 这个建立日期在10.2小时的复抓里一个都没变,可以当稳定标识用;同一次复抓里另一个字段变了将近四分之一,那个不能用,理由在讲商品年龄那篇里已经拆过 (https://zhangwenbao.com/product-age-created-at-audit.html)。 ## 一半的货架是最近两年才有的 建立年份 | 分类数 | 占比 | 2018年及更早 | 1042 | 5.4% | 2019到2021 | 2895 | 14.9% | 2022到2024 | 5935 | 30.6% | 2025 | 4857 | 25.0% | 2026 | 4676 | 24.1% | 分类年龄的中位数是658天,P75是1498天,P90是2384天,最老的一个已经5049天。也就是说,一半的分类不到两年,但尾巴一路拖到2012年。 ## 谁的货架最老 outdoorvoices有一个分类立于2012年,至今仍在被抓;chubbiesshorts和taylorstitch的最老分类都在2013年;fahertybrand、marinelayer、parachutehome、thirdlove停在2015年。这些站的共同点不是老,是没换过平台——一旦换过平台或者重建过店铺,所有分类的建立日期都会被重置成迁移那天,年龄就此归零。 顺便说,这跟用网页存档倒推域名年龄 (https://zhangwenbao.com/domain-first-archive-vs-registration-audit.html)是同一类手法:系统里那个日期记的是记录的年龄,不是业务的年龄,两者中间隔着一次或几次迁移。 ## 老货架是不是最荒废的那批? 直觉的答案是显然的:建得越早,越可能被忘掉。把五个年份桶跟四项健康指标交叉之后,这个直觉被数据打回来了。 ## 五个年份桶,四项指标 建立年份 | 分类数 | 空的(0件货) | 写了描述 | 在sitemap里 | 首页点得到 | 2018年及更早 | 1042 | 7.1% | 28.2% | 98.1% | 18.5% | 2019到2021 | 2895 | 14.8% | 32.4% | 87.5% | 15.2% | 2022到2024 | 5935 | 17.8% | 28.3% | 79.2% | 11.9% | 2025 | 4857 | 6.2% | 42.8% | 89.5% | 9.2% | 2026 | 4676 | 4.0% | 49.4% | 92.3% | 9.6% | 空分类那一列是个明显的驼峰:从7.1%爬到17.8%,再掉回4.0%。sitemap覆盖率是个明显的谷底:98.1%降到79.2%,再爬回92.3%。两条曲线的极值都落在同一个桶里——2022到2024。 ## 最老那批反而最规矩 2018年及更早的1042个分类里,98.1%在sitemap里,空的只有7.1%,还有18.5%至今挂在首页导航上——这个数字是所有桶里最高的,比2026年新建的那批还高一倍。 原因其实不难理解:能活过八年的分类,多半是这个店的骨架。男装、女装、鞋、配件,这些入口从开店那天挂到今天,没人有理由动它。老不是被遗忘的原因,只是被遗忘的必要条件——真正决定一个货架会不会烂掉的,是它当初为什么被建出来。 这一点跟孤岛页面的检测口径 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)有相通之处:光看某个属性(发布时间、入链数)排出来的名单,往往命中的不是真正的问题页面。得先问清楚这一批东西当初是怎么产生的。 ## 那个驼峰是怎么形成的 2022到2024这三年,恰好是很多DTC品牌上应用、上筛选、上活动页最猛的三年。建一个分类的成本近乎为零,删它却要担心有没有人还在链、有没有排名、后台有没有别的地方引用。于是建了没删的部分沉在那里,一沉三年。 ## 2022到2024那三年,建的到底是什么货架? 要回答这个问题,只能去看它们的名字。分类的handle是人起的,起名的时候就带上了用途。 ## 按命名把它们分类 用一组正则把19405个handle扫一遍,看promo、sale、clearance、black-friday、bundle这类词的出现比例: 建立年份 | 促销打折类 | 赠品捆绑类 | 节日活动类 | 看不出用途 | 2018年及更早 | 4.5% | 5.2% | 3.1% | 82.1% | 2019到2021 | 3.6% | 5.1% | 2.2% | 84.7% | 2022到2024 | 8.9% | 8.6% | 3.2% | 77.0% | 2025 | 7.8% | 5.6% | 3.4% | 80.6% | 2026 | 4.2% | 3.4% | 1.4% | 87.0% | 促销打折类在2022到2024那一桶里占8.9%,是最老那批的两倍。赠品捆绑类同样在这一桶见顶。那三年多出来的分类,主要不是品类,是活动。 ## 带这些名字的分类,更容易空掉 把命名特征跟“有没有货”交叉,差距非常直接: 命名特征 | 数量 | 空掉的比例 | 促销打折类 | 1255 | 29.7% | 新品类 | 120 | 26.7% | 节日活动类 | 512 | 14.3% | 赠品捆绑类 | 1141 | 12.8% | 联名合作类 | 335 | 10.7% | 季节类 | 511 | 8.4% | 全体分类 | 19405 | 10.6% | 促销打折类29.7%,接近全体的三倍。这个结果谈不上意外,但它给了一条能直接执行的判据:要清理分类,从名字里带sale、clearance、promo的那批开始查,命中率是随机抽查的三倍。 新品类那26.7%更值得玩味。一个叫new-arrivals的分类空掉,通常意味着它绑的规则失效了——比如按标签自动收货,而那个标签没人再打了。这种页面往往还挂在导航上,用户点进去看到一片空白,是转化损失,不只是SEO问题。用户在集合页连点五个筛选之后 (https://zhangwenbao.com/shopify-collection-applied-filters-overview-ux.html)那篇讲的是选多了之后的困惑,这里是另一个极端:一个选项都没有,页面还理直气壮地开着。 ## 逐站看,问题集中在少数几家 brooklinen在2022到2024建了539个分类,其中306个是空的,占56.8%;beistravel 433个里空206个,47.6%;snowpeak 45.1%;allbirds 31.1%;gymshark 26.5%。而marinelayer在同一时期建了194个,只空了5个。 同样的年份、同样的平台,结果差二十倍。所以这不是时代的问题,是各家流程的问题。 ## 有一批货架,根本不是给人建的 翻空分类样本的时候,allbirds那一堆handle很扎眼:mens-tree-runners-loop、anytime-ankle-sock-loop、mens-allbirds-108-shoes-loop,成百上千个,全带同一个后缀。 ## 584个,全在一家店里 这个站1346个分类里,有584个以loop或者shop-now结尾,占43.4%。它们的处境高度一致:60.8%是空的,100%写在sitemap里,0%出现在首页导航上。 这批分类是第三方退换货应用建的——用户申请换货时,应用需要一个只包含可换商品的集合,于是给每个商品各建一个。它们从来不打算给人看,但平台的sitemap不区分这个,照单全收。结果是这个站往搜索引擎提交的地址里,有超过四成是给应用内部用的空页面。 ## 这是单站现象,但不是孤例 必须说清楚:584个全部出自一家,不能拿它推广成行业普遍情况。但这个机制是通用的——任何一个会写商品集合的应用,都可能在你的分类表里留下这样一批东西。检查方法很简单:把分类handle按后缀聚类,凡是出现几十上百个同后缀的,去查一下是哪个应用建的。 顺带一提,这类地址在抓取预算上的开销不是零。谷歌的抓取预算文档 (https://developers.google.com/crawling/docs/crawl-budget)把低价值地址列为浪费的头号来源,而这批页面回200、有完整HTML、体积不小,爬虫每来一次都得读一遍——没改过的页面被反复重发 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)那笔账,在这里是加倍的。分面导航产生海量地址 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)那件事至少还是用户点出来的,这一批连点都没人点。 ## 老货架里装的,是老货还是新货? 把两份年龄数据接起来,可以问一个更有意思的问题:一个2018年建的分类,今天里面摆的是什么货。 ## 配对之后的结果 货架建立年份 | 可配对货架数 | 里面商品的货龄中位 | 2018年及更早 | 171 | 386天 | 2019到2021 | 379 | 537天 | 2022到2024 | 594 | 459天 | 2025 | 405 | 390天 | 2026 | 391 | 270天 | 最老那批货架里的货,中位货龄386天,比2019到2021那批(537天)还新。这条数据把前面的解释坐实了:老货架是主力入口,货一直在换;真正在积灰的是2019到2021那批——货架本身没那么老,里面的货却是全样本里最旧的。 ## 怎么用这条判据 如果你想在自己站上找“该收拾的分类”,用建立年份筛出来的名单会很长,也不准。更好的做法是拿两个年龄做差:货架很老但里面的货很新,说明它一直在被维护,别动;货架不算老但里面的货普遍超过一年半,那才是真的没人管了。这个差值跟仓库那边看SKU周转率 (https://zhangwenbao.com/dtc-overseas-warehouse-sku-turnover-inventory-abc-classification.html)是同一个思路,只不过前台看的是曝光有没有在流动,后台看的是货有没有在流动。 ## 描述越写越长,题图越配越少,这是怎么回事? 年份桶还带出来另外两条走向相反的曲线。 ## 两条曲线 写了描述的比例,从2018年及更早的28.2%一路涨到2026年的49.4%;而且写了的那些,长度也在涨——中位从172字符涨到229字符。 配了题图的比例正好反过来:2018年及更早25.1%,2019到2021降到16.0%,2022到2024是13.4%,2025只剩7.1%,2026是6.2%。 ## 两件事的成本不一样 描述是文字,现在有工具可以批量生成;题图是设计资源,建一个分类就得配一张banner,人手跟不上分类增长的速度。2018年一个店总共几十个分类,每个配张图不难;到了2026年一年新建四千多个,配图这件事自然就崩了。 所以这两条曲线讲的是同一件事:分类数量的增长速度,已经超过了维护它们的能力。描述靠工具勉强跟上了,题图没跟上。至于哪个更重要,得看这个分类是不是真的要拿来承接流量——用户点进一个分类页之后,最先要知道的是自己在哪 (https://zhangwenbao.com/category-navigation-scope-custody.html),一张图和两百字的描述,作用完全不同。 ## 最老的那个货架,前台还打得开吗? 清单里写着的东西,得去前台验一遍才作数。这是上一轮实测留下的规矩,代价是当场废掉一条本来会被当成主要结论的判断。 ## 109个分类页,只有一个真的打不开 做法是每个站取最老的一个分类和最新的一个分类,用真实浏览器打开,记状态码、最终地址、robots标记,以及页面上有没有空态文案。57个站里55个两边都取到了。 结果:老分类56个回200、1个回404;新分类53个回200、1个404、3个被平台限流没拿到。那个404出自harrys.com,而且它的最新分类也是404,属于整站路径不同,跟年龄无关。 更关键的一项是最终地址:109个正常打开的页面里,106个停在原来那个地址上,只有3个跳走——oclean的两个跳到了越南站首页,avocadogreenmattress的一个跳到了另一个分类。换句话说,八年前建的分类页,今天绝大多数还老老实实待在原处,既没被删也没被合并。 ## 老分类和新分类,前台待遇几乎一样 指标 | 最老的分类 | 最新的分类 | 正常打开 | 56 / 57 | 53 / 57 | 带noindex标记 | 8 | 9 | 页面上写着空态文案 | 6 | 7 | 接口声明0件货 | 6 | 3 | 四项里有三项几乎持平。这跟前面按年份分桶得到的结论方向一致:最老的那批分类没有被冷落,冷落发生在中间那几年。 ## 一个货架,接口说装了3056件 allbirds那个建于2018年3月的shoes分类,接口声明3056件商品,是全样本里数字最大的一个。用浏览器打开,页面标题写着“Uh-Oh, Nothing To See Here!”。 它在sitemap里,它是这个站最老的分类之一,它的商品数写着四位数,而它渲染出来是一张空页面。这不是删没删干净的问题,是接口那一层和展示那一层各说各话——三份清单对不上 (https://zhangwenbao.com/collection-three-lists-mismatch-audit.html)那篇讲的是清单之间对不上,这个例子更进一步:同一份清单跟它自己的页面都对不上。 ## 这里有一把不能用的尺子 本来还想数一件事:每个分类页正文区里实际显示了多少个商品。数出来有26个页面是“接口说有货、正文区一个商品链接都看不到”,听上去是个很大的发现。 但这把尺子不可靠。商品卡不一定是带/products/的链接,可能是脚本绑的点击事件;容器的class里带menu这类词会被误判成导航;懒加载没触发的时候页面上本来就是空的。这次的判定规则已经按DOM位置把导航和页脚排除掉了,仍然挡不住这三类误伤。所以除了allbirds那两个页面自己写着空态文案的之外,其余的数字只当线索,不当结论。 ## 分类的“最后更新时间”,能不能当荒废的判据? 既然要找没人管的分类,最顺手的想法当然是看它最后一次被改是什么时候。这个想法在商品那边已经彻底破产,在分类这边稍微好一点,但也只是稍微。 ## 复抓的结果 间隔10.2小时的两次采集里,7423个可对齐的分类中,published_at变动0个,updated_at变动1764个,占23.76%,商品数变动159个,占2.14%。 商品那边这个字段的变动率是100.00%,分类这边只有不到四分之一。看上去分类的这个字段还有点信息量。 ## 但它的取值范围骗不了人 把19405个分类的最后更新时间跟采集时刻做差:中位1天,P75是15天,P90是62天,最大值118天。 也就是说,整个样本里没有一个分类的这个字段超过四个月。而同一批数据里,有1042个分类是2018年以前建的。一个建了八年、里面一件货都没有、首页也点不到的分类,它的“最后更新时间”依然显示三个月以内。用它来找荒废的货架,一个都找不出来。 这跟sitemap里那个修改时间记的其实是请求时刻 (https://zhangwenbao.com/sitemap-lastmod-honesty-audit.html)是同一种病的不同表现:字段名承诺的语义,跟它实际记录的动作,中间差了一层。判断有没有人管,只能看内容本身——有没有货、有没有描述、有没有入口。 ## 自己站上怎么查,查完该改哪里? 这套查法不依赖任何工具,一次数据库查询加一个表格就能跑完。 ## 四步 第一步,导出全部分类,带上建立日期、商品数、描述长度、有没有题图。第二步,按年份分桶,找空分类占比最高的那个桶——多数站会落在两到四年前。第三步,把handle里带sale、promo、clearance、bundle、new-arrival的挑出来单独看,这批的空置率通常是平均值的两三倍。第四步,把空分类的地址跟sitemap和首页导航比对,看有多少正在被提交、有多少还挂在菜单上。 第四步最容易出错的地方是拿错清单。sitemap自己也会烂,从站点地图里抽585条地址查出48条是坏的 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)那次,生成程序一次都没报错。所以比对之前先确认这份sitemap是新生成的,不是几个月前的缓存。 ## 查出来之后怎么处置 空分类不能一律删。集合页没有商品时该怎么处理 (https://zhangwenbao.com/seo-empty-shopify-collections.html)取决于它是暂时空还是永久空:季节性分类明年还要用,留着但从sitemap里摘出去、加noindex;活动分类结束了就不会再有货,该301到父分类;应用建的那批既不该进sitemap也不该被抓,最省事的办法是在robots里按后缀拦掉。 谷歌关于筛选类地址的文档 (https://developers.google.com/crawling/docs/faceted-navigation)在这件事上给过一条很具体的要求:筛选组合没有结果的时候应当返回404,而不是回一个空着的200。这条要求写的是筛选,但道理对所有空着的集合页都成立——保哥自己站上做过一轮清理,最费劲的不是判断该不该删,是找出那些指向它的旧链接。 有一个坑要提前说:删分类会连带影响内链。一个分类被删掉之后,指向它的菜单项、面包屑、推荐位不会自动消失,会变成一堆404或者软404。内链结构本来就会自己烂掉 (https://zhangwenbao.com/internal-link-decay-equity-reclaim.html),清理动作做得不干净只会让它烂得更快。 ## 什么时候不用查 分类总数在一百以内、且从来没装过会写集合的应用,那基本不会有这个问题,肉眼过一遍导航就够了。这套检查真正值钱的场景是:分类数超过五百、装过筛选或退换货类应用、并且做过至少一次大促——三个条件里凑齐两个,去查一定有收获。 ## 常见问题解答 ## 分类页建得多到底有没有害处? 多本身不是害处,空才是。一个有货、有描述、有入口的分类页是正经落地页;一个声明0件货还回200的页面,对用户是死胡同,对爬虫是纯开销。这次样本里空分类占10.6%,其中六成还写在sitemap里。 ## 为什么最老的分类反而问题最少? 因为能活过八年的分类多半是店铺骨架,男装女装鞋子配件这类入口一直在用。真正容易烂掉的是为某次活动、某个应用、某个筛选临时建出来的那批,它们的共同点不是老,是建的时候就没打算长期维护。 ## 怎么快速找出没人管的分类? 三个信号叠着看:商品数为0、描述为空、首页导航里点不到。三项全中的基本可以判定失联。别用最后更新时间,这个样本里所有分类的这个字段都在四个月以内,包括那些建了八年一件货都没有的。“首页点不点得到”这一项要用渲染后的页面去数,只读静态HTML会漏掉大半个导航 (https://zhangwenbao.com/collection-three-lists-mismatch-audit.html)。 ## 空的分类页该返回404还是200? 看它是暂时空还是永久空。永久不会再有货的,返回404或者410最干净,301、410和软404怎么选 (https://zhangwenbao.com/magento-2-out-of-stock-discontinued-product-seo-301-410-soft-404.html)商品那边有一套现成的决策,分类可以照搬。季节性的暂时空,保留200但加noindex、从sitemap里摘掉,等有货了再放回来。最糟糕的做法是回200、进sitemap、还挂在导航上,用户和爬虫都要白跑一趟。 ## 第三方应用建的分类能不能直接删? 删之前先确认应用还在不在用。退换货、订阅、个性化推荐这类应用可能把这些集合当成运行时数据,删了会影响功能。更稳妥的做法是不删,但把它们从sitemap里排除、用robots按handle前缀或后缀拦住抓取。写robots规则的时候留意分组之间并不继承 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)这件事,给某个爬虫单独开一组,全局那组对它就整个失效了。 ## 分类的建立日期在别的平台上叫什么? WooCommerce的商品分类是taxonomy term,本身不带建立时间,得从term_meta或者第一次关联商品的时间反推;Magento的分类实体带created_at;自建站看自己的表。拿不到确切日期也不要紧,用“第一个商品被归进来的时间”当代理指标,结论方向是一样的。 ## 这次的结论会不会只适用于Shopify? 年份分布和空置率的具体数字肯定是平台相关的。但机制不挑平台:建分类的成本远低于删分类的成本,活动类分类的生命周期远短于品类分类,应用会在后台留下用户看不见的集合——这三条在任何电商系统上都成立。 ## 权威参考资料 ## 商品上架时间实测:43912件里老货没掉队,漏的是新货 - URL:https://zhangwenbao.com/product-age-created-at-audit.html - 分类:技术SEO - 发布:2026-08-19 | 更新:2026-09-08 - 摘要:想知道店里的商品放了多久,后台那个最后更新时间基本没用。60个海外电商站的实测告诉你该看哪个字段,以及漏掉的到底是老货还是新货。 - 关键词:技术SEO,电商SEO,Shopify > **TLDR**:摘要:从60个英文电商站取回43912件在售商品的全部时间字段,三年以上的有5361件,占12.2%;五年以上2331件,占5.3%;最老的一件已经挂在货架上4704天。原本以为老货会被系统性遗忘,逐站配对之后并没有——33个站里只有1个站的老货进sitemap的比例明显低于新货,13个站反而比新货更高。56个站各自最老的那件商品,前台逐个打开全部回200,一个404都没有。 > 摘要:从60个英文电商站取回43912件在售商品的全部时间字段,三年以上的有5361件,占12.2%;五年以上2331件,占5.3%;最老的一件已经挂在货架上4704天。原本以为老货会被系统性遗忘,逐站配对之后并没有——33个站里只有1个站的老货进sitemap的比例明显低于新货,13个站反而比新货更高。56个站各自最老的那件商品,前台逐个打开全部回200,一个404都没有。 先问一个很少有人认真回答的问题:你店里现在卖得最久的那件商品,是哪一年上架的? 大部分人的第一反应是去后台翻。翻到的通常是一个叫“最后更新”的时间,显示今天或者昨天。于是结论就成了:我的商品都很新,都在维护。 这个结论几乎一定是错的。不是因为你记错了,而是因为那个字段根本不记录你想知道的事。 ## 想知道一件货在店里放了多久,该看哪个字段? Shopify的商品对象上挂着三个时间戳,名字长得都差不多,含义差很远。 ## 三个日期,名字都很像 按Shopify官方的product对象文档 (https://shopify.dev/docs/api/liquid/objects/product),created_at是这条商品记录被建出来的时刻,published_at是它对外可见的时刻,updated_at是它最后一次被写入的时刻。前两个由人的动作决定,第三个由系统的动作决定——而系统的动作,比人频繁得多。 这次的分母来自各站自己的商品清单出口,就是那个不用登录就能读的/products.json。这个出口保哥单独写过一篇 (https://zhangwenbao.com/shopify-products-json-open-data-endpoint-audit.html),那篇讲的是它泄露了什么,这次只把它当尺子用,读三个日期。60个站里有4个拿不到有效清单(域名解析不了或者清单为空),剩下56个站合计43912件商品,每一件都同时带着这三个字段,没有一件缺。 ## 先看看它们各自的年份分布 把43912件商品按这三个字段各自的年份摊开,画面立刻分成两个世界。 年份 | 按created_at | 按published_at | 按updated_at | 2026 | 15869(36.1%) | 23613(53.8%) | 43912(100%) | 2025 | 16169(36.8%) | 12532(28.5%) | 0 | 2024 | 5929(13.5%) | 3672(8.4%) | 0 | 2023 | 1789(4.1%) | 1066(2.4%) | 0 | 2022及更早 | 4156(9.5%) | 3029(6.9%) | 0 | 第三列没有分布可言,它是一根竖线。43912件商品的updated_at全部落在采集时刻往前24小时以内,一件例外都没有。中位数是1天,最大值也是1天。 换句话说,如果你拿这个字段去回答“这件货多久没人碰过”,那么无论走进哪一家店,答案都是“昨天刚碰过”。这个字段在这个问题上,信息量精确地等于零。 ## 隔十小时再抓一次,哪个字段会变? 上面那句话还只是一次快照的推断。快照能得出的最强结论也只是“看起来都很新”,得再做一次才能把话说死。 ## 对照是怎么设计的 第二天早上,用完全相同的方式把同一批站再抓一遍,间隔中位10.2小时。然后按商品id逐件对齐,看三个字段各变了多少件。这一步的关键不在于观察updated_at变没变,而在于同一次测量里还有两个字段可以当基线——如果三个都变了,那说明是我的采集不稳;如果只有一个变,那就是字段本身的行为。补一组对照再下结论 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)这件事,吃过一次亏就再也不会省了。 ## 一个字段一件没动,另一个字段一件不剩 49个站顺利对齐,共9426件商品可逐件比对。结果干净得不像实测数据。 字段 | 10.2小时内变动 | 占比 | created_at | 0件 | 0.00% | published_at | 105件 | 1.11% | updated_at | 9426件 | 100.00% | 49个站,每一个站都是100%。不是“大部分站”,不是“绝大多数商品”,是每个站的每一件。同一时刻、同一段网络、同一个脚本,created_at一件都没动。 那105件变了published_at的商品也值得看一眼:其中104件出自同一个站,剩下1件出自另一个站。也就是说,这个字段在47个站里纹丝不动,只有一个站在半夜做过一次批量重新上架。它不是不会变,是变的时候真的对应了一件事。 ## 分类那边的数字不一样,这一点很关键 同一次复抓里还比了7423个分类。分类的published_at变动0个,updated_at变动1764个,占23.76%,商品数变动159个,占2.14%。 这个对比很说明问题。如果updated_at的刷新是平台的定时任务,那分类那边也该是100%。它不是,只有不到四分之一。所以商品那边的100%不是平台在空转,而是每一件商品每天都真的被写了一次——库存、价格、变体、第三方应用同步,任何一样都够。sitemap里那个修改时间记的是请求时刻 (https://zhangwenbao.com/sitemap-lastmod-honesty-audit.html),那是生成环节的问题;这里是数据层面的问题,两者机制不同,后果一样:你拿到的时间戳跟内容改没改无关。 顺带说一句,这也解释了为什么很多站的sitemap看起来天天全量更新。平台的lastmod就是从这个字段来的,而这个字段每天都在动。谷歌的sitemap构建文档 (https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap)要求这一列填的是内容最后一次实质性变更的时间,填得不诚实会被直接忽略。手工改修改日期骗不骗得到搜索引擎 (https://zhangwenbao.com/modified-timestamp-truthful-update-fake-refresh-signal-mechanism.html)是另一个话题,那个是人主动做的;这个是平台默认行为,店主多半不知道自己每天在向爬虫宣布“我全站都变了”。 ## 这四万多件货,到底有多老? 把updated_at扔掉,用created_at重新量一遍,站点的年龄结构立刻显形。 ## 整体分布:一半不到一年,一成二超过三年 货龄 | 件数 | 占比 | 不到1年 | 22953 | 52.3% | 1到2年 | 12118 | 27.6% | 2到3年 | 3480 | 7.9% | 3到5年 | 3030 | 6.9% | 5年以上 | 2331 | 5.3% | 中位数342天,四分位是189天和649天,P90是1278天。最老的一件建于2013年,到采集那天已经4704天,将近13年。 这个分布本身没什么惊人的——电商本来就是新品驱动。真正有意思的是它跟“最后更新时间”给出的画面完全对不上:一个说全站昨天刚碰过,另一个说有5361件货已经在架子上待了三年以上。 提醒一句,这里说的是商品的年龄,跟域名年龄是不是排名因素 (https://zhangwenbao.com/domain-age-ranking-factor-myth.html)不是一回事,跟用网页存档倒推域名什么时候真正开始有内容 (https://zhangwenbao.com/domain-first-archive-vs-registration-audit.html)也不是一回事。那两件事量的是站,这里量的是站上的东西。 ## 逐站差得很远,而且跟品类有关 把货龄中位数按站排开,跨度大得离谱。 站点 | 商品数 | 货龄中位 | 三年以上占比 | taylorstitch.com | 3000 | 1510天 | 65.7% | wusthof.com | 444 | 1413天 | 82.2% | snowpeak.com | 852 | 1175天 | 50.4% | decathlon.com | 518 | 700天 | 35.3% | allbirds.com | 294 | 643天 | 22.8% | beistravel.com | 460 | 161天 | 7.2% | dollarshaveclub.com | 128 | 140天 | 24.2% | 刀具站82.2%的商品超过三年,行李箱站只有7.2%,这不是运营水平的差别,是品类的物理属性。一把厨刀的产品周期以十年计,一只箱子的配色一年一换。所以“商品平均多老”这个指标不能横着比,只能跟自己的去年比。 ## 最老的那批,长什么样 五年以上的2331件里,随便抽几件看:allbirds那双womens-wool-runners-natural-white建于2018年11月,2857天;untuckit有一件4107天;thirdlove 4001天;brooklinen 4025天。都是主力款的基础色,不是清仓尾货。 这一点很重要,它直接影响后面所有结论的解释方向。这些老货不是忘了删的垃圾,是店里最经典的那几件。僵尸SKU (https://zhangwenbao.com/zombie-sku-revival-performance-max.html)那套救活逻辑对它们并不适用——它们不是没人买,是卖了七八年。 ## 从建档到上架,中间隔了多久? 既然created_at和published_at是两个字段,那它们的差值本身就是一条信息:一件货从录进系统到对外可见,中间等了多久。 ## 中位44天,尾巴长得吓人 43912件里,两个日期不在同一天的有37874件,占86.2%。差值中位44天,P75是170天,P90是429天,最大4074天——有一件货在库里躺了11年才上架。 44天这个中位数很符合直觉:拍照、写文案、定价、等库存到仓,一个多月不算慢。真正值得注意的是P90那个429天,意味着每十件里就有一件在系统里等了一年多。如果你在做上新节奏的复盘,这个差值比任何后台报表都诚实。 ## 那109件负数是怎么回事 有109件商品的published_at早于created_at,最极端的一件早了1499天。按字面理解,这件货在被创建之前四年就已经上架了。 当然不是时间旅行。这109件分布在12个站,其中一个站独占69件。这是数据迁移的指纹:换平台、换主题、批量重建商品记录的时候,新记录拿到了新的created_at,但published_at从旧系统原样带了过来。占比只有0.2%,成不了普遍结论,但它是个很好的排查线索——如果你的站上突然冒出一批负数,多半是有人动过底层数据。 ## 老货是不是更容易掉出sitemap? 到这里,实测该回答那个真正的问题了:待得久,会不会就被系统忘掉。 ## 先看总量,看不出规律 把所有商品按货龄分桶,逐桶算在sitemap里的比例:不到1年85.4%,1到2年84.3%,2到3年92.2%,3到5年90.4%,5年以上82.3%。 五个数字上上下下,没有单调趋势。这种时候最容易发生的事,是从里面挑一个符合预期的数字讲故事。但这个百分比是被大站主导的——taylorstitch一家就贡献了3000件商品,它的口径歪一点,整个桶就跟着歪。 ## 换成同站配对,结论反过来了 正确的做法是把每个站当成自己的对照组:在同一个站里,比较三年以上的老货和两年以内的新货,各自进sitemap的比例。两组都至少有20件的站才进统计,一共33个。 配对结果 | 站数 | 老货明显更差(低于新货1个百分点以上) | 1 | 基本一样(相差1个百分点以内) | 19 | 老货反而更好(高于新货1个百分点以上) | 13 | 差值的中位数是0.0个百分点。19个站里老货和新货的收录比例分毫不差,多数是双双100%。 而13个老货更好的站里,差距大得很难忽略:dreametech的老货88.5%在sitemap里,新货只有36.4%;dollarshaveclub老货100%、新货66.3%;magicspoon老货64.6%、新货40.2%。这几个站真正漏掉的,是最近两年上架的那批。 原因不难猜。sitemap是按某种规则批量生成的,老货早就在里面了,新货要等下一次生成、等某个开关、等某个应用同步。这跟电商sitemap的进出场机制 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)是同一回事——进场那一步,多数站根本没有验收。全站逐条查一遍代价太大,按页面模板抽样 (https://zhangwenbao.com/ecommerce-seo-audit-template-level-sampling.html)是更现实的做法,但抽样的前提是先知道该按什么维度分层,而“上架年份”正好是一个现成的分层轴。 ## 唯一那个反例,值得单说 33个站里只有taylorstitch符合“老货更容易被漏掉”的直觉:老货68.3%在sitemap里,新货97.0%,差28.7个百分点。这个站的货龄中位1510天,三年以上占65.7%,是全样本里最老的一家。也就是说,只有当老货多到成为主体的时候,漏掉老货才会成为一个规模问题。 ## 从首页点两下,还找得到老货吗? 收录是爬虫那一侧的事,用户这一侧还有另一道关:从首页出发,经过首页上点得到的分类,两跳之内能不能走到这件货。这个口径上一篇已经完整跑过一遍 (https://zhangwenbao.com/product-two-click-reachability-audit.html),这次直接把货龄这一维叠上去。 ## 这一层,老货确实吃亏 同样做同站配对,28个站够条件:老货明显更差的10个站,基本一样的10个站,老货反而更好的8个站,差值中位仍然是0.0个百分点。 但更差的那10个站,差得非常明显:ice-watch老货可达率46.2%、新货95.9%,差49.8个百分点;tentree差43.5个;marinelayer差38.4个;decathlon差21.1个。 ## 三分之一,不是全部 10比10比8这个分布,比“老货会被埋起来”这句话精确得多。真实情况是:三分之一的站会把老货从导航里挤出去,三分之一无差别,还有三分之一的老货反而站得更稳——因为老货往往是主力品类,主力品类的分类入口一直挂在首页上。 这里还要提一句货架本身。这些站一共开了19405个分类,首页真正点得到的只有一成七 (https://zhangwenbao.com/collection-three-lists-mismatch-audit.html),其中一成的分类里一件货都没有。所以老货走不到,有时候不是它被挤下去了,而是装它的那个货架从来就没挂上去过。 会挤的那批站有个共同点:分类切得很细、上新很勤,新品会自动进“新品”“本周上新”这类入口,老货则要靠人手动维护分类归属。站点架构那笔账 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)在这里体现得最直接——架构不是搭一次就完事,它每上一次新就退化一点,跟内链结构会自己烂掉 (https://zhangwenbao.com/internal-link-decay-equity-reclaim.html)是同一个道理。 ## 最老的那件货,现在还卖得动吗? 清单里写着,不等于前台还在。这一步不能省——上一次做分类清单比对的时候,正是这道闸当场废掉了一条本来会被当成主要结论的判断。 ## 56个站的最老商品,全部回200 做法是每个站取最老的一件和最新的一件,用真实浏览器打开,看状态码、看有没有加购按钮、看结构化数据里的库存状态。为什么用浏览器而不是脚本,后面那一节会讲。 结果是56个站的最老商品,56个200,一个404都没有。里面46件有加购按钮,按谷歌的商品结构化数据规范 (https://developers.google.com/search/docs/appearance/structured-data/product)标着有货的41件。这批平均已经上架三到十年的商品,前台状态跟新品没有实质差别。 ## 缺货比例:配对之后差别很小 53个站两件都正常打开,把“页面上出现缺货字样或者结构化数据标着无货”当成缺货,做同站配对: 老货缺货 | 新货缺货 | 站数 | 是 | 否 | 7 | 否 | 是 | 5 | 都缺货 | — | 8 | 都有货 | — | 33 | 7比5,基本对称。“老货多半已经断货,留着占位置”这个说法,在这个样本上不成立。页面正文长度也是同样的结论:老货中位4220字符,新货3944字符,老货甚至还长一点。 ## 那3个404,核对完只剩1个 唯一出现404的是新货那一组,3件。这个数字看着很有故事性——最新上架的商品前台打不开,结论都能顺手写好了。但逐个核对之后,故事塌了三分之二。 ugreen那件的域名会按访问来源做地区路由,上一批已经因为同样的原因把整站扣掉;functionofbeauty连老货那一页的h1都渲染成了购物车,说明它的商品页在无头浏览器里根本没正常出来,整站数据都不能用。真正干净的只有peakdesign一件:出口里明明白白写着这个handle,前台回404,而且是自定义的404页。 所以最后能说的只有一句:每站抽一件的量级下,新货出现前台失效的情况有,老货一件都没有。想把它变成一个可外推的比例,还得再抓一轮。 ## 这次的尺子坏在哪三处? 这一节是整轮实测里最贵的部分。三处读数出过问题,其中两处是靠浏览器才看出来的,脚本层面完全无感。 ## 接口给的顺序,一半的站跟页面上不一样 本来还想量一件事:老货在分类页里排第几位。分类的商品清单接口是带顺序的,直接数位次就行——这个想法在脚本层面无懈可击。 于是挑了12个站,用浏览器打开对应的分类页,只数正文区里可见的商品链接,按DOM顺序去重,跟接口返回的前12个对照。结果:5个站前12位完全对上,5个站一个都对不上,1个站的/collections/all在前台压根是个系列列表页,正文区一个商品链接都没有,还有1个站的前台显示“这里什么都没有”,而接口说这个分类里有294件商品。 接口的顺序是集合的存储序,前台的顺序是主题模板套上默认排序规则之后的展示序,两者只在没人改过排序的站上重合。所以位次这条腿直接砍掉了——留着就是一条有一半概率是错的结论。商品列表页那97条准则 (https://zhangwenbao.com/product-list-guidelines-scoring-selection-bias.html)里有相当一部分也栽在这个坑上:准则本身没问题,量它的尺子在页面上取不到值。同一个毛病用错请求方法查响应头 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)时也会犯——工具没坏,问的方式不对。 ## 脚本被限流的那半小时,浏览器一路畅通 复抓跑到第36个站的时候开始连续返回429,而且是跨域名的——36个不同品牌、不同域名的站同时开始拒绝,说明限流不在各家自己的服务器上,在平台的边缘层。响应里没有Retry-After,恢复用了大约35分钟。 关键在于同一时刻发生的另一件事:浏览器那一路的56个站、112个页面,一个429都没有,全部200。同一台机器、同一个出口地址、同一分钟。 公平起见补一句:后来又跑了一轮浏览器采集,114个页面里出现了3次429。所以浏览器通道并非完全免疫,只是阈值明显高得多——脚本那边是连续25个站全军覆没,浏览器这边是零星3个。 换句话说,被限的不是这个IP,是这个客户端。你用脚本去量一个站,量到的可能是这个站给脚本准备的那一份待遇。这跟决定收录哪一版页面的其实是十分钟前路过的那个用户 (https://zhangwenbao.com/vary-header-cache-fragmentation-googlebot-version-seo.html)是同一类问题的两个面:一个是内容因人而异,一个是通道因人而异。做审计的时候,两个通道都得留一条。 ## 还有一件事:我的采集被当成了亚太访客 112次浏览器访问里,25次最终落到了不同的地址上——aloyoga和glossier跳进了/en-sg/,dollarshaveclub跳到了us.子域,casper和getquip收敛到了带变体参数的地址。前两类是按访问来源做的地区路由,这意味着这次看到的商品页并不都是这些站的主版本。 这不影响“老货还在不在”这个判断——404就是404,跟地区无关。但如果要做内容层面的对比,就必须先把地区这一维锁死,否则量的是两个站。 ## 这套查法搬到自己站上,该怎么做? 不必等到有人来做审计,自己站上跑一遍,半小时就够。 ## 三步,做完之前先别删东西 第一步,导出全部在售商品的建档时间,按年份分桶,看看三年以上的占多少。这一步只需要一次数据库查询或者一次接口翻页。第二步,把这批老货的地址跟当前sitemap比对,看有多少不在里面——反过来也要比,看sitemap里有多少地址在商品表里已经不存在。第三步,抽10到20件老货,用浏览器逐个打开,确认它们不是软404、不是跳转到了首页。 顺序重要在于:很多人拿到第一步的分桶结果就开始动手清理三年以上的那批,而保哥这次的实测说明,那批多半是最不该动的。等第二步和第三步跑完,名单会完全换一批人。 ## 判据:三个都是同一个问题的不同问法 这三步问的其实是同一件事:这件东西还在不在你的管理范围里。在库里能查到、在sitemap里写着、在前台打得开,三者缺一样都算失联。 需要注意的是,这三个判据不能只查老货。这次实测最反直觉的一点就是,漏掉的更可能是新货——新货还没来得及被任何一套自动流程收进去。所以每次上新之后,最该做的一次检查是“这批刚上的货进sitemap了吗”,而不是“老货该不该清理了”。 ## 什么情况下不用管 如果你的商品总数在三位数以内、上新频率低于每月一次,那么这套检查的价值有限,肉眼过一遍分类页就够了。它真正值钱的场景是SKU上千、有第三方应用在写商品数据、并且换过一次主题或者平台——这三个条件凑齐两个,出问题的概率就相当高。 还有一种情况值得单独提:如果你正在做内容审计的留改并删决策 (https://zhangwenbao.com/content-audit-pruning-decision-system.html),别把商品页和内容页套同一套标准。文章会衰减,老内容的流量确实会悄悄掉 (https://zhangwenbao.com/content-decay-mechanism-portfolio-roi-tiering.html),但一把卖了八年的厨刀不会因为上架久了就变差。判断商品该不该下架的依据是销量、库存和毛利,不是年龄。 ## 常见问题解答 ## 商品的最后更新时间为什么完全不能用? 因为它记录的是这条记录最后一次被写入的时刻,而不是内容最后一次被人修改的时刻。库存扣减、价格同步、第三方应用回写、批量任务扫过,任何一样都会刷新它。实测里43912件商品的这个字段全部落在24小时以内,49个站复抓的变动率是100.00%——一个每天都返回“刚刚”的字段,用来判断新旧没有任何意义。 ## 那要判断一个页面有没有真的改过,该看什么? 看内容本身。取两次快照做正文差分,比看任何时间戳都可靠。如果只能用时间戳,优先用建档时间加上一份自己维护的变更记录——变更记录是你自己写的,它才对应真实的动作。sitemap里那个修改时间 (https://zhangwenbao.com/sitemap-lastmod-honesty-audit.html)同样不能直接信,很多站的那一列就是生成文件的当下时刻。至于内容该不该更新,那是新鲜度与QDF机制 (https://zhangwenbao.com/content-freshness-qdf-algorithm-mechanism.html)要回答的问题,跟“它上次到底变没变”是两个层面。 ## 老商品到底该不该下架? 先分清是“不卖了”还是“卖得久”。真正停售的商品,处置方式取决于有没有替代品和有没有外链,301、410和软404怎么选 (https://zhangwenbao.com/magento-2-out-of-stock-discontinued-product-seo-301-410-soft-404.html)是另一套决策。而卖得久的商品不需要处置,这次实测里56个站最老的那件商品全部正常在售,其中相当一部分是主力款。 ## 新品迟迟不被收录,最该先查哪一步? 先查它在不在sitemap里。这次配对实测发现,13个站的新货进sitemap的比例低于老货,最极端的一个站新货只有36.4%在里面。多数人会先去改标题、补结构化数据,但如果地址根本没进清单、站内又没有链接指过去,改什么都白搭——这跟孤岛页面检测 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)要解决的是同一类问题。 ## 建档时间和上架时间差很多,说明有问题吗? 不一定。整体中位是44天,一个多月完成拍照、文案、定价、备货是正常节奏。需要警惕的是两头:差值超过一年的那10%,多半是排期一直往后拖或者干脆忘了;差值是负数的,说明这批记录被迁移或者重建过,底层数据动过手脚。 ## 我的站不是Shopify,这套方法还能用吗? 能,字段名要换。WooCommerce看post_date和post_modified,Magento看created_at和updated_at,自建站看你自己的表。判据不变:任何一个会被库存同步刷新的字段,都不能拿来判断新旧。 ## 为什么强调要用浏览器核对,脚本不够吗? 这次三处读数出问题,两处是浏览器发现的:分类页的商品顺序跟接口对不上,以及脚本被平台限流的同时浏览器畅通无阻。脚本快、便宜、能跑全量,但它看到的是接口愿意给它的那一份。全量用脚本、抽样用浏览器,是目前最省力的组合。 ## 这些数字多久会过时? 货龄分布本身是持续变化的,半年后重跑必然不同。但两条结论稳定性很高:一是更新时间字段被系统刷新这件事属于平台机制,不会因为站点不同而不同;二是“老货被遗忘”这个直觉在同站配对下站不住,因为它的成因是运营流程,而不是时间流逝本身。真要复现,重点复现方法,不是数字。 ## 权威参考资料 ## sitemap lastmod记的是哪一刻?41万条实测 - URL:https://zhangwenbao.com/sitemap-lastmod-honesty-audit.html - 分类:技术SEO - 发布:2026-08-19 | 更新:2026-08-22 - 摘要:这个字段本该跟着页面内容走,实际接在了生成程序上——它记的是你什么时候来问,不是页面什么时候改。 - 关键词:技术SEO,抓取预算,Sitemap,lastmod > **TLDR**:摘要:41万条地址的sitemap里,58.7%写了修改时间。把这批文件按2小时22分、7分钟、4秒三种间隔各重抓一遍,测出来的前移量分别是2小时18分、474秒和4秒——每次都正好等于间隔本身。同一批被声称刚刚改过的页面逐字比对,标题99.0%一字未动、H1零变化。另一头还有6个站的时间戳停在2到4年前。文中给出全量覆盖率、精度、年龄七档分布、索引层对账结果,一次把尺子量歪的完整复盘,以及一分钟就能在自己站上跑完的验证办法。 > 摘要:41万条地址的sitemap里,58.7%写了修改时间。把这批文件按2小时22分、7分钟、4秒三种间隔各重抓一遍,测出来的前移量分别是2小时18分、474秒和4秒——每次都正好等于间隔本身。同一批被声称刚刚改过的页面逐字比对,标题99.0%一字未动、H1零变化。另一头还有6个站的时间戳停在2到4年前。文中给出全量覆盖率、精度、年龄七档分布、索引层对账结果,一次把尺子量歪的完整复盘,以及一分钟就能在自己站上跑完的验证办法。 八月十九日有一条不大不小的消息:有人在后台看到排名波动,比官方宣布更新早了三到五天,于是问Google为什么不早点说。官方给出的答复 (https://www.searchenginejournal.com/google-answers-why-search-updates-arent-announced-right-away/586370/)是他们并没有提前推,只是尽量让公告贴近真正按下按钮的那一刻,时区有时候会让这件事变得麻烦。 这个答复里藏着一个更普遍的问题:一件事情发生的时刻,和这件事被写下来的时刻,中间隔着一道工序。那道工序由谁触发、什么时候触发,决定了写下来的那个时间到底可不可信。 网站上最典型的一个这种时间,就是sitemap里的修改时间。协议原文对这个字段的定义 (https://www.sitemaps.org/protocol.html)清清楚楚:这个地址对应的页面最后一次被修改的时间。它是个自我申报的字段,没有任何人来核验。 保哥把143个站声明出来的sitemap两层全拉了下来,435份文件、41万条地址,然后做了一件很朴素的事——隔一段时间原样再抓一遍,看这个数字会不会自己动。 ## 把同一份地址清单隔两小时再抓一次,会发生什么? 这个实验的设计只有一句话:同一个地址、同一个请求身份、同一份文件,隔一段时间再取一次,把每条地址的修改时间前后对照。 百万级商品的站还要多考虑分片,分片、进出场与这个字段的诚实度 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)是同一套工程。 时间戳在几种格式之间来回换很容易出错,从这个字段到结构化数据的日期换算 (https://zhangwenbao.com/timestamp-converter-unix-epoch-sitemap-lastmod-guide.html)有一份对照。 这份文件的写法讲究不少,2400个站踩出来的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)基本都在那份清单里。 如果这个字段真的记录内容变更,那么两次之间只有极少数地址会变——一个卖鞋的品牌站不可能在两小时里改掉几万个页面。 ## 样本是怎么攒出来的 起点是157份能正常读取的robots.txt,其中143个站在里面声明了sitemap地址。顺着这些声明往下抓,第一层拿到157份可用文件,其中116份是索引文件、36份是直接的地址清单。索引文件里又声明了8573个子文件,按站抽取之后抓回第二层。 同一批文件上做过另一项实测,两条规则同时命中一个地址时谁说了算 (https://zhangwenbao.com/robots-txt-rule-conflict-longest-match-audit.html)算出来是最长的那条。 两层结构的解析有现成办法,六种格式的解析与地址批量提取 (https://zhangwenbao.com/sitemap-extractor-url-extraction-format-analysis-guide.html)可以省掉自己写解析器。 起点那份文件本身就很容易写废,整站从谷歌搜索结果里消失的那类事故 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)多半是从一行规则开始的。 两层合并、去掉抓失败和返回HTML伪装页的,最终得到435份可解析文件:313份是地址清单,122份是索引。地址一共410101条,覆盖116个站。 第一次抓取集中在晚上21点21分到21点33分之间。第二次原样重抓,集中在23点43分到23点55分。两次的中位间隔是2小时22分。 ## 这次没算进去的几件事 有三类东西被排除在外,先交代清楚免得误读。 逐条查一百天不如按模板抽样半天,电商审计改成按页面模板抽样的做法 (https://zhangwenbao.com/ecommerce-seo-audit-template-level-sampling.html)更适合大站。 用别人的工具之前更该先校准口径,第三方数据到底准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 抽样口径直接决定结论真假,孤岛页面检测的抽样口径怎么定 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)是同一类方法论问题。 一是抓不到的站。20个站一份文件都没取回来,24次请求直接返回拒绝。这批站不在任何一个比例的分母里,所以文中所有百分比说的都是能读到的那部分。 二是图片和文档专用的清单。有些站给图片单独做了一份,那里面的时间语义跟页面不是一回事,统一剔掉了。 三是同一个地址在多份文件里重复出现的情况。这种重复本身也是个问题,但它属于另一个话题,这次只按文件为单位分别统计,不做跨文件去重。 ## 376736条地址,16.9%的修改时间变了 能够两次都取到、且地址完全相同的条目一共376736条。其中63519条的修改时间发生了变化,占16.86%。 这份文件的作用常被夸大,提交网站地图到底能不能提升排名 (https://zhangwenbao.com/does-sitemap-improve-google-ranking-myth.html)那篇把边界划得比较清楚。 单站也做过同类抽查,585条网址里48条是坏的 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)而生成程序一次都没报错。 这个比例本身就不太对劲。两个多小时里,六万多个页面被改动过,这在任何一家电商公司都不是常态。但比比例更说明问题的是变化的方向和幅度。 ## 中位前移2小时18分19秒,和间隔几乎一样 把每一条变化算成前后差值,结果是这样的:93.2%的变化是往前挪了不到2.5小时,5.6%挪了2.5小时到1天,1.0%挪了超过1天,还有135条是往回退的。 把日期改一改能不能骗过去,真更新与假刷新的副作用实测 (https://zhangwenbao.com/modified-timestamp-truthful-update-fake-refresh-signal-mechanism.html)给了直接的答案。 新鲜度这件事本身是有机制的,哪些页面该更新、更新了会怎么被处理 (https://zhangwenbao.com/content-freshness-qdf-algorithm-mechanism.html)值得先弄明白再动手。 所有变化的中位前移量是2小时18分19秒,四分位区间只有2小时18分04秒到2小时18分25秒。而两次抓取的间隔是2小时22分。也就是说,这个字段没有停在原地,它跟着我的请求一起往前走了。 再换一个角度看同一件事:63519条变化里有58917条,也就是92.8%,新值落在第二次抓取时刻的前后1.5小时以内。它不是散落在过去的某个时间点上,它就贴在你请求的那一刻旁边。 ## 站级分布:46个站一动不动,18个站整份全变 把它拆到站级会更清楚。115个有可比数据的站里,46个站的修改时间一条都没变,7个站变动不到5%,44个站在中间,18个站的变动比例在95%以上。 中间还夹着一层缓存,六层缓存与边缘路由对SEO的影响 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)会改变你看到的东西。 地址规模失控会连带一堆问题,大量无用页面拖垮流量的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 这个信号最终服务的目标是抓取预算,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)按优先级排过一次序。 最后那18个站的数字非常整齐:anker.com的4214条全变,eufy.com的11690条全变,soundcore.com的1975条全变,dji.com的354条全变,italic.com的96条全变。gymshark.com、tentree.com、aloyoga.com、everlane.com、marinelayer.com、fahertybrand.com、taylorstitch.com都是差一条全中。 这不是内容更新的分布形状。内容更新永远是长尾的——少数页面动、多数页面不动。整份文件同时全变只有一种解释:这个数字是在文件被生成的那一刻现算出来的。 ## 另外那46个站呢 它们一条都没动。这看上去像是好消息,但先别急着下结论——后面会看到,它们里面有一批的问题比前面那18个还严重,只是方向相反。 这几年该查的层次比过去多,从AI爬虫到无障碍的42步实战 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)是一份扩展清单。 资深团队反而更容易栽在结构性问题上,被忽略的那几类技术SEO失灵原因 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的就是这种局面。 这类没人报错的欠账攒起来相当可观,技术债怎么排查和分批偿还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了一套可执行的顺序。 ## 被声称刚刚改过的那些页面,正文真的动了吗? 到这里为止,能证明的只是这个数字在动。要证明它在说假话,还得反过来问一句:那些被声称刚刚改过的页面,正文究竟改了没有。 两次抓取拿到的东西不一样也可能另有原因,爬虫和用户看到的页面不一样怎么揪出来 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)是另一条排查线。 做对照组这件事经常能救命,量出七成页面有差异、补上对照组后只剩两个点 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)就是一次返工。 ## 闭环怎么设计 做法是从那18个整份全变的站,加上6个从不变化的对照站,把之前抓过的页面原样再抓一遍。两次抓取的间隔和sitemap那边完全一样,都是两个多小时。 抓下来的东西还可能被截断,2MB抓取上限的八步优化 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)是先要排除的干扰项。 抓下来的东西有没有正文得先确认,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)量的就是这件事。 做内容指纹要选对算法,从摘要算法到缓存键与完整性校验 (https://zhangwenbao.com/hash-generator-md5-sha256-etag-sri-fingerprint-guide.html)那份对照可以直接抄。 比对四样东西:页面标题、页面描述、H1、以及正文的词集相似度。前三样是逐字比对,改一个字符就算变;正文那一项是把可见文本切成词、剔掉哈希与随机串之后算重合比例。 选这四样是有讲究的。电商页面上有大量本来就每次都不同的东西——防重放令牌、灰度分桶标记、时间戳、埋点参数。这些东西如果不剔干净,任何两次抓取看上去都是不一样的。而标题、描述、H1不会因为你刷新一次就变。 ## 102个页面,标题99.0%一字未动 那18个站里可比对的页面一共102个。结果是: 标题在别处还会被重写一遍,四大平台社交卡片的逐字段体检 (https://zhangwenbao.com/og-preview-4-platform-social-card-audit-guide.html)能看出差异。 有些字段其实是被平台锁死的,哪些页面元素能改、哪些改不了 (https://zhangwenbao.com/shopify-on-page-seo-title-meta-url-platform-constraints.html)得先摸清楚。 标题这一栏怎么写也有讲究,八种模板与长度阈值背后的真相 (https://zhangwenbao.com/seo-title-generator-8-template-serp-length-guide.html)比工具给的建议实在。 比对项 | 可比对数 | 一字未变 | 占比 | 页面标题 | 96 | 95 | 99.0% | 页面描述 | 78 | 77 | 98.7% | H1 | 21 | 21 | 100% | 正文词集相似度 | 102 | 中位100% | — | sitemap说这102个页面在刚过去的两小时里全部被修改过,实际上它们一个字都没改。 ## 对照组给出了同样的100%,这很重要 对照组那29个页面(来自prose、article、weber、philips、traeger、stokke这几个修改时间从不变化的站)标题一字未变的比例是100%,描述100%,H1也是100%,正文相似度中位同样是100%。 想知道某个动作到底有没有增量,别让本来就会买的人冒领功劳 (https://zhangwenbao.com/incrementality-testing-marketing-measurement-guide.html)那套测法值得借鉴。 验证一条建议有没有效有个笨办法,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)比讲道理管用得多。 两组给出一样的结果,恰恰说明这把尺子是好的。两组页面在这两小时里都没动,唯一的差别在于它们的sitemap怎么说这件事。 ## 这把尺子第一次量出来的是4.6%,而且是错的 这一节值得单独讲,因为它差点让整篇文章的结论反过来。 数据看着正常也未必真的正常,浏览器把yes改成forks而问卷看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是同一种隐形污染。 口径不清的指标最容易误导判断,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭自己的框架。 一个准确率数字先要问它的及格线谁划的,95%准确率是自己划的还是考出来的 (https://zhangwenbao.com/ai-audit-tool-accuracy-rate-denominator.html)是同一类追问。 第一次跑闭环比对时,量出来的正文相似度中位数是4.6%,很多站甚至只有0.24%。按字面读,这意味着两小时里页面被换掉了99%以上——刚好可以拿来支持sitemap,可惜方向完全相反。 发现它有问题靠的是对照组:那6个从不变化的站也给出了同样极低的相似度。如果尺子是准的,两组不该长得一样。 根子在一行毫不起眼的映射代码。原先那批页面的存盘文件名里带一个序号,而这个序号来自任务队列的行号。我图省事,拿抓取结果文件里的出现顺序去重建这个序号——问题是那批抓取是八个进程并行跑的,结果文件的写入顺序跟队列顺序根本对不上。于是我一直在拿A页面的旧版跟B页面的新版做比较,比了一百多对,一次都没比对过同一个页面。 改成按队列文件里的序号列取值之后,相似度立刻从4.6%跳到100%。这类错误最坏的地方在于它不报错,输出的数字看起来还挺像那么回事。 教训写下来只有一句:并行写出来的结果文件,它的行序不携带任何信息,任何拿行序当键的做法都是错的。要拿也只能拿输入队列的行序。 ## 间隔换成七分钟、再换成四秒,前移量还跟得上吗? 两小时那一次可以说明问题,但单独一次实验总归不够。如果这个字段真的等于请求时刻,那么换一个间隔,前移量应该跟着换成新的间隔。这是一个可以被证伪的预测,做起来也不贵。 能被机器批量验证的事就别靠人记,哪些SEO工作能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条边界。 在线上做实验要先想好收尾,怎么做A/B测试才不影响SEO (https://zhangwenbao.com/ab-testing-page-seo.html)里有官方表态和清理动作。 ## 第二次自检:间隔七分钟 从那批文件里挑出变动最多的一份地址清单,每个站一份,在第二次抓取结束大约7分钟之后再抓第三次。 服务器上那一整套例行动作都能自动化,备份、清单导出、缓存与证书一条龙 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)有现成脚本可抄。 这类定时对照最适合交给计划任务,把排名、清缓存和这类巡检挂上定时 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)配置起来不算麻烦。 53842条可比对地址里,8539条的修改时间又变了,占15.86%——跟两小时那次的16.86%几乎一样。而这次的中位前移量是474秒,也就是7分54秒。 变动的站还是那18个,一个不多一个不少。 ## 第三次自检:间隔四秒 最后一次间隔短得有点荒唐。第三次抓取里我给同一个地址连发了两个请求,只是请求身份不同,两个请求之间隔着几秒钟的串行时间。 抓取速率被调低时往往一条错误都没有,服务器日志里看不见的那种降速 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)是同一类静默故障。 这类小脚本自己写最快,用对话式编程做SEO小工具的八步避坑 (https://zhangwenbao.com/vibe-coding-seo-tool-tutorial.html)讲的就是这种自养工具。 手头没有脚本的时候,用接口测试工具看清一个地址的状态码与响应头 (https://zhangwenbao.com/api-tester-http-status-header-rest-debug-seo-guide.html)也够用了。 结果是121851条可比对地址里有32406条给出了不同的修改时间。把这些差值按绝对值分档: 差值区间 | 条数 | 占比 | 不超过60秒 | 28880 | 89.1% | 61秒到10分钟 | 1092 | 3.4% | 10分钟到1天 | 779 | 2.4% | 超过1天 | 1655 | 5.1% | 差值的中位数是4秒。两个请求之间隔了几秒,答案就差了几秒。 ## 三个量级全部对上,这个字段就是请求时刻 把三次实验并排放: 同一件事在日志里也能验一遍,5000个站的爬虫伪造与抓取预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)可以互相印证。 数字与数字之间也会出问题,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)是最典型的一例。 一个指标要能被复算才敢拿来做决策,五大指标的单一事实来源怎么建 (https://zhangwenbao.com/seo-metrics-layer-single-source-of-truth-data-governance.html)是配套的治理办法。 两次请求的间隔 | 发生变化的比例 | 中位前移量 | 2小时22分 | 16.86% | 2小时18分19秒 | 约7分钟 | 15.86% | 7分54秒 | 约4秒 | — | 4秒 | 三个数量级差着上千倍,每一次前移量都跟间隔本身对齐。这已经不是相关性了,这是同一个东西。 为什么中位前移量总比间隔略小一点?因为435份文件不是同时抓完的,每份的两次时刻各有各的偏差;另外有些站的这份文件挂在缓存后面,缓存的存活时间会让答案落后于真实的请求时刻几分钟。 ## 一分钟就能在自己站上跑一遍 不需要写脚本,两条命令就够。取一条你站上的sitemap地址,抓下来存成第一份,喝口水,再抓一份,然后对比两份文件。如果两份文件里的时间字段整体前移了你喝水的那段时间,那么这个字段在你站上就是个装饰。 生成器说格式正确并不代表内容对,它说校验通过的时候其实只查了三件事 (https://zhangwenbao.com/sitemap-generator-xml-lastmod-priority-validation-guide.html)值得看一眼。 不会写代码也有办法批量做,十二个表格公式把数据活自动化 (https://zhangwenbao.com/google-sheets-for-seo.html)对小团队够用。 不花钱也能把基础检查做全,预算为零时真正好用的那批工具 (https://zhangwenbao.com/free-seo-tools-zero-budget-checklist.html)列过一份清单。 需要留意的是要用同样的请求身份抓两次,并且别用浏览器——浏览器会带缓存,你看到的可能是本地副本。 ## 换一个身份去问,同一份文件会给出不同答案吗? 跨站抓取有一条铁规矩:任何一个数字报出去之前,都要先确认它测的是这个地址的状态,还是这台机器受到的待遇。同一个地址对不同来客给出不同答案,是这几年越来越常见的事。 模拟不同身份去测站有现成办法,用生成的标识去试探自己的站 (https://zhangwenbao.com/useragent-generator-ua-string-bot-simulation-seo-guide.html)能复现大部分差别待遇。 要弄清对面到底是谁再谈待遇,120种爬虫标识的分类与真假验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)是一份可以照做的清单。 ## 为什么这一步不能省 更早一批实验里遇到过一次典型:63条抓取失败的地址,换成普通浏览器身份重抓,18条立刻变成正常,占28.6%。如果不做这一步,失败率会被虚报将近一半。 真要拦住某类程序得分层做,三层选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比只改一个文件靠得住。 想知道谁真的来过只能看日志,每5次Googlebot抓取就有1次IP不属于谷歌 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是同一批数据挖出来的。 拦截往往发生在你看不见的那一层,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)答案没那么简单。 写了放行也未必等于对方进得来,说允许、仍有十个站把对方挡在门外 (https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html)是另一层错位。 所以这次也做了。第三次抓取的时候,每个地址用爬虫身份和浏览器身份各请求一次,两次挨着发。 ## 表面数字:26.59%,涉及61个站 直接比对的结果是121851条可比对地址里32406条不同,占26.59%,涉及61个站。eufy.com差了7300条,anker.com差了1585条,iittala.com差了1550条。 一个判断值不值得做,样本先替你答一半,87个站的清单先替你答了一半 (https://zhangwenbao.com/keyword-own-page-duplicate-wordset-audit.html)是同一种取数思路。 一个数字好看不等于它有用,砍掉虚荣指标、只盯能驱动生意的信号 (https://zhangwenbao.com/vanity-metrics-north-star-omtm-ecommerce.html)是同一个取舍。 同一个数字各家算法不同这件事到处都是,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 如果就这么写出去,标题大概会是“同一份地址清单,四分之一的时间戳会因为你是谁而改变”。这句话很有传播力,也很危险,因为它是错的。 ## 把测量顺序从结果里扣掉 问题出在两个请求不是真的同时发出去的。脚本先发爬虫身份那一个,等它跑完再发浏览器身份那一个,中间隔了几秒。而前面刚证明过,这个字段每过一秒就往前走一秒。 做对照要先算清能不能测得出来,单因素隔离与最小可检测效应 (https://zhangwenbao.com/seo-ab-testing-experiment-design-statistical-power-single-factor.html)是绕不开的一步。 换个环境结论就变的建议要格外小心,四层架构分歧导致优化建议跨平台失灵 (https://zhangwenbao.com/ai-optimization-advice-not-portable-cross-platform.html)是同一类陷阱。 所以要看差值有多大。89.1%的差异不超过60秒,中位数4秒;方向上也是压倒性的——32276条是后发的那次更新,只有130条反过来。这三条特征凑在一起只指向一个结论:这不是身份差异,这是我自己的测量顺序。 按站算也一样:61个站里有45个站的中位差值不超过60秒。 ## 扣干净之后,真正的身份差异只剩3个站 把中位差值超过1天的站单独挑出来,只有三个:iittala.com有1550条,中位差1.8天;rituals.com有134条,中位差3.0天;otto.de只有1条,差6.3天。 爬虫拿到的可能压根不是页面,人机验证屏被当成正文索引 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)是最难查的一种。 响应会不会因人而异也能量,说会变的3个站、真会变的17个站 (https://zhangwenbao.com/vary-header-declared-vs-actual-response-variation.html)是同一种对照。 还有一个负结果值得记一笔:两种身份下114份文件的状态码全部是200,没有一份因为身份被拒。在别的实验里这个位置经常出现大批403,这次一次都没有——机器可读文件的待遇和普通页面确实不一样。 ## 这条方法能搬到别的地方 判据可以固化成三问:第一,两次测量是不是真的同时发生的?第二,如果不是,被测的量在这段时间里会不会自己变?第三,观察到的差异,方向是不是压倒性地偏向后测的那一次? 一堆问题先修哪个得有依据,五百个站实测排出来的技术SEO优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)可以当排期底稿。 把审计交给自动化之前有三个前提,数据、方法与人工复核各要满足什么 (https://zhangwenbao.com/ai-seo-geo-audit-agent-pitfalls.html)得先过一遍。 判断对面是哪一代程序只能看日志,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)那套挖法可以直接套用。 三个问题里只要有一个答不上来,报出去的差异里就掺着你自己的影子。这次的比例是89.1%——四分之一的差异里,九成是我造出来的。 ## 41万条地址里,这个字段的整体面貌是什么样的? 前面几节都在拿动态说事,这一节回到静态口径,把这批数据完整摊开。 整站体检该查什么有现成框架,从抓取、内容到AI可见度的完整诊断清单 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以照着排。 收录、排名、流量是三件事,没流量的时候先分清卡在哪一层 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)能省掉一半无用功。 ## 覆盖率58.7%,但站级分布是两头大中间小 410101条地址里有240643条带修改时间,占58.7%。 平台内置、通用工具与专属应用各有边界,三层框架怎么选 (https://zhangwenbao.com/shopify-seo-tools-three-layer-selection.html)能避免重复投入。 换成前后端分离之后这套基建要自己重搭,清单、重定向与规范网址集体失分 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是常见的第一课。 不装插件也能把这份清单做扎实,动态优先级、图片节点与分页缓存的写法 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)是一份完整实现。 站级看是这样:116个站里12个站一条都不写,38个站条条都写,66个站部分写。部分写的那批多半是因为不同类型的地址由不同的模块生成——商品页有,专题页没有,博客有,落地页没有。 ## 一条都不写的那12个站,反而是最省心的 这个说法听着别扭,但从信号质量的角度看确实成立。不写就是不表态,抓取方拿不到信息,会退回到自己的判断,代价是它得多花点力气。 每年清一次工具栈很有必要,12个站样本里的四维冗余与八步瘦身 (https://zhangwenbao.com/ai-tool-stack-annual-audit-12-sites-4-dimensions-8-steps.html)给了可执行的顺序。 装得越多越容易互相打架,应用栈精简、性能治理与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)是同一个减法思路。 写了假的则不一样。它先给出一个明确的表态,抓取方按这个表态排一次序,事后发现不对再回来调整,中间浪费掉的抓取次数是实打实的。 这里有个容易被忽略的连带影响:这个字段还常常被拿去喂别的东西。有些站把它当成商品的更新日期渲染进页面,有些站的内部报表拿它统计维护频率。一旦源头是假的,下游几个地方会一起跟着假。 ## 精度:12.7%只精确到日期 写了时间的那24万条里,30562条只写到年月日,没有时分秒,占12.7%。带时区标记的有210081条。两种写法都合规,时间格式规范里的完整日期与完整日期加时间两种形态 (https://www.rfc-editor.org/rfc/rfc3339.html)都被允许。 结构化数据里的日期同样容易写错,把结构化数据调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)那篇有逐字段的排查法。 几种日期写法各有各的场合,国际标准格式、清单与响应头之间的格式账 (https://zhangwenbao.com/date-formatter-iso8601-sitemap-lastmod-rfc2822-guide.html)算得很清楚。 还有一个数字为零:未来时间的条目一条都没有。这算是个好消息,说明至少没人把这个字段当成上架排期表用。 ## 年龄分布:将近一半号称是当天改的 距离抓取时刻 | 条数 | 占比 | 不到1天 | 116413 | 48.4% | 1到7天 | 42521 | 17.7% | 7到30天 | 19707 | 8.2% | 30到180天 | 29433 | 12.2% | 180天到1年 | 14419 | 6.0% | 1到3年 | 8344 | 3.5% | 超过3年 | 9806 | 4.1% | 刚开始做数据分析先把工具理顺,三类工具与排名追踪的习惯 (https://zhangwenbao.com/seo-data-concept.html)是个不错的起点。 旧文章的处置有一套标准动作,更新、合并还是删除的四步判断 (https://zhangwenbao.com/old-blog-content-update-merge-delete-seo-sop.html)可以直接搬。 新鲜度也能拿来换AI引用,内容新鲜度的五条实战法则 (https://zhangwenbao.com/maintain-content-freshness-fast-indexing-ai-citations-2026.html)说的是怎么做才算真更新。 老内容悄悄掉量是常态,内容衰退的识别与分级更新 (https://zhangwenbao.com/content-decay-mechanism-portfolio-roi-tiering.html)比盲目全量刷新划算得多。 整体中位年龄是1.12天。四分之一的地址号称是抓取前15分钟内改的。而最老的一条落在14.4年前,比很多做SEO的人入行还早。 把这张表跟前面的漂移实验放一起看就明白了:那48.4%里有相当大一块不是真的当天改过,只是它每次被读取的时候都会重新盖一个当天的戳。 ## 为什么有些站的时间戳整整齐齐挤在同一秒? 翻这批文件的时候有个现象特别扎眼:不少文件里成百上千条地址共用同一个时间戳,一秒不差。 一个模板生成十份内容也是同样的机制,字符层看不出重复、信息层十份一模一样 (https://zhangwenbao.com/multilingual-template-ten-languages-duplicate-content-risk.html)是它的另一面。 模板批量生成的东西撞车是常态,插件和主题各冒出一套规范网址怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一类清理。 ## 232份文件里,90份整份只有一个取值 把带修改时间不少于50条的文件挑出来一共232份,其中90份文件里所有条目的时间戳完全相同,占38.8%。 一次扒清页面上所有格式的字段缺漏,结构化数据审计工具怎么用 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)那篇讲了操作细节。 结构化数据里也有大量批量填出来的字段,112个独立站里17个在犯的商家名称错误 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是一份对照。 几个具体的例子:bellroy.com的一份文件513条地址全部写着同一个日期;rapha.cc的93条全部是同一个毫秒;allbirds.com的291条共用同一秒。 aloyoga.com更整齐——三份文件分别是936条、986条、991条,前两份共用同一秒,第三份共用它的下一秒。2913个页面,两秒钟改完。 ## 把这些时刻拉到同一个时区,它们落在同一分钟里 这才是真正有意思的地方。allbirds写的是06点16分18秒,aloyoga是06点16分19秒和20秒,avocadogreenmattress是06点16分23秒,baseus是06点16分30秒,beistravel是06点16分32秒。awaytravel和brooklinen写的是另一个时区的09点16分,换算过去也是06点16分26秒和55秒。 名单上那些名字有没有真来过也能量,266个爬虫令牌里只有23.3%真的来过 (https://zhangwenbao.com/crawler-ua-list-named-vs-real-visits-audit.html)是另一组实测。 这类没人维护的字段到处都是,响应头里248个死字段、多数不是你写的 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html)量的是同一种存量。 响应里冒出一个莫名其妙的日期,可能是运行环境替你写了一行1981年的时间 (https://zhangwenbao.com/php-session-cache-limiter-nocache-cdn-audit.html)就是这么来的。 七个互不相干的品牌,页面加起来好几千个,声称自己在同一分钟之内完成了修改。而那一分钟,恰好是我这台机器开始发请求的前后。 它们的共同点是跑在同一个电商平台上。平台在生成这份文件时把当前时刻填了进去,仅此而已。 ## 这不是某一家平台的毛病 容易把这件事读成某个建站平台不行,但数据不支持这个说法。那18个整份全变的站里,既有跑在主流托管电商上的服装品牌,也有自建站的消费电子品牌,还有欧洲的连锁零售。它们唯一的共同点是这份文件由程序在请求时现生成。 默认值被人悄悄改掉更难发现,第三方默认行为变更造成的静默漂移 (https://zhangwenbao.com/third-party-default-changes-silent-drift-audit.html)是同一种失控。 第一年最容易踩的都是默认配置,跨四种建站系统共有的12项隐性失分 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)可以逐条对照。 选平台时就该问清楚默认行为,托管、自建还是纯代码怎么选 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)把各自的代价摊开了。 反过来,同一个平台上也有大量站的时间戳老老实实待在原地。差别不在平台,在于导出这份清单的那段逻辑到底读了什么——读数据库里的内容更新时间,就是对的;读系统当前时间,就是错的。这两行代码长得很像,写的人往往不觉得有区别。 更值得留意的是,这类默认值一旦定下来,后面接手的人几乎没有机会发现它不对。生成的文件格式合法,校验工具全部通过,搜索后台也不会报错。要发现它,你必须主动去做一次前后对照——而这件事不在任何一份常规检查清单上。 ## 只写到日期的那12.7%是同一种毛病的低配版 只精确到年月日的写法,效果等于把时间戳的分辨率砍到一天。bellroy那513条就属于这一类——它们全都写着抓取当天的日期。 工具漏改的地方往往在它的视野之外,它只看紧挨着的那一个字 (https://zhangwenbao.com/chinese-typography-punctuation-paren-diff-panel-guide.html)就是这类边界。 分页那一层也常被平台简化处理,集合页分页的索引判断与规范网址设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)需要单独理一遍。 这种写法的问题不在于不精确,而在于它同样是生成时算的。第二天再抓,日期会跟着换成第二天。 ## 怎么一眼认出这种文件 不需要抓两次也能看出苗头:打开一份地址清单,看时间戳的不同取值有几个。如果几千条地址只有一两个取值,或者所有取值都挤在几秒钟之内,那基本可以确定它记的是生成时刻。 想看一个页面过去长什么样,缓存快照退役后还能用的几个工具 (https://zhangwenbao.com/webpage-cache-snapshot-viewing-tools-guide.html)能帮上忙。 桌面爬虫跑一遍就能看出不少毛病,全站审计的十二类问题排查清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)是配套的检查表。 清单里混着坏地址也很常见,死链批量检测、分类到提交的一条龙 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)能顺手一起做掉。 真正跟着内容走的文件长得很不一样——时间戳会散布在过去几个月甚至几年里,密度随着时间往回走逐渐变稀。 ## 那44个处在中间的站,才是这个字段正常工作的样子 115个站里有44个既不是全变也不是全不变。这批站的形态值得看一眼,因为它们提供了一个可以对照的正常值。 商品数据一变就牵动一堆页面,八类重复内容的成因地图与诊断清单 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)可以对照排查。 真正难缠的是筛选组合产生的地址,分面导航产生的海量地址怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)单独拆过一遍。 同一商品的几十个地址该合还是该拆,产品变体的地址与索引策略 (https://zhangwenbao.com/product-variant-seo-url-canonical-indexation-strategy.html)需要先想清楚再动。 它们的变动比例散落在几个百分点到几十个百分点之间,且集中在特定几份子文件上——通常是商品清单那几份在动,帮助中心和法律条款那几份不动。这正是一个真实电商站该有的样子:库存和价格每天变,退货政策一年改一次。 要注意的是,两小时里动几个百分点仍然偏多。更可能的解释是这批站的时间戳跟的不是内容本身,而是数据库里那行记录的更新时间——库存数字变一下,记录的更新时间就跟着变,页面上肉眼看不出任何区别。这算是个中间状态:开关接上了,只是接得比应该接的位置更靠前。 ## 另一头的毛病:四年没动过的时间戳算不算问题? 前面说过还有46个站一条都没变。它们里面藏着方向完全相反的另一种病。 自动化不是哪天突然坏的,它从第二周就开始走形而没人发现 (https://zhangwenbao.com/ai-automation-runtime-rot-guardrails.html)说的是同一种慢性失效。 变更没人记就等于没发生,13类信号、5档工具栈与22周落地 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)是一套变更日志的做法。 ## 6个站的时间戳停在半年到四年以前 把这46个站按各自时间戳的中位年龄排一下,有6个站的中位年龄超过180天: 长期没人管的东西还有别的形态,测试站被索引后的八步清除与四层防御 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)是最典型的一例。 新鲜度和常青资产要一起平衡,媒体站为什么总在这两者之间崩 (https://zhangwenbao.com/news-publisher-seo-freshness-breaking-evergreen-lifecycle.html)有完整的机制拆解。 上千篇旧内容的处置需要一套判据,留、改、并、删、转的决策系统 (https://zhangwenbao.com/content-audit-pruning-decision-system.html)比拍脑袋靠谱。 站点 | 时间戳中位年龄 | prose.com | 1578天(约4.3年) | article.com | 1431天(约3.9年) | weber.com | 1292天(约3.5年) | philips.com | 974天(约2.7年) | traeger.com | 887天(约2.4年) | stokke.com | 294天(约0.8年) | 这几个都不是小站。它们的商品页在这几年里必然改过价格、改过库存状态、改过文案、改过图片。而那份清单上的时间,还停在改版那天。 ## 两种病的机制其实是同一个 第一种是把这个字段接到了生成程序上,第二种是压根没接。看上去南辕北辙,本质完全一样:没有任何一个事件会触发这个值的更新。 同一批样本上量过的另一件事是,给单个爬虫开组会丢掉通配组全部规则 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)中招比例高得离谱。 写下去却没有接收方的指令不止这一处,有多少条规则压根没人在读 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)比想象中高得多。 第一种的触发源是文件被请求,第二种的触发源是某次人工导入。真正应该当触发源的那件事——页面内容发生变更——两种都没接上。 ## 哪一种更糟 要看搜索引擎怎么用它。如果它每次都说全都是新的,那么它对所有地址的区分度为零,等于什么都没说;如果它常年不动,同样区分度为零。两种都是废字段,但后一种至少不会给人一种在正常工作的错觉。 收录速度本身也能当指标看,三个平台、三百个站的收录速度实测对比 (https://zhangwenbao.com/seo-kpi-guide.html)给了参照值。 有些指标该退休了,2026年该淘汰的九个SEO指标与替代方案 (https://zhangwenbao.com/retire-outdated-seo-metrics-2026-strategy.html)列得比较果断。 需要说清楚的是,这个字段不写并不会招来惩罚。规范里它是可选的。真正的代价在于:一个大站的抓取资源是有限的,你放弃了一个本来可以用来引导抓取顺序的信号。 ## 判断自己属于哪一种,只要两步 第一步,隔十分钟抓两次,看数字动不动。全都在动就是第一种。 做这行容易把自己耗空,一套个人审计五步法 (https://zhangwenbao.com/seo-health-zhang-xuefeng-insight.html)顺手也留给自己用。 三个平台的后台告警要分级处理,分级诊断与90天监控闭环 (https://zhangwenbao.com/webmaster-alert-triage-gsc-bing-baidu-three-platform.html)能把噪声压下去。 想批量核对收录状态有配额限制,2000条配额下的监控管线怎么搭 (https://zhangwenbao.com/gsc-url-inspection-api-bulk-index-monitoring.html)是一套现成方案。 第二步,如果不动,随便挑五个你确定最近改过的页面,看它们的时间戳是不是跟着改了。没跟着改就是第二种。 两步都过了才算这个字段是活的,而这批样本里能两步都过的站并不多。 ## 索引文件那一层的时间,和子文件对得上吗? 大站的sitemap通常分两层:一个索引文件列出所有子文件,每个子文件再列具体地址。索引文件那一层也可以给每个子文件写一个修改时间,语义是这个子文件最后一次变动的时间。 两处说法不一致时该信谁是个老问题,工具说在头部、浏览器说在正文该信哪一边 (https://zhangwenbao.com/head-boundary-canonical-parsed-into-body-seo.html)也是同一种分歧。 两层由不同团队维护是常态,后端工程师配合SEO的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)是从22周账本里总结的。 ## 1730条声明,只有70对能真正核对 索引文件里带修改时间的子文件声明一共1730条。能同时拿到子文件本体、可以做对账的有70对。 要批量订正历史数据得小心,怎么安全地批量改一批文章的SEO字段 (https://zhangwenbao.com/sql-generator-batch-update-cms-database-injection-guide.html)有可直接用的写法。 论坛程序也能自己拼出这份清单,免插件的导出改造与分页做法 (https://zhangwenbao.com/discuz-portal-sitemap.html)是个小而完整的例子。 对账办法很直接:索引里声明的那个时间,应该等于这份子文件里所有地址的最大修改时间。 ## 只有32.9%对得上 70对里相差不超过60秒的只有23对,占32.9%。剩下47对的差值中位数是0.4天,最大的一对差了1374天,也就是将近3.8年。 两处说法不一致最后往往落到重复上,同域、跨域与参数变体六类全排查 (https://zhangwenbao.com/content-duplicate-issue.html)可以顺着查。 规范网址自相冲突也是常见故障,八种跨页场景与冲突诊断 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)可以按图索骥。 两个声明同时出现该怎么判,九种场景下这两者能不能一起用 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)有逐个场景的答案。 换句话说,同一个站的两层文件对同一批页面的最后修改时间给出了差着三年多的两个答案,而这两份文件是同一次导出生成的。 ## 为什么会脱节 多数情况是两层由不同的代码路径生成:索引那一层由一个定时任务刷,子文件由另一段逻辑填。谁都没有义务去看对方写了什么。 把检查接进流水线才不会反复,自动化为什么不能放在最后一段做 (https://zhangwenbao.com/seo-automation-engineering-ci-maintenance-architecture.html)讲的正是这件事。 两段逻辑归两个团队就容易脱节,内容、技术、外链三类分工与团队配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)是同一个协作问题。 还有一种更隐蔽:索引那一层写的是文件被重新导出的时间,子文件里写的是内容的时间。两个语义本来就不一样,但字段名是同一个。 ## 这一层错了要紧吗 要紧程度取决于站的规模。子文件数量少的时候,抓取方会把每个子文件都读一遍,索引层写什么都无所谓;子文件成百上千的时候,索引层的时间会影响先读哪一份。 想知道抓取资源花在哪只能看日志,读懂抓取行为与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)是配套的工具教程。 站的层级深浅直接影响能不能被找到,架构搭错了爬虫根本走不到商品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)有对照实验。 ## 没有交叉校验的余地,这件事严重在哪? 一个自我申报的数字要变得可信,通常靠两条路:要么有人核验,要么有另一个独立来源可以对照。这个字段两条都没有。 两处都能下同一道指令的时候容易搞反,这两个手段各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)里分工写得很清楚。 响应头那一层能承载的信息比多数人以为的多,索引指令、缓存与协商字段各管什么 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)有一份完整机制图。 ## 694个页面响应里,只有13个带修改时间响应头 HTTP协议本身有一个字段专门用来说明资源的最后修改时间,位置在响应头里,协议规范里对这个字段的语义界定 (https://www.rfc-editor.org/rfc/rfc9110.html)比清单那边严格得多。理论上它可以拿来跟sitemap里的声明对账。 有些地址连声明的地方都没有,接口和订阅源拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)是同一类结构性缺口。 缓存这一整套字段配起来讲究不少,怎么让回头客秒开又不犯改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)有逐项配置建议。 实测下来,694个页面的响应里只有13个带了这个字段,占1.9%。剩下98.1%的页面根本没有第二个时间可以拿来核对。 原因不难理解:现在的页面几乎都是动态生成的,服务端自己也说不清这个页面的内容是什么时候定稿的,索性就不写。 ## 校验的最后一条路也堵着 还有一个办法是用内容指纹——如果两次抓取的页面字节完全一样,那就是没改。可惜页面上那些每次都不同的令牌和埋点参数让字节比对基本失效,必须先做归一化,而归一化的规则每个站都不一样。 正文藏在脚本里会让所有比对失效,三种渲染方式下的引用率差异实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)给了量化的落差。 页面上哪些是内容、哪些是壳子并不好分,语义化标签到底影响不影响机器抓取 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)拿样本页跑过一遍。 这就是为什么这个字段在实践中变成了一句没人查的话。 ## 抓取方其实还有一条路,只是这条路上的站更少 HTTP协议里有一套条件请求机制:抓取方带上上次拿到的指纹再来问一次,服务端如果发现没变,就回一个不带正文的短响应。这个字段与条件请求怎么配合 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Last-Modified)有一份写得很细的说明。这套机制既能省流量,又天然是一个诚实的变更信号,因为它由服务端在响应那一刻现算。 传输这一层还有别的浪费,出厂只压一种类型、其余字节全额计入抓取预算 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)也值得顺手查。 没改过的页面被反复重发很浪费,服务器把同一个页面对爬虫重发几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)是怎么发现的写在里面。 这套机制的普及度实测过,142个站只有52个回得出那个短响应 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)就是那次的结论。 问题是能正确回应这套机制的站同样不多。更早一批实测里,142个站只有52个在没改的情况下回得出那个短响应,其余的每次都把整个页面重发一遍。 两条路都走不通的结果是:抓取方只能靠自己反复抓、反复比,用统计的办法猜哪些地址值得常来。你在清单里写的那个时间,在这套猜测里的权重,取决于它历史上有多准。 ## 搜索引擎那边怎么处理 Google的公开说法是这个字段只有在一致且可信的时候才会被参考。这句话反过来读就是:它已经默认相当一部分站写的是假的,所以先看一致性再决定信不信。 手动提交能不能加快收录也被问烂了,真相与配套的排查清单 (https://zhangwenbao.com/request-indexing-faster-google-indexing-myth.html)那篇答得比较干脆。 一个信号在整条链路里的位置决定它的分量,召回到重排四个阶段各看什么 (https://zhangwenbao.com/search-ranking-pipeline-retrieval-rerank-architecture.html)有完整拆解。 声明与实际判定不一致是常态,规范网址选择的九条决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)解释了它凭什么不听你的。 怎么判断一致?最省事的办法就是隔一段时间抓两次,看这个值是不是跟着请求走——跟我做的实验一模一样,而且他们抓的次数比我多得多。 ## AI那边的抓取器读不读这个字段? 这个问题现在还没有可靠答案,能说的只有几条负结果,但负结果也是结果。 第一,各家AI抓取器都没有公开承诺过会参考这份清单里的时间。它们的公开文档里通常只写遵守哪些抓取规则,不写按什么顺序抓。 第二,从行为上看,这类抓取器更依赖从页面链接出发的遍历,以及用户当场提问触发的实时取回。后一种模式压根用不上任何预先排序——用户问了,它现在就去取,不管这个地址上次什么时候改过。 第三,同一批样本里给AI准备的那份纯文本清单,规范新增的两种链接关系在631个页面里采用数为零。这说明这一层的基建还很早期,谈不上谁在读谁的时间戳。 所以务实的判断是:修这个字段的收益目前只落在传统抓取那一侧。如果你的动机是让AI更快看到新内容,力气花在别处更划算——比如让页面在不执行脚本的情况下就能读出正文。 ## 回到开头那条新闻 官方说尽量让公告贴近按下按钮的那一刻,为什么这件事需要专门解释?因为“发生”和“被记录”之间那道工序,永远存在。区别只在于有没有人认真去缩短它。 核心更新来了先别慌,六步落地的应对动作 (https://zhangwenbao.com/google-broad-core-update-survival-guide.html)比到处打听消息管用。 算法更新的时间线值得留一份,完整盘点、评估体系与应对策略 (https://zhangwenbao.com/google-algorithm-updates.html)可以当索引用。 sitemap里那个字段的问题不是有人存心撒谎,而是写它的那段代码,只在文件被生成的那一刻运行过一次,此后它再也没有机会知道页面发生了什么。 ## 自己站上怎么查,查完该改哪里? 前面全是别人家的数据,这一节说自己怎么办。整套检查一个人半天能做完,不需要额外工具。 技术项全绿也可能不涨,问题多半出在搜索意图没对齐 (https://zhangwenbao.com/search-intent-alignment-vs-technical-seo.html)是另一条要并行看的线。 同样的问题在不同规模的站上优先级不同,三类站点的高投入产出比修复顺序 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以直接套。 ## 五步自查顺序 第一步,抓两次隔十分钟的同一份地址清单,比对时间字段。全变说明接在生成程序上,全不变进第二步。 两个来源给的收录数不一样时,六种场景下该信谁与三源校准 (https://zhangwenbao.com/site-search-operator-vs-gsc-coverage-accuracy-decision.html)给了判据。 用命令查收录有它的适用边界,这个命令什么场景能用、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)说得比较细。 后台那份抓取报告要会读,五类问题地址的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你分清是谁的问题。 第二步,挑五个最近确实改过的页面,看它们的时间戳有没有跟着变。没变说明这个字段是死的。 第三步,看一份文件里时间戳的不同取值有几个。几千条只有几个取值,就是批量盖章。 第四步,如果是两层结构,拿索引层声明的时间跟子文件里的最大时间对一下。 第五步,看看页面响应头里有没有修改时间字段。有的话跟清单里的值对一下,两边差得离谱说明至少有一边是编的。 ## 三条判据,问的是同一件事 把上面五步压缩成三个问题:这个值是谁写进去的?世界上发生什么事它才应该改?那件事发生的时候,有没有任何东西会去通知写它的那段代码? 服务器上那些数值型配置也该逐条问一遍,二十项配置对SEO的实际影响 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着核对。 配置每次都通过不代表没事,每八次抓取就有一次撞在跳转上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类隐形代价。 第三问答不上来,前两问答得再漂亮也没用。一个字段能不能长期保持正确,靠的不是当初写得多用心,而是它背后有没有一个“什么时候该改我”的开关。 ## 要修的话改哪一层 最正确的做法是在内容层埋一个更新时间,页面每次保存时写一次,导出清单时直接读它。这需要后台配合,多数团队卡在这一步。 导出之后还要把新地址推出去,实时推送与异步队列的做法 (https://zhangwenbao.com/wordpress-baidu-active-push.html)是配套的一环。 批量订正历史数据免不了直接动库,分批更新与时间字段同步的写法 (https://zhangwenbao.com/dedecms-commonly-used-batch-sql-statements.html)有可复用的语句。 老程序里改一次内容就冲掉发布时间,怎么改文章又保留原发布时间 (https://zhangwenbao.com/dedecms-changes-the-time-of-release-after-updating-the-article.html)是同一个字段该由谁写的问题。 退而求其次,可以在导出程序里加一层缓存:把上一次导出的地址与时间存下来,这次导出时只有内容指纹变了的地址才更新时间,其余沿用旧值。这个方案不需要动业务代码,成本主要在存那份快照。 再退一步,如果两条路都走不通,那就别写。空着比乱写强,理由前面说过——一个对所有地址都给同样答案的信号,等于没有信号。 ## 把检查接进流程,别做成一次性巡检 这件事最容易的失败方式是:这次查出来了,改好了,三个月后原样回来。原因很简单,改的是数据,没改产生数据的那段逻辑。 重复劳动该交出去就交出去,六类耗时任务的自动化方案 (https://zhangwenbao.com/ai-streamline-seo-tasks.html)按投入产出排过序。 这类脚本现在写得比过去快,怎么搭一条SEO自动化工作流 (https://zhangwenbao.com/claude-code-seo-automation-workflow.html)有完整实测。 把巡检串成工作流并不难,四个场景闭环把内耗变成产线 (https://zhangwenbao.com/n8n-dtc-seo-pipeline-4-scenarios.html)有现成的编排思路。 可以接的地方有两处。一是在导出流程的末尾加一道断言:如果这次导出的时间戳里,取值数量少于地址数量的某个比例,就让流程报错而不是安静地发布。这条断言写起来不到十行,能挡住批量盖章那一整类问题。 二是留一份上次导出的快照,每次导出后对比两次的时间戳分布,变动比例超过阈值就发一封邮件。这条能挡住的是另一类:某次上线之后生成逻辑被人改了,而没有人注意到。 两道都加上,这个字段才算真正有人管着。只做一次巡检,得到的只是一张三个月后就过期的快照。 ## 什么情况下干脆不必管它 地址少于几千条的站,抓取方大概率会把全部地址都读一遍,这个字段影响很小,花力气去修性价比不高。 小站的力气该花在别处,把计算器和生成器做成链接磁铁 (https://zhangwenbao.com/free-tools-calculators-seo-link-magnet-asset.html)可能回报更高。 任何改动都要给它时间,收录、爬坡到起量的真实时间线 (https://zhangwenbao.com/how-long-does-seo-take-realistic-timeline.html)能帮你管理预期。 地址上万、页面更新频率差异很大的站才值得认真做——比如商品页天天变、帮助中心一年不动的那种,这个字段能实实在在改变抓取的先后顺序。 ## 修好之后能拿回什么,可以粗算一笔 这笔账算法不复杂。假设一个站有5万个地址,抓取方每天大约来看几千次,那么把全站过一遍需要十几天到几十天不等。 如果这份清单里的时间是可信的,抓取方可以把力气优先放在真正改过的那几百个地址上,剩下的按更低频率轮转。你新上的商品从上架到被发现的时间,可以从以周计缩短到以天计。 如果这份清单里的时间对所有地址都一样,这个优先级就无从谈起,抓取方只能按自己的历史统计去猜。猜的结果通常是:过去经常变的那类地址多来几趟,其余的慢慢排队。对一个刚上线新品类的站来说,这个默认策略相当不友好,因为新品类没有历史。 换句话说,这个字段的价值在改版和上新的时候最大,平时看不出来。这也解释了为什么它长期没人管——它不出问题的时候完全隐形,出问题的时候你又很难把掉量归因到它头上。 ## 顺手说说旁边那两个字段 这份清单里还有两个常被一起写上的字段:更新频率和优先级。它们和修改时间是同一类东西——自我申报、没人核验,区别只在于它们连一个可以被证伪的事实都没有。 修改时间至少还对应着一件客观发生过的事,你可以拿页面去核对。更新频率写的是你打算多久改一次,优先级写的是你觉得这个页面在自己站内有多重要。这两件事只存在于你脑子里,外部无从验证,所以抓取方早就宣布不再参考它们。 实践中的建议很简单:这两个字段直接删掉。留着它们唯一的作用是让文件变大,以及让下一个接手的人以为它们还在起作用。样本里仍然有相当一批站在认真维护这两栏,那些力气基本是白花的。 ## 一张判断表 观察到的现象 | 说明什么 | 该做什么 | 隔十分钟抓两次,值整体前移十分钟 | 接在生成程序上 | 改成读内容层时间,或加导出快照 | 值常年不动,改过的页面也不动 | 压根没接触发源 | 同上,或干脆去掉这个字段 | 几千条地址只有一两个取值 | 批量盖章 | 同上 | 索引层与子文件差着几百天 | 两层由不同代码生成 | 统一由一处产出 | 只有少数地址在变,且能对上改动记录 | 这个字段是活的 | 什么都不用做 | 推不动改动往往不是技术问题,重写汇报方式的八个步骤 (https://zhangwenbao.com/enterprise-seo-evolutionary-framing-eight-steps-rebuild.html)比反复解释有效。 把口头约定写成文字永远划算,达标定义、违约责任与四类经典纠纷 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)是另一个场景的同一道理。 ## 顺带一个和内容策略有关的提醒 有人会想:既然这个字段这么容易写,那把它全刷成今天是不是能让页面显得更新鲜?这条路走不通,而且代价不小。抓取方会拿它跟页面实际变化对账,对不上的站会被降低这个信号的权重——一旦被降权,你以后真的更新了它也不认。 结构化数据也常被当成灵丹妙药,它对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)有官方说法加实测。 旧文章翻新是有章法的,十二步把旧版改成可被引用的来源 (https://zhangwenbao.com/revise-old-content-for-aeo-ai-search-optimization.html)比改日期实在得多。 批量生成的东西容易长得一样,五步差异化的实战办法 (https://zhangwenbao.com/ai-content-sameness-seo-fix-guide.html)能救回一部分。 换句话说,这个字段最大的价值来自它的诚实度,而诚实度是一次性的信用。攒起来要很久,花掉只要一次批量刷新。 真要让页面显得更新鲜,办法还是那个笨办法:把内容改到真的值得被重新看一遍,然后让这个字段如实记下改动那一刻。它不是一个可以单独优化的开关,它只是一个记录仪——记录仪本身没有价值,它记的东西才有。 ## 常见问题解答 ## sitemap里的修改时间到底会不会影响排名? 不直接影响排名,它影响的是抓取的先后顺序。抓取方拿它决定先去看哪些地址,这个决定间接影响你的更新多久能被发现。规范里这个字段是可选的,写不写都不算错。但如果写了却写得不诚实,被识破之后这个信号在你站上就作废了,等于自己把一个免费的引导工具关掉了。 ## 怎么判断我站上的这个字段是不是假的? 最快的办法是隔十分钟把同一份地址清单抓两次,比对每条地址的时间。如果绝大多数条目都往前挪了十分钟,那它记的就是你请求的那一刻。实测样本里115个站有18个是这种情况,占15.7%。要用同样的请求身份抓两次,并且避开浏览器缓存,否则第二次可能拿的是本地副本。 ## 整份文件几千条地址共用同一个时间戳,一定有问题吗? 基本可以确定有问题。样本里带时间戳不少于50条的232份文件中,90份整份只有一个取值,占38.8%。真实的内容更新不可能这么整齐——它一定是长尾的,少数页面动、多数不动,时间戳会散布在过去几个月里。唯一的例外是那份文件本来就只装同一批同时上线的页面,比如一次性导入的活动页,这种情况在实践中很少见。 ## 这个字段常年不动,比每次都刷新更好还是更差? 两种都是废字段,区别只在观感。常年不动至少不会误导人,而每次都刷新会让维护的人以为它在正常工作。样本里有6个站的时间戳中位年龄超过180天,最久的停在4.3年前。判断自己属于哪一类只要两步:先看抓两次动不动,再看确实改过的页面有没有跟着动。两步都通过才算这个字段是活的。 ## 只写年月日不写时分秒,可以吗? 格式上完全合规,规范允许只写日期。但要注意它常常是同一个毛病的低配版——把分辨率砍到一天之后,仍然可能是每次生成时填当天日期。样本里12.7%的条目只精确到日期,其中不少属于这种情况。判断办法一样:隔一天抓两次,如果日期跟着换了而页面没改,那它记的还是生成时刻。 ## 索引文件那一层的时间要不要写? 可以不写。真要写就得保证它等于对应子文件里的最大修改时间,否则不如空着。实测70对可对账的声明里只有23对对得上,占32.9%,最离谱的一对差了1374天。脱节的原因通常是两层由不同的代码路径生成,谁也不看谁写了什么。子文件数量少的时候这一层无所谓;子文件成百上千时它会影响抓取方先读哪一份。 ## 响应头里的修改时间和sitemap里的,哪个更可信? 理论上响应头更接近服务端的真实状态,实践中它基本不存在——694个页面里只有13个带了这个字段,占1.9%。动态生成的页面服务端自己也说不清内容什么时候定稿,所以干脆不写。这就是为什么sitemap里的声明缺少一个独立来源可以对照,也是它长期以来没人查的根本原因。 ## 修这件事需要后端配合到什么程度? 最彻底的做法要动内容层:页面每次保存时写一个更新时间,导出清单时读它,这需要后台改字段。如果推不动,可以只在导出程序里做——把上一次导出的地址与时间存成快照,这次只有内容指纹变了的地址才更新时间,其余沿用旧值。后一种方案完全不碰业务代码,成本在于要存一份快照,适合作为第一步先落地。 ## 权威参考资料 ## robots.txt两条规则撞车,赢的不是先写的那条 - URL:https://zhangwenbao.com/robots-txt-rule-conflict-longest-match-audit.html - 分类:技术SEO - 发布:2026-08-19 | 更新:2026-08-21 - 摘要:明明写了Allow却没能放行,把它挪到Disallow前面也不管用。问题出在裁决依据是路径长度,不是行号。 - 关键词:robots.txt,技术SEO,独立站运营,抓取控制 > **TLDR**:摘要:把157份电商站的robots.txt按RFC 9309的规则跑了一遍,6571条代表路径里有2378条同时被Allow和Disallow命中,占36.2%,牵涉67个站。撞上之后谁赢,规范写得很死:路径写得更长的那条赢,长度一样才轮到Allow。我把每份文件的规则随机打乱五遍、跑了32815次判定,结论一次都没变——顺序在这件事上完全不起作用。可要是换成一部分老爬虫用的先命中先算读法,1644条路径的结论会当场反过来。另有296条Allow(占全部1113条的26.6%)删掉之后判定纹丝不动,它们放行的是本来就没被挡住的地址。 > 摘要:把157份电商站的robots.txt按RFC 9309的规则跑了一遍,6571条代表路径里有2378条同时被Allow和Disallow命中,占36.2%,牵涉67个站。撞上之后谁赢,规范写得很死:路径写得更长的那条赢,长度一样才轮到Allow。我把每份文件的规则随机打乱五遍、跑了32815次判定,结论一次都没变——顺序在这件事上完全不起作用。可要是换成一部分老爬虫用的先命中先算读法,1644条路径的结论会当场反过来。另有296条Allow(占全部1113条的26.6%)删掉之后判定纹丝不动,它们放行的是本来就没被挡住的地址。 八月中旬那几天,SEO圈子里传得最广的一条消息是OpenAI关于ChatGPT抓取器的一句表态 (https://www.searchenginejournal.com/openai-says-robots-txt-may-not-apply-to-chatgpts-fetch-bot/585864/):ChatGPT里由用户点击触发的那次抓取,robots.txt的规则可能不适用。争的是解释权——同一份文件,你当它是禁令,对方当它是给批量爬虫看的,而不是给某个人的一次点击看的。 这句话让保哥想起手头一批没跑完的数据。争解释权这件事,其实根本不用等到AI公司下场。同一份robots.txt,摆在同一个Googlebot面前,只要文件里有两条规则同时够得着一个地址,就已经存在两种以上说得通的读法了。而绝大多数写规则的人,从没读过那张裁决表。 所以我把两周前抓下来的那批文件重新翻了出来,写了一个严格照着RFC 9309实现的匹配器,把每一份文件里的每一条规则都当成一次庭审来跑。下面是结果。 ## 一份robots.txt里,两条规则撞上同一个地址有多常见? 先说清楚撞上指的是什么。robots.txt里的每一条Allow或Disallow,后面跟的都是一个路径模式。模式和模式之间没有任何互斥要求,写成什么样都合法。于是同一个地址完全可能被好几条规则同时匹配到,有的说放行,有的说拦下。 同一批157份文件我还量过另一件事,有多少条指令压根没有接收方在读 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)的比例比想象中高得多。 这份文件一旦写废了后果并不小,整站从谷歌搜索结果里消失的那类事故 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)多半就是从一行规则开始的。 ## 撞车不是语法错误,语法检查器一个字都不会提 这是这类问题最难被发现的原因。你把文件贴进任何一个robots.txt校验工具,它检查的是字段名拼没拼对、有没有写在User-agent组里面、路径是不是以斜杠开头。这些全过了,工具就说没问题。 这类只查表面不查逻辑的毛病到处都是,页面结构分析工具能揪出的六个维度短板 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)也是同一种边界。 生成器给的预设也未必跟规范对齐,通配符判定会和标准打架的那几种情形 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)值得在照抄之前先看一眼。 但校验器不会告诉你:第14行那条Allow,和第112行那条Disallow,管的是同一批地址,而且第112行赢了。它甚至没有这个概念——单看每一行,两行都是完全正确的规则。 这就把问题推到了一个很尴尬的位置。语法层面有工具兜底,逻辑层面没有;而真正会让页面掉出索引、让抓取预算白烧的,全是逻辑层面的事。前者是几秒钟就能查完的东西,后者需要有人坐下来把整份文件想一遍,于是它永远排在待办清单的最后。 顺带说一句,这也是这类问题在SEO工具报告里长期缺席的深层原因。工具的商业逻辑要求每一条发现都能落到一个具体位置、给出一个具体动作;而规则冲突给不出这两样,它只能说这一组规则的合并效果和你的预期可能不一致,然后把判断权交回给人。这样的结论没法做成告警,也没法做成评分,于是它就消失了。 ## 157份文件的口径是怎么定下来的 样本来自一批做得比较成熟的海外电商与消费品牌站,抓取时间是2026年8月16日。抓回来的原始响应有198份,但能进分母的只有157份。中间剔掉了两类:一类是抓取记录里状态码不是200的,服务器把403、429的错误页面也写进了文件;另一类是状态码给了200、内容却是一整页HTML的,那是边缘防护返回的拦截页,不是规则文件。 用别人的工具之前更该先校准口径,第三方数据到底准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 同一批样本上做过的另一项实测是,给单个爬虫开组会丢掉通配组全部规则 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html),中招比例高得离谱。 这个口径我上一批就踩过一次坑:拿目录里的文件数当分母,数出来是161,比真值多了4份。分母必须从抓取记录里的状态码清单来建,不能从落盘的文件来建。 多说一句为什么必须这么较真。这类文章里所有的百分比都挂在分母上,分母虚高4份,每个比例都会被系统性地压低两三个百分点。单看一个数字察觉不出来,但如果拿它和别的批次做对比,趋势就假了。分母是整篇文章的地基,地基歪一厘米,屋顶歪一米。 还有一个细节值得提前说明:本文所有统计都以Googlebot为观察对象,换成别的爬虫名字重跑,分组结果会不一样,数字自然也会变。之所以选它,是因为它是唯一能在官方后台里当场验证判定结果的对象,别的爬虫我没有办法核对自己的解析器算得对不对。这也是做这类普查时的一条原则:能被独立验证的口径,优先于看起来更全面的口径。 ## 只看对Googlebot生效的那一组 还有一层筛选容易被忽略。robots.txt是按User-agent分组的,一个爬虫只会执行它匹配到的那一组,别的组的规则跟它没关系。所以统计之前,我先对每份文件跑了一次分组选择:有没有专门写给Googlebot的组?有就只用那一组;没有才回落到通配组。 分组之外还有例外条款要留意,通配组的星号对广告爬虫不生效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)是最容易被漏掉的一条。 要弄清对面到底是谁再谈规则,120种爬虫标识的分类与真假验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)是一份可以直接照做的清单。 157个站里有22个给Googlebot单开了一组。剩下的135个走通配组。最后进入统计的规则是5494条Disallow加1113条Allow,中位数是每站41条,最多的rituals.com写了324条,最少的一条都没写。 如果跳过这一步,直接把文件里所有的Allow和Disallow一锅端进统计,得到的数字会大得多,但那个数字不对应任何一个真实爬虫的处境。它是一份文件的总字数,不是任何一个读者读到的内容。这两件事在robots.txt里差得非常远,因为分组之间是互斥的,不是叠加的。 ## 6571条代表路径,2378条撞车 怎么判断一条规则会不会跟别的规则撞上?我的办法是给每条规则生成一个代表路径:把路径里的星号换成一段不会撞车的字符,去掉结尾的美元符号,得到一个这条规则一定能匹配的具体地址。然后拿这个地址回头去问整组规则:有多少条能匹配它? 需要被挡住的地址里最难缠的是筛选组合,分面导航产生的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)我单独拆过一遍。 这几千条禁止规则最终服务的目标是预算,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)按优先级排过一次序。 去重之后一共6571条代表路径。其中2378条被至少一条Allow和至少一条Disallow同时命中,占36.2%,分布在67个站上。也就是说,每三个地址里就有一个处在两条规则的交叉火力下。 口径 | 数值 | 说明 | 进入统计的站 | 157 | 抓取记录状态码为200且内容不是HTML | Disallow条数 | 5494 | 只算对Googlebot生效的那一组 | Allow条数 | 1113 | 写过Allow的站74个 | 代表路径 | 6571 | 每条规则生成一个,去重后 | 撞车路径 | 2378(36.2%) | 同时被两类规则命中 | 涉及站点 | 67 | 占样本的42.7% | 这张表里最值得盯住的是第三行和第五行的关系。1113条Allow分布在74个站,而撞车路径有2378条分布在67个站——撞车数远多于Allow数,说明一条Allow平均会跟两条以上的Disallow发生交叠。精细放行从来不是一对一的,你放行一个地址,实际上是在跟一整片禁令区域谈判。 另一个容易被忽略的口径问题是去重。6571条代表路径是去重后的数字,去重前是7000出头,差额来自同一份文件里写了两遍的规则。去重这一步必须做,否则重复规则多的站会在统计里获得双倍权重,把整体比例往它那边拽。 ## 剩下90个站为什么一次都没撞 因为它们压根没写Allow。1113条Allow集中在74个站手里,另外83个站的文件里全是Disallow。没有Allow就不存在放行与拦截的对撞,所有地址的命运只有一条路:被某条Disallow匹配到就是拦,匹配不到就是放。 筛选参数该怎么分类处理是个老问题,五类过滤器参数的处理方式对比 (https://zhangwenbao.com/ecommerce-category-page-filters-seo-tips.html)给了可以直接抄的表。 至于哪些页面真的该挡,电商该屏蔽的七类页面与Shopify实操 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)里有逐类的判断依据。 这也解释了一个现象——撞车集中在那些看起来最讲究的文件里。写Allow说明这个人知道robots.txt有精细控制的能力,而恰恰是这批人最容易掉进裁决规则的坑。什么都不写的反而不会错。 这个结论有点反直觉,也不该被拿去当成不作为的借口。它真正说明的是:能力越强的工具,误用的代价越大。Allow这个字段的存在意义就是在大范围禁止里开一个小口子,而开口子这件事本身要求你精确知道禁止的边界在哪——大多数人并不知道,因为那条禁令往往不是他写的。 这里还藏着一个容易被当成好消息的坏消息。83个站一条Allow都没写,说明它们的规则是纯粹的黑名单模式——凡是没被禁的都放行。这种模式确实不会内部打架,但它同时意味着这些站从来没有做过精细控制:所有的筛选参数、所有的会话地址、所有的打印版页面,要么被一条粗规则整片挡掉,要么完全不管。粗糙和无冲突是同一件事的两面。 另外值得一提的是,这83个站里有不少是规模相当大的品牌。规模和精细度之间并没有必然联系——决定要不要写Allow的,往往只是当年建站那个人的习惯,以及之后有没有人真正接手过这份文件。 ## rituals的324条规则是怎么堆出来的 规则最多的那个站值得单独看一眼。324条里有78条Allow,撞车路径135条——一个站就占了全样本撞车量的5.7%。翻开文件能看出堆叠的痕迹:先是一批按语言前缀写的目录禁令,然后是一批带查询参数的过滤规则,再往后是一批针对具体促销活动页的临时补丁。 资深团队反而更容易栽在结构性问题上,被忽略的那几类技术SEO失灵原因 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的就是这种局面。 这类没人报错的欠账攒起来相当可观,技术债怎么排查和分批偿还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了一套可执行的顺序。 这种文件不是某一天写成的,是三四拨人隔着几年往上叠的。每一拨人只看自己那几行对不对,没人跑过整份文件的合并效果。而合并效果恰恰是爬虫唯一会看的东西。 顺着这条线还能看出一个组织问题。促销活动页的补丁说明写规则的人是运营,语言前缀的禁令说明写规则的人是国际化团队,参数过滤说明写规则的人是技术。三拨人共用一个文件、没有共用的评审,这个文件的最终行为就成了没有人负责的东西。 ## 撞车率高的站,有一个共同的组织特征 把67个撞车站和90个零撞车站放在一起对比,能看出一条界线:撞车站几乎全是有独立技术团队、做过国际化、上过筛选导航的中大型站;零撞车站要么规模小、要么全站结构极简。这不是能力差异,是复杂度差异。 推不动改动往往不是技术问题,甲方拒绝SEO建议八成源于身份冲突 (https://zhangwenbao.com/enterprise-seo-evolutionary-framing-eight-steps-rebuild.html)给了一套重写汇报的办法。 跨团队协作这件事有具体抓手,后端工程师配合SEO的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)是从二十二周账本里总结的。 复杂度带来的不只是规则变多,还有决策链变长。一条禁令从提出到写进文件可能经过运营、SEO、前端三道手,每道手都对它做了一点修改,最终那一行长什么样谁也说不准。而裁决只看最终那一行。 ## 撞上的时候,规范说谁赢? 这就是整件事的核心。答案在RFC 9309关于规则优先级的条款 (https://www.rfc-editor.org/rfc/rfc9309.html)里,一句话:匹配到的规则里,路径写得最长的那条生效;如果最长的有好几条且方向相反,Allow赢。 涉及取舍的场合还有一张速查表,301、302、404和410各自该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)能省掉不少争论。 这件事该用哪个手段也常被搞反,robots.txt和meta robots各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)里分工写得很清楚。 ## 比的是字符数,不是行号 规范里比的是规则路径的字符长度,跟它写在文件的第几行毫无关系。这一点和绝大多数人的直觉是反的。程序员看到一组规则,第一反应通常是防火墙那套——从上往下匹配,先命中先返回;或者反过来,后面的覆盖前面的。robots.txt两条都不是。 配置每次reload都通过不代表没事,Googlebot每八次抓取就有一次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类隐形代价。 服务器上那些数值型配置同样值得逐条问一遍,服务器配置影响SEO的二十项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着核对。 举个最直白的例子。文件里写着Disallow: /products/ 和Allow: /products/sale/,那么/products/sale/summer这个地址会被放行,因为Allow那条的路径长了6个字符。把两行的位置对调,结果完全一样。 为什么规范要这么设计,其实有道理可讲。robots.txt是给成千上万个互不相识的实现去读的,如果裁决依赖顺序,那么任何一次编辑器的自动排序、任何一次配置管理工具的合并,都可能悄悄改变整个文件的语义。用长度做裁决依据,文件就成了一个跟排列无关的集合,这对分布式的、无人对账的场景是更稳的选择。 ## 长度一样的时候才轮到Allow优先 规范给的第二条裁决是:长度打平时,允许优先于拒绝。这条在真实文件里几乎用不上——我在157份文件里找同一路径既写Allow又写Disallow的情况,一处都没找到。没人会那么写,因为那看起来太明显是自相矛盾了。 把它当访问控制的代价有多大,测试站被谷歌索引后的八步清除与四层防御 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)是最直观的样本。 真要拦住某类程序得分层做,robots、UA识别、WAF三层的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比只改一个文件靠得住。 真正吃掉人的不是打平,是差一两个字符的那种。差一个斜杠、多一个星号,胜负就换了边。 这条规则还有一层现实含义:当你不确定该不该放行时,规范的默认倾向是放行。robots.txt从设计上就不是一个安全机制,它是一份君子协定,遇到歧义时倾向于让内容被看到,而不是倾向于藏起来。把它当访问控制来用的人,都会在这一点上吃亏。 说到这里得澄清一个常见的误解。有人以为robots.txt的默认倾向是禁止,理由是这个文件叫排除协议。恰恰相反:没有任何规则命中的地址一律放行,这是规范写死的行为。文件叫排除协议,是因为它的用途是排除,不是因为它的默认值是排除。 这个默认值决定了很多事情。它意味着你不写规则的地址全都是开放的,也意味着规则文件损坏、返回500、或者被防护挡住时,爬虫的行为不是保守地全站不抓——各家实现不同,有的会沿用上一次缓存的版本,有的会当成没有规则从而全站放行。想清楚这一点,就不会把robots.txt当成访问控制来用了。 还有个更实际的问题:这个默认值意味着遗漏的成本远高于写错的成本。你少写一条规则,那片地址就是全开放的;你写错一条规则,最多是挡错了地方。所以做审计时该先查有没有该挡没挡的,再查有没有挡错的——两者的排查顺序不该反过来。 ## 2378次对撞,Disallow赢了65.2% 把这2378条撞车路径逐条判决,结果是Disallow赢1551次、Allow赢827次。也就是说,三分之一的对撞里,那条Allow是真的起了作用,把一个本来会被挡住的地址救了回来。 解释不同会直接反映到报告上,抓取报告里五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你分清是谁的问题。 挡与不挡最终都会落到索引规模上,大量无用页面拖垮流量的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 裁决结果 | 条数 | 占比 | 含义 | Disallow胜出 | 1551 | 65.2% | 写Allow的人没能达到目的 | Allow胜出 | 827 | 34.8% | 精细放行确实生效了 | 要留意的是,Disallow赢的那1551次并不都是事故。很多情况下人家本来就想让那个地址被挡住,Allow匹配上纯属副作用。真正需要人去看的是另一批:写Allow的时候心里想的就是这个地址,结果它没赢。这批混在1551条里,只能靠人工判断意图才能分出来。 还有一件事这张表看不出来:胜负是按路径统计的,不是按流量统计的。一条被误挡的商品列表页和一条被误挡的测试页,在表里各算一条,实际价值差着好几个数量级。所以看完比例之后,务必回头按业务重要性把那些地址排一次序——绝大多数站真正需要处理的,就是排在最前面的那三五条。 ## Allow赢下来的那些地址长什么样 看几个真实的。aboutyou.com把带各种筛选参数的地址全禁了,然后单独放行了商品详情页上的两个参数,规则写成Allow: /p/*?*firstProductId= 这样。它比通配的Disallow: /*?*firstProductId= 多了三个字符,赢得干净利落。 同一商品的几十个地址该合还是该拆,产品变体的URL与索引策略 (https://zhangwenbao.com/product-variant-seo-url-canonical-indexation-strategy.html)需要先想清楚再写规则。 这类参数地址到底该不该写禁令,电商筛选URL的三类判别法 (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)给了处理策略而不只是结论。 aloyoga.com那组更典型:Disallow把带account、orders、checkout的地址全挡了,再用Allow: /products/account这类规则把商品目录下同名的东西放回来。这些都是真正读懂了裁决规则的写法。 值得注意的是这两组Allow赢得都很险——多出来的只有三到七个字符。这意味着它们非常脆弱:哪天有人把那条Disallow写得更具体一点,胜负立刻反转,而且没有任何地方会报警。把关键放行做成这种一线之差的写法,等于把生意押在别人不会动那一行上。 这两组写法还有个共同点:它们都出现在参数层面而不是目录层面。目录型的放行几乎不会赢,因为目录名通常比通配规则短;参数型的放行经常赢,因为参数名本身就长。想让一条Allow稳稳生效,把它写在尽可能具体的那一层,是唯一可靠的办法。 ## 换一种长度算法,结论会变吗 我顺手做了个对照实验。有人猜测比长度时通配符不该计入,毕竟星号只是一个占位符。于是我用去掉星号和美元符号之后的字面长度重新判了一遍这2378条。 做对照组这件事经常能救命,量出七成页面有差异、补上对照组后只剩两个点 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)就是一次返工。 同一个数字各家算法不同这件事到处都是,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 结果是零条改判。这个变量在真实数据上完全不敏感——因为带通配符的规则和不带的,长度差距通常远大于一两个符号。这是个负面结果,但它有用:说明你不用纠结这一点,把星号算进去还是不算进去,答案都一样。 做对照实验的价值也在这儿。一个猜想被数据否掉,比一个猜想被数据支持更省事,因为你从此可以不再考虑这个变量。可惜大多数人只在结果符合预期时才把实验写出来,于是零结果永远没人报告,后面的人接着猜。 把这两条结论合起来看,能得到一个很朴素的操作建议:写Allow之前先确认它有对手,写完之后再确认它赢得下来。两件事都只需要一次判定就能验完。 ## 把裁决规则记成一句话 如果只想记一条,就记这句:谁写得具体谁说了算,一样具体的时候放行说了算。它比最长匹配这个术语更好传达,因为具体这个词天然对应着人的直觉——你专门为某个地址写的规则,当然应该压过那条大而化之的通配规则。 一堆问题先修哪个得有依据,五百个站实测排出来的技术SEO优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)可以当排期底稿。 规则要能传达给非技术同事才有用,内容、技术、外链三类分工与团队配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)也是同一个协作问题。 把这句话交给团队里非技术的同事,他们也能判断自己提的那条需求会不会生效。判断不了的那些,正好是需要坐下来一起看的那些。 ## 把规则顺序整个打乱,结论会跟着变吗? 这是本批最让我自己意外的一次验证。既然规范说裁决只看长度,那顺序理论上就该完全无关。理论归理论,我决定直接拿数据砸一遍。 口径不清的指标最容易误导判断,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭自己的框架。 验证一条建议有没有效有个笨办法,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)比讲道理管用得多。 ## 实验设计:每份文件洗牌五次 做法很简单。对每一份文件,先按原顺序把所有代表路径判一遍,存下结论;然后把规则数组随机打乱,再判一遍,逐条比对;重复五次。全部157个站跑下来,一共比对了32815次。 想知道某个动作到底有没有增量,别让本来就会买的人冒领功劳 (https://zhangwenbao.com/incrementality-testing-marketing-measurement-guide.html)那套测法值得借鉴。 抽样口径直接决定结论真假,孤岛页面检测的抽样口径怎么定 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)是同一类方法论问题。 之所以要洗五遍而不是一遍,是因为一次洗牌有可能碰巧没改变关键规则的相对位置。五次独立洗牌把这种巧合的概率压到可以忽略,同时又不至于让脚本跑太久。随机种子写死在脚本里,任何人拿同一份数据都能得到一模一样的结果。 ## 32815次比对,零次改变 一次都没变。这在实验里是最干净的一种结果——它把规则顺序影响结果这个流传很广的说法彻底钉死了。你把Allow写在最上面还是最下面,把新规则追加在文件末尾还是插在中间,对按规范实现的爬虫来说没有任何区别。 这类小脚本自己写最快,用Vibe Coding做SEO小工具的八步避坑 (https://zhangwenbao.com/vibe-coding-seo-tool-tutorial.html)讲的就是这种自养工具。 能被机器批量验证的事就别靠人记,哪些SEO工作能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条边界。 顺便说,这也意味着一类常见的优化是白做的:有人为了让某条Allow生效,特意把它挪到对应的Disallow前面。挪了等于没挪。真正该做的是把那条Allow的路径写得更长更具体。 这条结论还有个用得上的地方:既然顺序不影响语义,那么你可以放心地对文件做排序、去重、分组重排,只要不改动规则本身的字符内容,行为就不会变。这让robots.txt具备了可以被自动化整理的性质——很多团队不敢碰这个文件,怕一动就出事,其实动的是排版就完全没风险。 ## 但换一种读法,1644条会当场翻盘 顺序无关只在按规范实现的解析器里成立。我又实现了另外两种读法做对照:一种是先命中先算,从上往下扫,第一条匹配上的规则说了算;另一种是后写的覆盖先写的,扫到最后一条匹配的为准。 判断对面是哪一代程序只能看日志,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)那套挖法可以直接套用。 名单上那些名字有没有真来过也能量,266个爬虫令牌里只有23.3%真的来过 (https://zhangwenbao.com/crawler-ua-list-named-vs-real-visits-audit.html)是另一组实测。 用第一种读法,1644条路径的结论和规范读法不同,牵涉60个站;用第二种,667条不同,牵涉48个站。60个站是什么概念——样本里38.2%的站,命运取决于对面那个爬虫是哪一年写的。 读法 | 裁决依据 | 与规范读法的分歧 | 涉及站点 | 最长匹配(RFC 9309) | 路径字符数,打平时Allow优先 | 基准 | — | 先命中先算 | 从上往下第一条匹配的 | 1644条 | 60 | 后者覆盖前者 | 从上往下最后一条匹配的 | 667条 | 48 | ## 分歧最集中的几个站 nespresso.com一个站就贡献了84条分歧,rituals.com 52条,接下来是一长串各40条的站——这批站的文件内容高度相似,一看就是同一个平台生成的模板。模板这件事后面单独说。 选平台时就该问清楚默认配置,SaaS托管、自建还是纯代码怎么选 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)把各自的代价摊开了。 模板生成的东西撞车是常态,插件和主题各冒出一套canonical怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一类清理。 模板站的分歧数完全一致这件事本身就很能说明问题:它们不是各自写错了,是同一个错误被复制了几十份。追责的话,责任在生成模板的那一方;但承担后果的是每一个店主,而且他们连这份规则长什么样都没看过。 ## 哪种读法才算合规,这事有过变化 2019年之前,robots.txt根本没有正式标准,只有1994年的一份非正式共识文档,那份文档里没有Allow,也没有通配符。所以早年的爬虫按什么顺序算全凭实现者自己决定,先命中先算是当时很常见的一种做法。RFC 9309是2022年9月才发布的,它把最长匹配写成了规范要求。 想靠这个文件拦训练数据更不够用,内容进入模型的四条路 (https://zhangwenbao.com/ai-training-data-four-paths-robots-txt-limits.html)在一份诉讼材料里被摊开过。 同一家公司的抓取器也不都守同一套规矩,有一整类抓取器压根不看robots.txt (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)这次改名把它推到了台前。 这意味着一件很现实的事:你面对的爬虫如果是这三年内写的,大概率按规范走;如果是十年前那批还在跑的老程序,它按什么算你无从得知,也没法要求它改。 这里有个判断上的分水岭值得记住。主流搜索引擎和主流AI公司的抓取器基本都跟着规范走,因为它们有明确的合规压力;真正按老规矩跑的,是那些没人维护的采集脚本、监控工具、以及各种一次性写完就长期在线的小程序。而这批程序恰恰不是你想放行的对象,所以规范分歧的实际损失,通常小于它听上去的可怕程度。 ## 顺序不重要,但注释的位置很重要 既然顺序对机器没意义,那它就只对人有意义了。这反而提高了排版的价值:把相关的规则放在一起、用注释行分段、按功能而不是按时间组织,能显著降低下一个人读错的概率。 把口头约定写成文字这件事永远划算,达标定义、违约责任与四类经典纠纷 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)是另一个场景的同一道理。 多人共同维护一份规则文件要立规矩,共享与个人怎么分、规则冲突听谁的 (https://zhangwenbao.com/claudemd-team-collaboration.html)是一套可搬用的做法。 注释行以井号开头,爬虫会整行忽略,写多长都不影响解析。样本里用注释做分区的站不到三分之一,而这批站恰好也是撞车最少的那批。相关不等于因果,但至少说明肯写注释的人通常也肯把整份文件读一遍。 ## 写下去的1113条Allow,有多少条其实没起作用? 撞车至少说明Allow参与了裁决。更尴尬的一类是:这条Allow压根没进裁决现场。 有些地址连声明的地方都没有,接口和feed拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)是同一类结构性缺口。 写了放行也未必等于对方进得来,robots说允许、仍有十个站把GPTBot挡在门外 (https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html)是另一层错位。 ## 判定方法:把它删掉,看结论变不变 逐条Allow做一次删除实验。先按完整规则集判它的代表路径,再把这条Allow从规则集里拿掉重判一次。两次结论一样,就说明这条规则的存在与否对结果毫无影响——它是空转的。 在线上做实验要先想好清理,A/B测试怎么做才不影响SEO (https://zhangwenbao.com/ab-testing-page-seo.html)里有Google的表态和收尾动作。 判断一样东西该不该留有个通用问法,用第一性原理做工具选型 (https://zhangwenbao.com/seo-tools-martech-replacement-trend-2025.html)说的就是删掉会不会出事。 这个判据比有没有被别的规则覆盖更严格,也更贴近真实价值:一条规则的价值就在于删掉它会不会出事。 这个思路可以推广到任何配置文件。判断一行配置有没有用,最可靠的办法不是读它、不是问写它的人,而是把它拿掉再跑一遍观察输出。能这么验的东西,就不该靠读代码去猜。 ## 296条空转,占全部Allow的26.6% 1113条Allow里,817条有效,296条空转,空转率26.6%。四分之一强。 结构化数据里也有大量白写的字段,112个独立站里17个在犯的商家名称错误 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是一份对照。 写了不等于有效这件事在别处也成立,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)量的是同一种落差。 换个角度看这个数字:74个站写了Allow,其中58个站至少写过一条空转的。也就是说写过Allow的人里有将近八成,至少有一次以为自己在放行什么,实际上什么也没做。这个比例比条数比例更能说明问题,因为它衡量的是人而不是行。 ## 空转的原因几乎只有一种 我原本以为空转会分成好几类,其中最惨的一类是写了但输了——被一条更长的Disallow压过。实际数据把这个猜想否掉了:被更长Disallow压过的Allow是零条。 有些声明本来就只是提示不是命令,canonical是提示不是指令的八种误用 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html)解释了为什么它常常不生效。 两种手段能不能一起用是个高频疑问,noindex和canonical同时用的九种场景怎么判断 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)逐个给了答案。 296条里,285条属于根本没人挡它:这条Allow放行的地址,整份文件里没有任何一条Disallow够得着。robots.txt的默认状态本来就是允许,所以这条规则等于在说请允许一件本来就被允许的事。剩下的11条里,2条是与另一条更宽的Allow重复,9条是几种边角情况。 空转成因 | 条数 | 站数 | 解释 | 没有任何Disallow够得着 | 285 | 58 | 默认就是允许,这条纯装饰 | 与另一条Allow重复 | 2 | 1 | 更宽的那条已经覆盖了 | 其它边角情况 | 9 | — | 空路径、根路径等 | 被更长的Disallow压过 | 0 | 0 | 真实数据里一例都没有 | 零这个结果还有一层含义值得展开。它说明真实世界里的Allow和Disallow并不是在同一片区域里贴身肉搏,更多时候它们各写各的,压根不在一个战场上。人们写Allow时想的是一个具体地址,写Disallow时想的是一整类地址,两种思维方式产生的路径长度天然就不在一个量级——具体的那条几乎总是更长,所以Allow只要真的撞上了,赢面就不小。 这也反过来解释了为什么空转率会高达26.6%。既然Allow通常写得比Disallow更具体,那它要么赢,要么根本没对手。没对手的那种就是空转,占了绝大多数。 ## 45个站写了Allow: / 空转里最好认的一种是Allow: /,也就是放行整个站。157个站里有45个写了这一行。它当然不会有任何效果,因为没有这行的默认状态就是全站允许。 不同页面类型该给什么声明有差别,五类页面的meta robots与canonical配置差异 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)可以直接照搬。 虚拟文件和物理文件谁优先也常被搞混,WordPress的robots.txt该怎么写 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)把这两层的优先级讲清楚了。 这一行为什么会出现?多半是从某份模板抄来的,抄的人觉得先声明允许再逐条禁止比较符合直觉。这个直觉在防火墙配置里是对的(默认拒绝,所以要显式放行),在robots.txt里是反的。 更麻烦的是这行会误导后来的人。看到文件开头写着Allow: /,很容易以为下面的Disallow都是在这条总放行的基础上做例外,进而以为删掉某条Disallow就会回到全放行状态。这个理解链条每一环都对,唯独起点那条规则是虚的。 还有一类空转值得单独认一下:写给某个具体文件的Allow,比如放行某张图片或某个脚本。这类规则的出发点通常是担心页面渲染所需的资源被挡住,导致搜索引擎看到的页面是残缺的。担心本身完全正确,但如果整份文件里根本没有一条Disallow够得着那个资源目录,这条Allow就是纯粹的心理安慰。 正确的做法是反过来查:先确认渲染必需的那些资源有没有被某条规则挡住,挡住了才需要写Allow放行。从担心出发写规则,写出来的十有八九是空转的;从实测出发写规则,写出来的每一条都有对手。 ## 空转不等于有害,但它是个信号 说句公道话:296条空转的规则不会造成任何损失,爬虫读到它们只是多花几微秒。真正的代价是别的——它们让文件看起来比实际更精细,让下一个接手的人以为这些地址有特殊安排,也让审计的人多花时间去理解一件根本不存在的意图。 渲染必需的资源被挡会直接丢内容,抓取和渲染DOM分几步、哪一步会丢东西 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)讲得比较完整。 担心资源被挡住是常见动机,Googlebot为什么不读你的preload (https://zhangwenbao.com/why-googlebot-ignores-resource-hints.html)说明了哪些提示其实无效。 更值得警惕的是它反映的心理状态:写这些规则的人以为自己在做精细控制,实际上没有跑过一次合并判定。同一批人写的那些真正参与裁决的规则,出错概率也不会低到哪去。 所以我一般不建议客户去删这些空转的行——删掉省不下什么,还可能删错。建议做的是在每条旁边加一句注释,写清楚它是哪年为什么加的。注释不会被爬虫读,但会被下一个人读,而下一个人才是这份文件真正的风险来源。 ## 一个星号写进去,这份文件还是同一个意思吗? 通配符是robots.txt里最晚被正式承认的东西,也是分歧最大的东西。5494条Disallow里有3591条带星号,占65.4%;1113条Allow里有732条带星号,占65.8%。三分之二的规则依赖一个在1994年那份原始共识里并不存在的语法。 参数类地址还有专门的处置方案,URL里那个srsltid参数的四种处置办法 (https://zhangwenbao.com/google-srsltid-parameter-seo.html)是一份现成对照。 拿这个文件去解决它管不了的事很常见,用robots.txt拦UTM参数的危害 (https://zhangwenbao.com/robots-txt-disallow-utm.html)就是一个典型。 ## 规范要求支持,但规范只管得了2022年之后 RFC 9309明确写了:解析器必须支持星号表示任意长度的任意字符,必须支持行尾的美元符号表示路径结束。这是硬性要求,写进了规范的正文而不是附录。 真正吃掉带宽的那批已经换人了,AI爬虫抓取量超过Googlebot好几倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)改变了很多决策的优先级。 把日志按对象拆开看会很清楚,八类爬虫标识的二十二周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)是一份可对照的样本。 问题在于规范2022年才发布,而互联网上跑着的爬虫程序有相当一批比它老得多。一个2015年写的抓取脚本不会因为2022年出了份RFC就自动学会通配符,它只会把星号当成一个普通字符,去做前缀匹配。 这类程序的数量还不算少。前一批我翻了本站59天的访问日志,光是自称爬虫的标识就有401个不同的串,其中相当一部分是各种监控工具、采集脚本、外链分析器留下的。它们绝大多数不会更新,也没有人对它们的合规性负责。 它们里面还有一批更尴尬的存在:那些号称支持robots.txt、实际只实现了一半的商业工具。做站点审计的桌面爬虫、做外链分析的采集器、做价格监控的比价程序,都会读这个文件,但读的深度参差不齐。你在报告里看到的可抓取判定,取决于那个工具的作者当年读到规范的哪一版。 ## 把不支持通配符的读法跑一遍,3535条判定变了 我实现了第三种解析器:星号和美元符号都当字面字符,规则匹配退化成朴素的前缀比较。用它重跑6571条代表路径,有3535条的结论和规范读法不一样,牵涉133个站——占样本的84.7%。 各家工具读同一个页面结论未必一致,十款技术栈检测扩展的实测对比 (https://zhangwenbao.com/seo-website-technology-stack.html)能看出差异有多大。 桌面爬虫能覆盖的范围有边界,桌面爬虫能查出的十二类问题清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)可以对照看缺了哪一块。 这个数字比前面的顺序分歧大得多,原因也直白:一条Disallow: /*?*price_max= 在支持通配符的爬虫眼里能挡住全站带这个参数的地址,在不支持的爬虫眼里只能挡住路径真的以斜杠星号开头的那几个地址——而这样的地址一个都不存在。规则从挡一大片直接变成什么都不挡。 解析器行为 | 受影响路径 | 站点数 | 占样本 | 不支持通配符(退化为前缀匹配) | 3535条 | 133 | 84.7% | 先命中先算 | 1644条 | 60 | 38.2% | 后者覆盖前者 | 667条 | 48 | 30.6% | 三种分歧的性质并不一样。顺序分歧是双向的——有的地址从挡变成放,有的从放变成挡;通配符分歧几乎是单向的——绝大多数是从挡变成放。所以后者的实际风险更明确:你以为挡住的那些筛选页、搜索结果页、打印版页面,在这批老程序面前是敞开的。 还有一个方向的分歧这张表没列:对同一条规则,不同解析器在通配符的贪婪程度上也可能不一致。星号该匹配尽可能长的一段还是尽可能短的一段,在最长匹配的裁决框架里通常不影响结论,但在带美元符号的规则里会。这一类差异我没有在真实文件里找到能触发的例子,所以没有单独统计,只作为已知边界记在这里。 顺带一提,这三个数字的分母都是6571条代表路径,不是页面数。一个站可能有几十万个真实地址落在同一条规则下,也可能一个都没有。所以这里量的是规则的脆弱程度,不是流量的暴露程度,两者需要分开谈。 ## 受影响最重的是参数拦截那一类 nespresso.com有128条、rituals.com 100条、osprey.com 95条。翻开这几个站的文件,密集出现的都是同一种句式:斜杠星号问号星号加一个参数名。这是拦截筛选参数的标准写法,也是最依赖通配符的写法。 站内搜索地址到底该不该禁,四种方案的对比与适用场景 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)讲清了各自的副作用。 参数这件事在内链上也有代价,给内链加UTM参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)是流量分析与抓取的取舍。 换句话说,各家为了控制抓取预算写得最用力的那部分规则,恰好是在老爬虫面前最容易整段失效的部分。而抓取预算被吃掉这件事,通常正是老爬虫和小爬虫干的。 这就形成了一个很拧巴的局面:规则对守规矩的搜索引擎完全有效,对不守规矩的采集程序完全无效,而你想拦的恰恰是后者。robots.txt作为一个协作机制,本来就只对愿意协作的人有用,通配符这一层只是把这个特性放大了一次。 ## 美元符号只有26条,说明大家都不太敢用 行尾的美元符号表示路径到此为止,用来精确挡住某个具体地址而不误伤它下面的子路径。157份文件里只有26条规则用了它。这个数字低得有点反常——考虑到很多站都想挡住某一个具体页面而不是一整个目录。 路径本身的写法也有讲究,影响抓取与排名的九个URL细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)是一份实操清单。 地址结构决定了规则好不好写,扁平URL和层级URL在SEO上到底差在哪 (https://zhangwenbao.com/flat-urls-vs-hierarchical-urls-for-ecommerce-sites.html)值得在改版前想清楚。 我的判断是大家心里没底。星号至少直觉上好理解,美元符号涉及匹配是从头开始还是必须整段相等这层语义,写错了后果是挡多了,风险不对称,所以宁可不写。 不写的代价是精度。想挡住/search这个页面本身、又不想挡/search-tips,正确写法是Disallow: /search$ 加一条;不用美元符号就只能靠祈祷没有别的路径以search开头。样本里确实有站因此把内容页一起挡了。 还有一件事值得说明:这26条美元符号规则里,有几条写在了路径中间而不是末尾。规范只承认行尾的美元符号有特殊含义,写在中间的会被当成普通字符处理。写的人多半以为它是某种分隔符,结果那条规则匹配的是一个真的带美元符号的地址——那样的地址当然不存在。 ## 星号写在开头的那批,其实是多余的 还有个细节值得提。robots.txt的路径匹配天生就是前缀匹配,从路径的第一个字符开始比。所以写Disallow: /*/search和写Disallow: /*/search没区别,但很多人会写成Disallow: */search,少了开头的斜杠。 真出语法级问题时症状反而很明显,一个看不见的字节头就能让页面白屏 (https://zhangwenbao.com/notepad-edit-saved-code-generate-bom-resulting-web-page-error-white-screen-solution.html)是另一种极端。 同样的沉默在结构化数据里更狠,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)而页面照样正常显示。 按规范,路径必须以斜杠开头,不以斜杠开头的值行为未定义。Google的解析器会给它补一个斜杠,别家未必。这是又一处两种读法都说得通的地方。 类似的还有Disallow: /*,它跟Disallow: /在语义上完全等价,都是全站禁止,但看上去像是在做某种通配。样本里没人这么写全站禁止,倒是有不少人在路径中间加了不必要的星号,让规则变长了几个字符——而长度正好是裁决依据,所以这几个多余的星号是有实际后果的。 ## 要不要为老爬虫单独写一套规则 知道通配符在老程序面前会失效之后,一个自然的想法是:那我把不带通配符的等价规则也写一份,两套并存。这个做法技术上可行,代价是文件长度翻倍、撞车概率同步上升。 边缘防护的效果也没那么确定,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测出来的答案挺意外。 在服务器上动手要防误伤,拦AI爬虫与限速怎么不把Googlebot一起拦掉 (https://zhangwenbao.com/nginx-ai-bot-blocking-rate-limit-rdns-misblock-account.html)有具体的匹配写法。 我的建议是别做。真正会读robots.txt又不支持通配符的程序,数量和危害都不足以让你把文件复杂度翻一倍。要防的话,防在服务器层更直接——按UA或者按请求特征限速,比在一份君子协定里反复叮嘱有效得多。 ## 路径里的大写字母、美元符号和百分号,谁最容易让规则落空? 通配符是明面上的分歧,还有一批分歧藏在更细的地方:大小写、编码、以及路径末尾那个斜杠。这三样都不会触发任何警告,但它们会让一条规则彻底匹配不到任何东西。 编码这件事历史上吃过大亏,搜索引擎抓回去的不是俄语而是一串认不出的字母 (https://zhangwenbao.com/cyrillic-encoding-legacy-windows1251-utf8-indexing-cost.html)就是那个年代的账。 本地化和机器可读经常要反着来,正文越本地化越好、结构化数据却要写回国际格式 (https://zhangwenbao.com/minor-language-structured-data-inlanguage-locale-schema.html)是同一种张力。 ## 路径匹配区分大小写,894条规则带着大写字母 这是最容易翻车的一条。robots.txt里的字段名(User-agent、Disallow)不区分大小写,但路径值区分。写Disallow: /Search挡不住/search。 目录层级深浅同样会影响判断,目录层级URL对SEO有何影响 (https://zhangwenbao.com/impact-of-hierarchical-urls-on-seo.html)给了六招优化实操。 地址命名习惯有行业惯例可循,一万个站实测出来的URL结构选择 (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)能当参照系。 157份文件里有894条规则的路径含大写字母,分布在107个站上——超过三分之二的站至少写过一条。minted.com一个站就有173条,osprey.com 47条,yeti.com 43条。 这个分布本身有信息量:大写字母集中在少数几个站,说明它跟站点的URL设计强相关,而不是随机的手误。用驼峰命名路径的站,规则里自然全是驼峰;全小写站点里冒出一条带大写的规则,那才是真的写错了。 ## 带大写不等于写错,但它把风险抬高了 公平地说,这894条里有相当一部分是对的:站点的URL结构本身就带大写,比如产品编号、语言代码写成zh-CN那种形式。规则跟着URL走,天经地义。 生成器不报错不等于内容对,抽了585条网址、48条是坏的 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)而程序一次都没报警。 声明和真实资源对不上是通病,236条地区声明背后只有6个真页面 (https://zhangwenbao.com/hreflang-region-code-declared-vs-real-pages.html)是一个极端例子。 真正的问题是混用。同一份文件里,一部分路径写成全小写、一部分带驼峰,往往说明这些行来自不同的人、不同的时期,谁都没有回头核对过站点当前的URL到底是哪种写法。而URL的大小写形态是会随着改版变的,规则不会自己跟着变。 验证成本其实很低:从sitemap里拉一批真实地址,看看有没有任何一条能匹配上这条带大写的规则。匹配不上就说明它已经悬空了。这个检查十分钟能跑完,但我几乎没见过谁做。 还有一种混用是跨站抄来的。做多品牌矩阵的团队经常把A站的robots.txt复制到B站再改几行,而两个站的URL命名规范未必一样。复制过来的那些带大写的路径,在新站上一条都匹配不到,却会长期留在文件里充当装饰。这类规则在样本里不少见,判断方法就是拿它去sitemap里搜一下有没有对应地址。 ## 百分号编码这一层,规范说得很清楚但很少有人照做 规范要求:比较之前,规则路径和被检查的地址都要按同一套百分号编码规则归一化。中文路径、带空格的路径、带加号的路径,编码方式不同就匹配不上。 按IP自动跳语言版本的代价很大,半数页面会因此进不了索引 (https://zhangwenbao.com/international-seo-ip-redirect-geolocation-language-switcher-ux.html)是实测出来的结果。 多语言站的地址层坑最多,hreflang、URL与价格结构化数据的三层避坑 (https://zhangwenbao.com/woocommerce-multilingual-multicurrency-seo-hreflang-url-schema.html)可以逐项核对。 实际文件里我见到的写法五花八门:有的直接写中文,有的写成百分号加十六进制那种编码形式,还有的写成加号代替空格。这三种写法在不同解析器里的处理不完全一致,尤其是加号——它在查询串里代表空格,在路径段里代表加号本身。 做多语言站的话这一条要格外小心。俄语、阿拉伯语、日语的分类页URL经常带非拉丁字符,浏览器地址栏显示的是可读形式,实际发出去的是编码形式。规则写成哪一种,取决于你是从浏览器复制的还是从日志复制的——而这两处看到的是同一个地址的两副面孔。 还有一种情况是同一个站两种编码并存。老页面的地址是早年编码方式生成的,新页面走了新的编码,两批地址在浏览器里看起来一模一样,字节层面却不同。规则只能匹配其中一批,另一批照抓不误。这类问题几乎只能靠日志发现,因为它在任何静态检查里都是完全正常的。 ## 末尾那个斜杠,决定了你挡的是目录还是前缀 Disallow: /account和Disallow: /account/是两条完全不同的规则。前者会连/accountsettings这样的地址一起挡掉,因为它只做前缀比较;后者只挡目录里的东西。 改版之后最容易出这类问题,一次揪出全站404与重定向链 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)是改完必跑的一步。 批量确认地址还在不在有现成办法,死链怎么批量查出来再分类提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接套用。 这一条在真实事故里出现的频率很高。我见过一个站想挡后台登录页,写了Disallow: /login,结果把/login-help这个专门写来做SEO的帮助页也一起挡了,半年没人发现。 发现它的过程也很典型:不是有人查robots.txt查出来的,是内容团队问为什么那篇帮助文章一直没有自然流量,顺着排查才摸到根上。robots.txt导致的问题几乎都是这个路径被发现的——从业务异常倒推回配置,而不是从配置审计里主动查出。 ## 空的Disallow值是允许,不是禁止 还有一个语法上的陷阱:Disallow后面什么都不写,规范定义为不挡任何东西,等于显式声明全站放行。157份文件里有8条这种写法。 生成器说格式正确的时候,它其实只查了三件事 (https://zhangwenbao.com/sitemap-generator-xml-lastmod-priority-validation-guide.html)剩下的还得自己看。 同一家族的另一份文件写法讲究更多,2400个站踩出来的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)基本都在那份清单里。 写这一行的人可能是想留个占位,也可能是删规则时删了一半。它不会造成损失,但如果它出现在一个原本打算全禁的组里,那就是灾难——那个组里别的规则还在,它只是没起到作者以为的作用。 这条规则的历史背景挺有意思:1994年那份原始文档里没有Allow字段,想表达全站放行只能靠写一个空的Disallow。所以它是一个语法上的历史遗迹,今天完全可以用Allow: /代替——虽然那一条同样是空转的。 顺带说一句,这四类问题在自动化检查里都很好实现,判定逻辑都是几行正则的事。真正的难点从来不在技术上,而在于没有人把它排进日常流程——它们不属于任何一个岗位的例行工作。 ## 这四种细节里,哪一种最值得先查 按发生频率排,大小写第一(894条)、末尾斜杠第二、编码第三、空值最后。但按单条造成的损失排,顺序几乎是反过来的:一条误挡了内容目录的末尾斜杠问题,可能比一百条永远匹配不上的大写规则代价更大。 链接结构层面也有类似的一次性体检,一次扒清内外链结构与扣分项 (https://zhangwenbao.com/link-analyzer-internal-external-audit-guide.html)适合改版后做。 页面被什么挡在索引外可以一次查清,可索引性体检把几层原因分开列 (https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html)比逐个猜快得多。 所以查的顺序建议按损失排而不是按频率排:先把所有不带末尾斜杠的目录型规则列出来,看看它们会不会波及同前缀的别的路径;再查带大写的那些还匹不匹配得上现在的URL;编码和空值放最后,它们更多是整洁性问题。 ## 这些规则到底是你写的,还是平台替你写好的? 统计到中途,我注意到一件事:一批毫不相干的品牌,撞车数完全相同,都是56条;空转的Allow也完全相同,都是7条。这不可能是巧合。 第三方悄悄改默认值这件事我量过,默认配置发生变更却没人通知 (https://zhangwenbao.com/third-party-default-changes-silent-drift-audit.html)的漂移比例并不低。 平台默认给的东西要先认清,Shopify的128种结构化数据类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)也是同一个问题。 ## 规则集完全相同的站有14个 我给每个站的规则集算了个签名——把所有规则排序后取哈希。157个站里,14个站落在4个签名上:7个站共用一份、3个站共用一份、还有两组各2个站。这批是逐字逐句一模一样的文件。 标签页这类批量地址最容易被忽略,Shopify博客标签页怎么避免权重稀释 (https://zhangwenbao.com/shopify-blog-tag-seo.html)给了处理方法。 平台生成的空页面也要单独处理,集合页没有产品时该怎么办 (https://zhangwenbao.com/seo-empty-shopify-collections.html)有三种场景的分别处置。 值得注意的是这14个站分属不同的国家、不同的品类、不同的价位段,彼此之间没有任何关系。把它们联系在一起的只有建站平台,或者更准确地说,是同一家代理商用的同一份起手模板。 ## 更普遍的是同一套骨架加几行自定义 完全相同只是冰山尖。更常见的情况是骨架来自平台、末尾追加了几行自己的。前面提到那批撞车数都是56、空转数都是7的站,文件并不完全相同,但前面几十行一字不差。 这种零星失分往往第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验的汇总。 换架构之后这套基建得自己重搭,sitemap、重定向这些东西不会自动跟过来 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是常见的上线失分点。 这套骨架来自一个主流的托管电商平台,它给每个店铺自动生成的robots.txt里,本来就包含了一组Allow和Disallow的对撞——平台先用通配规则挡住带查询参数的地址,再用几条Allow把商品目录下的同名路径放回来。设计上是合理的,问题是店主不知道这些规则存在,更不知道自己后来加的那几行会跟它们撞。 观察项 | 数值 | 说明 | 规则集逐字相同的站 | 14个(4组) | 完全套用平台默认 | 撞车数相同为56的站 | 十余个 | 共用同一套平台骨架 | 同一条规则写了多遍的站 | 9个,共26条 | 叠加维护的痕迹 | 规则条数中位数 | 41条 | 最多324,最少0 | 把这张表连起来读,能看到一条从平台到店主的责任链。平台提供骨架,代理商套用模板,店主追加补丁,三方各自只对自己那一段负责,而爬虫读到的是三段合并之后的结果。合并结果没有主人,这才是撞车集中出现在成熟站点上的真正原因——不是因为他们不懂,是因为没有任何一个角色的职责范围覆盖到最终效果。 判断自己是不是处在这条链上有个快办法:把robots.txt的第一行到第十行贴进搜索引擎搜一下。如果能搜到一堆别的站的同款文件,那前面这几十行就不是你的资产,而是你继承来的默认值。 ## 重复规则是叠加维护最直接的证据 26条完全重复的规则分布在9个站上,rab.equipment有8条,peakperformance.com有7条。同一条Disallow在一份文件里写两遍,唯一的解释是两个人在不同时间做了同一件事,谁都没先搜一下文件里有没有。 自动化流程走形是从第二周开始的,那批页面早已进了索引 (https://zhangwenbao.com/ai-automation-runtime-rot-guardrails.html)说的就是没人复查的后果。 判断一个站的技术欠账有多深,三类站点的高ROI修复清单 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以当成快速评估表。 重复本身无害,爬虫读到两条一样的规则不会有任何异常。它的价值在于当指纹用:一份文件里出现重复,基本可以断定它没有单一的维护者,也没有走过评审。 我做诊断的时候会把重复率当成一个粗糙的组织健康指标。重复越多,说明改这个文件的人越多、彼此越不通气;而这类站的其它配置——重定向规则、结构化数据、埋点脚本——通常也有同样的问题,因为那是同一批人用同一种方式在维护。 指纹这个用法还能反过来用。如果你要评估一个外包团队过去的工作质量,robots.txt是成本最低的切入点之一:有没有注释、有没有重复、有没有明显抄来的行、Allow写得准不准。十分钟看完,大致能判断这批人做事的细致程度,而这个判断通常能推广到他们做的别的东西上。 ## 平台默认与自定义规则撞车,责任在谁 这是个很现实的问题。店主加的那行Allow被平台默认的某条Disallow压住了,或者反过来,店主想挡的东西被平台的Allow放行了。文件是店主能编辑的,但骨架不是他写的,他甚至没读过。 完整的诊断框架能避免漏项,从抓取、内容到AI可见度的审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以当成检查表。 装太多东西之后冲突排查很难做,应用栈精简与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)是一套可执行的清理顺序。 保哥给客户做诊断时,遇到这种情况的第一步永远是:先把平台默认那份原样调出来,跟当前线上这份做一次逐行差分,把哪几行是自己加的圈出来。不做这一步,后面所有分析都建立在这些规则都是我们写的这个错误前提上。 差分之后经常会出现第三种情况:某几行既不在平台默认里,也没人记得是谁加的。这类行最值得单独拎出来做实验——注释掉两周,看日志有没有变化。多数时候什么都不会发生,那它就可以正式退休了。 还有一种更隐蔽的情况:平台把某些规则做成了动态生成。同一个地址在不同时段、不同区域节点上拿到的robots.txt可能不完全一样,因为它是按当前配置实时拼出来的。遇到这种平台,单次抓取的结论不能当定论,必须多点多次采样才有意义。 ## 平台侧也在悄悄改这份文件 还有一层容易被忽略:托管平台会更新它的默认模板,而更新通常不通知店主。你上个月核对过的文件,这个月可能已经多了两行。 定时表达式记不住就用生成器,把sitemap、排名、清缓存交给定时任务 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)是很划算的投入。 存档这件事交给定时任务最省心,把备份、sitemap、缓存、证书都自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)一条龙脚本可以直接改。 应对办法只有一个,就是定期存档。每周把线上那份robots.txt存一份带时间戳的副本,出问题时能立刻做时间维度的差分。这件事用一行定时任务就能做,成本几乎为零,但能省下未来某次排查的整整一天。 ## 为什么所有robots.txt检测工具都不报这类问题? 写到这里应该问一句:这么明显的问题,市面上那么多SEO工具,怎么一个都不提示? 工具的盲区往往正是机会所在,六个工具盲区里的捡漏选词法 (https://zhangwenbao.com/keyword-research-tool-blind-spots-overlooked-methods.html)是同一种思路。 工具选型别只看功能列表,五大类SEO工具的完整推荐与取舍 (https://zhangwenbao.com/seo-tools-recommendation-2026.html)说清了各自的能力边界。 ## 工具查的是语法,冲突是语义 语法检查的边界很清楚:字段名对不对、值有没有、结构合不合法。这些都是单行就能判定的事情。而两条规则会不会撞,必须把整组规则合并起来、针对某个具体地址跑一次完整裁决才知道。这是两个量级的工作。 调试这类文本有专门的顺手工具,把JSON-LD调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)省下不少肉眼比对。 生成器只保证语法不保证语义,十三种结构化数据类型一键生成 (https://zhangwenbao.com/schema-generator-jsonld-13-types-guide.html)之后仍然要自己核对。 更关键的是输出形态不一样。语法错误可以指着第几行说这里错了,冲突却指不到任何一行——它是两行之间的关系,报告里该怎么写、该标红哪一行,产品设计上就不好办。这大概也是没人做的原因之一。 ## 更根本的原因:工具不知道该拿哪些地址去试 就算工具愿意做合并判定,它也得有一批地址去喂。robots.txt本身不包含任何真实地址,规则里写的是模式不是URL。要测出冲突,工具得先知道这个站有哪些页面——那需要一次全站抓取,或者至少一份sitemap。 另一个地址来源是日志本身,读懂Googlebot抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)那套分析法拿到的是真实请求。 想批量拿到一批真实地址并不难,六种格式的sitemap解析与URL批量提取 (https://zhangwenbao.com/sitemap-extractor-url-extraction-format-analysis-guide.html)能省掉手工翻页。 这就是为什么我这次用了代表路径这个折衷办法:从规则自身生成一批一定能匹配的地址,不依赖任何外部数据。它测不出你的真实页面有没有被误挡,但能测出你的规则之间有没有内部矛盾。这两件事需要分开做。 ## Google Search Console的robots.txt测试也只测单个地址 官方工具确实实现了官方文档里描述的那套完整裁决逻辑 (https://developers.google.com/search/docs/crawling-indexing/robots/robots_txt),你输一个地址进去,它会告诉你放行还是拦截、哪条规则生效。这个结果是权威的,因为它就是线上那套解析器。 报告里那些状态词各有含义,八种未编入索引状态的决策路径 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)对照着看才不会误判。 官方后台里能挖的东西比想象中多,用过滤器精准拆分品牌流量 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)是个被低估的功能。 但它一次只测一个地址,得你自己想好要测什么。真正会出问题的那些地址,恰恰是你想不到的——你想得到就不会写错了。 这是所有单点检测工具的通病。它能确认你的假设,不能帮你产生假设。而排查这件事里,产生假设才是最难的一步。 ## 把官方解析器搬到本地跑,是最省事的一条路 Google把它的robots.txt解析器开源了 (https://github.com/google/robotstxt),就是线上用的那份C++实现。编译出来是个命令行程序,喂给它一份robots.txt、一个User-agent和一个地址,它吐回允许或拒绝。 自己养一套小工具的杠杆很大,自养工具怎么重塑SEO工作流 (https://zhangwenbao.com/vibe-coding-seo-competitive-advantage.html)给了十步可执行路径。 另一条硬边界也能本地复现,Googlebot那个2MB抓取上限怎么测 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)有现成的检查器。 有了这个东西,前面所有实验都能在自己站上复现:从sitemap里拉一批真实地址,批量喂进去,把判定结果和你的预期比一遍。这比任何第三方工具都可靠,因为它不是模拟,它就是本体。 如果懒得编译,照着规范自己写一个也就几十行——核心逻辑只有匹配和比长度两件事。我这次用的就是自己写的PHP版本,跑完之后拿几十个地址跟官方实现对了一遍答案,全部一致才敢往下做统计。这一步千万别省,写解析器最容易在通配符的贪婪程度上出偏差。 ## 拿自己的站跑一遍,该按什么顺序查? 数据看完了,落到自己站上该怎么做。这一节给的是一套顺序,不是清单——顺序比清单重要,因为前一步的结论会决定后一步值不值得做。 开发期就该埋好这些点,自建站开发阶段的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)能省掉上线后的返工。 从零起步的话顺序更重要,前十二周从技术地基到内容蓝图 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)是一份排好序的清单。 ## 第一步:确认爬虫读到的是哪一组规则 先别看规则内容,先确认分组。用你关心的那个爬虫名字去匹配文件里的每个User-agent值,找出匹配上的那一组。只要匹配上了任何一个专属组,通配组的全部规则对它就不再生效——这是很多人栽的第一跤。 服务端识别对方身份有几种老办法,五种代码识别搜索引擎蜘蛛的实战写法 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)可以拿来验证。 新出现的抓取器要单独认一遍,Google-Agent是什么、怎么识别和应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是最近才需要处理的问题。 确认方法很土但可靠:把文件里所有User-agent行列出来,逐个判断你的目标爬虫会不会匹配上。判断依据是子串包含,不是完全相等。Googlebot-Image会匹配到写着Googlebot的那一组吗?会。所以给Googlebot单开组的时候,图片爬虫也一起被拉进去了。 这一步的产出应该是一张表:左边是你在乎的爬虫,右边是它实际执行的那一组的行号范围。表做出来之后经常会发现,你精心写给通配组的那二十条规则,主流搜索引擎一条都没在读。 ## 第二步:把真实地址而不是规则拿来测 规则之间有没有内部矛盾是一回事,你真正在乎的页面有没有被误挡是另一回事。后者才是生意上的问题,测法是从sitemap里拉一批真实地址出来喂给解析器。 百万级商品的地址怎么组织,分片、进出场与lastmod诚实度 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)是一整套工程实践。 这份文件的作用常被高估,提交网站地图到底能不能提升排名 (https://zhangwenbao.com/does-sitemap-improve-google-ranking-myth.html)得先把预期放对。 我这次也做了这件事:从143个站的sitemap里拉了26万条地址,每站抽300条跑判定。结论是被自己robots.txt挡住的只有14条,涉及6个站,比例低到0.05%。这是个让我意外的负面结果——自己提交的地址被自己挡住这个经典事故,在这批成熟站点上几乎不存在。 那14条也不全是事故。philips.com有8条落在一个明显是测试用的目录下,theordinary.com那两条指向站内搜索结果页——搜索页进sitemap本来就不合适,被robots挡住反而是对的。真正算失误的没几条。这个结果值得写出来,因为很多审计工具把这一项列为高危,实际数据说明它在成熟站上早就不是主要矛盾了。 抽样口径也得交代清楚。每站至多抽300条,是为了不让sitemap有二十万条的巨型站压过只有几百条的小站。如果不做这个上限,最后的比例基本就是那几个巨型站的比例,跟整体没关系。抽样时用了固定的随机种子,任何人拿同一批数据重跑都会抽到同一批地址。 ## 第三步:反过来查,被挡的地址是不是你想挡的 第二步查的是误伤,第三步查的是漏网。把规则生成的代表路径列出来,逐条问一句:这个地址真的存在吗?我想挡的是不是它? 换成有效手段之后还得等,页面加了noindex要多久才从结果里消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)有六个场景的实测。 快速看一眼收录情况有个老办法,site命令怎么用、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)得先知道它的边界。 上一批我做过这个实验,结论相当难看:能判定存在性的176条被挡路径里,94条指向的地址已经不存在了,占53.4%。规则还在挡一个早就被删掉的目录,而真正该挡的新目录没人补规则。 这两步合起来才是完整的图景:误伤率低不代表规则健康,它可能只是说明规则太旧、已经够不着任何现存的地址了。一份挡不住任何东西的robots.txt当然不会误伤,它只是彻底失去了作用。 这一步还有个附带收获:跑完之后你会得到一份规则实际覆盖范围的清单,它比文件本身好读得多。把这份清单发给运营和内容团队看,他们经常能当场指出某个目录不该被挡——那些判断只有天天用这些地址的人做得出来,技术这边看规则是看不出来的。 ## 第四步:把冲突判定跑出来,只看结论和预期不一致的那些 前三步做完,最后才轮到本文的主角。对每条Allow做一次删除实验,看它删掉之后判定变不变;对每条规则的代表路径跑一次完整裁决,记下胜出的是哪条。 声明与实测的落差在响应头上更明显,说会变的有3个、真变的有17个 (https://zhangwenbao.com/vary-header-declared-vs-actual-response-variation.html)是另一组数据。 声明和实际不一致的情况我量过,132个首页有23%自己跟自己矛盾 (https://zhangwenbao.com/canonical-self-declaration-conflict-google-selected.html)是同一类对照实验。 输出格式建议做成三列:地址、你以为的结果、实际结果。只看第二列和第三列不一样的行。绝大多数站这样的行不会超过十条,一个下午能全部处理完。 难点在第二列。你以为的结果没有任何地方记着,得靠人回忆或者靠猜。所以这一步的真正价值不是当次修了几条,而是逼着团队第一次把每条规则的意图写下来。写下来之后,往后每次改动都能自动比对。 还有个更省力的做法,适合手上有几十个站要管的人:把前四步全部脚本化,输出一份每站一行的汇总表,列上规则条数、Allow条数、空转数、撞车数、误挡数。跑一次十几分钟,之后每月定时跑,只看数字发生变化的那几行。变化本身就是最好的告警——没人改过的文件不会突然多出三条撞车。 ## 第五步:把平台默认那份单独存一份 前面说过,你编辑的那份文件里很可能有一半不是你写的。做完前四步,把当前线上这份存档,再去平台文档里找到默认模板存一份,做一次差分。 另一份长期没人碰的配置也值得存档,重写、缓存、规范化与HSTS六层治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)是同样的维护逻辑。 把原始记录留下来是所有排查的前提,日志怎么收集成可检索的结构 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是一件越早做越好的事。 差分结果建议写进团队文档,注明哪几行是自己加的、为什么加、什么时候可以删。半年后接手的人会感谢这份记录——他至少知道哪些行是可以动的。 差分还有一个副产品:它能告诉你平台什么时候改过默认模板。把每周的存档串起来看,模板变更的时间点一目了然,而这些时间点经常能对上某次说不清原因的抓取量波动。没有存档的话,这类波动永远只能归因为算法调整。 ## 做完这五步,剩下的事情就交给日志 robots.txt的真实效果只有一个地方能验证:服务器日志。规则写完一周后翻日志,看那些你以为挡住了的路径还有没有请求进来,请求方是谁。 限速做在服务器上也有反噬,限速拒掉的第四个请求正好是robots.txt (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html)会让全站抓取停十几个小时。 要看清谁在真抓你的站,五千个站样本里的爬虫伪造与预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)是更硬的参照。 这一步能同时验出两件事:规则有没有生效,以及对方守不守规矩。这两件事经常被混为一谈,但处理方式完全不同——前者要改文件,后者只能上更硬的手段。 翻日志时有个小技巧:不要按路径搜,按状态码和UA的组合搜。被挡住的路径如果还在被抓,日志里通常伴随着一批很有特征的UA;把这批UA单独拉出来看它们还抓了什么,往往能顺手发现别的问题。 还有一个前置动作容易被跳过:先确认这份文件本身能不能被稳定拿到。样本里有20个站的sitemap对着我们的抓取直接返回403,robots.txt本身也有类似情况。如果连文件都拿不全,后面的所有判定都建立在残缺数据上,而这一点在报表里完全看不出来。 ## 这套顺序在多站场景下怎么排期 手上站少的时候,五步一次做完就行。站多的时候建议拆成两轮:第一轮只做第一步和第二步,把分组错配和误挡这两类会直接掉流量的问题清掉;第二轮再做后面三步,那些属于长期整洁性投入,可以按季度排。 排期这件事在大促期间尤其要紧,大促与日常SEO的八维度差异 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)给了完整时间轴。 多站还是单站本身就是个决策,建一个大站还是多个品牌小站 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)的取舍会影响后续所有工作量。 拆轮次的好处是能拿第一轮的结果去换第二轮的资源。分组错配这种问题一旦被量出来,通常能立刻拿到修复窗口;而空转的Allow清理这种事,光靠讲道理很难排进任何一个迭代。 ## 量这批数据的时候,尺子坏在哪几处? 照惯例交代一下这批数字是怎么被我量错又量对的。这一节不是自我批评,是给想复现的人省时间。 监控类工具的口径差异更大,二十款监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)得先看它们各自怎么算。 同一批域名上做过的另一项实测是,142个站里只有52个回得出304 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)口径同样卡得很死。 ## 第一次:解析器的分组逻辑写错了,Allow数量差了三倍 第一版脚本里,我用了PHP的引用赋值来往分组数组里追加规则,写法看着没毛病,跑起来分组会串。结果是同一个站的规则被分到了错误的组里,统计出来的Allow总数是369条。 有报错反而是好事,这个致命错误的五步排查修复 (https://zhangwenbao.com/fatal-errorcall-to-a-member-function-getinnertext-on-a-non-object-in.html)至少有明确的起点。 不报错的故障最难查,从GD库到会话残留的逐层排查 (https://zhangwenbao.com/a-dedecms-background-verification-solution-error-code.html)是同一种沉默失败。 第二版脚本换成先追加数组、再取引用的写法,同一批文件量出来是1113条。三倍的差距。这种错误最可怕的地方在于它不报错,两个数字都长得很像真的,如果不是我恰好用两个脚本量了同一件事,会直接把369写进结论里。 发现它纯属运气:两个脚本的输出摆在一起,一个说74个站写过Allow,另一个说22个。数字对不上才回头查代码。所以我现在的习惯是关键指标一定用两条独立路径各算一遍,哪怕多花二十分钟。对不上比对得上有价值得多。 ## 第二次:分母差点又用错 上一批踩过的坑这次差点原样重踩:目录里躺着198个文件,直觉上就想拿它当分母。实际能用的只有157份,中间差着41份403和429的错误响应体,以及9份返回200但内容是HTML拦截页的。 换个口径看数据结论可能完全不同,三类站点的聚合自然流量实测 (https://zhangwenbao.com/aggregate-organic-traffic-seo-metric-keyword-dead.html)就是一次口径切换。 两个数字对不上先怀疑口径,站长工具排名为何与实际不一致 (https://zhangwenbao.com/webmaster-tool-query-website-keywords-ranking-and-baidu-search-results-are-inconsistent-reasons.html)给了六步排查法。 教训固化成一句话:分母必须从抓取记录来,不能从落盘文件来。抓取脚本会把失败响应也写进文件,这是它的正常行为,判断哪些能用是分析脚本的责任。 那9份HTML拦截页也值得说一句。它们状态码是200,内容里有完整的HTML结构,如果不做内容检查会被当成一份robots.txt解析——解析结果是零条规则,于是这个站会被统计成什么都没禁。一个防护严格的站,就这样在报表里变成了完全开放的站。 ## 第三次:代表路径这个办法本身有边界 把星号替换成一段固定字符来生成代表路径,这个办法能测出规则之间的内部矛盾,但测不出真实页面的命运。因为生成的地址在站上很可能不存在。 样本量大不代表结论可用,三千条数据揭开的认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)说明该信什么不该信什么。 指标定义清楚才谈得上对比,三个平台三百个站的收录速度实测 (https://zhangwenbao.com/seo-kpi-guide.html)是一份口径统一的样本。 所以本文里所有百分之多少的路径说的都是规则层面的比例,不是页面层面的比例。这两个口径差得很远,后者我另外用sitemap的真实地址跑了一遍,就是前面那个0.05%。混用这两个数字会得出完全错误的结论。 写文章的时候我特意在每个百分比后面都标了口径,看着有点啰嗦。但这类数据一旦被人引用,标注就是唯一能防止它被误读的东西——引用的人不会回头看你的方法论,他只会摘走那个数字。 ## 还有一个中文变量名的低级坑 写统计脚本输出的时候,PHP的双引号字符串里如果变量名后面紧跟中文标点,那个标点会被当成变量名的一部分——PHP允许高位字节出现在标识符里。于是输出变成一片空白,还附赠一个未定义变量的警告。 还有更隐蔽的改写发生在浏览器里,自动翻译把yes改成forks而数据看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是同一种沉默污染。 脚本层面的小疏忽代价可能很大,上传目录还能跑PHP的五种加固写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是另一类低级但致命的问题。 这个坑我这批犯了两次,第二次才反应过来。修法是所有插值一律写成花括号包裹的形式。听起来微不足道,但它会让一屏统计结果里最关键的那个数字消失,而你正忙着看别的行。 ## 还有一处没能量成的东西 我本来想量一件更有意思的事:一条规则在文件里躺了多久。如果能拿到历史快照,就能算出那些空转规则的平均年龄,进而说明它们是不是随时间自然沉积的。可惜公共存档接口在这台服务器上取不到数据,这条路走不通。 监控闭环怎么搭是个通用问题,四步把引用率监控做成闭环 (https://zhangwenbao.com/monitor-measure-iterate-ai-citation-optimization-2026.html)可以套到别的指标上。 想追时间维度的变化得先有数据源,各家波动追踪工具与解读流派 (https://zhangwenbao.com/google-algorithm-volatility-tracking-tools-interpretation-frameworks.html)各有各的取数方式。 退而求其次的替代方案是看重复规则和注释密度,两者都能间接反映沉积程度,但都不如时间维度直接。这一项留给以后有条件的时候补,写在这里也算给自己留个记号。 这个记号还有个用处:它提醒读者本文的结论有时间边界。所有数字都是2026年8月16日那一次抓取的快照,规则每天都在被人改动。半年后重跑同一套脚本,比例大概率会变,而变化本身才是更有意思的数据。 ## 为什么要把这些写出来 因为这类文章最大的风险不是结论错,是结论看起来对。5494和8624这两个数字放在文章里都很有说服力,读者没有办法判断哪个是对的。 数据分析入门先建立习惯,三类工具与排名追踪的日常做法 (https://zhangwenbao.com/seo-data-concept.html)比学工具更重要。 把过程写出来比只给结论有用,从AI搜索到结构化数据的实施策略 (https://zhangwenbao.com/geo-strategy.html)也是一步步摊开的。 唯一能让人放心的做法是把口径、剔除规则、失败过程全部摊开,让人能照着复现。数字本身不值钱,能被复现的数字才值钱。 还有一个原则是这几批做下来最有用的:任何一个要写进结论的数字,都必须能追回到某一行原始数据。做不到这一点的数字,宁可不写,也别让它出现在表格里——它一旦被印出来就会被当成事实,而你自己都不知道它是怎么算出来的。 ## 一份能被复现的清单该包含什么 如果你想把本文的实验原样跑一遍,需要的东西一共四样:一份抓取记录(含状态码),一批robots.txt原始响应,一个照规范实现的匹配器,以及一份随机种子写死的洗牌脚本。前两样决定分母,后两样决定结论。 把流程沉淀成模板能省很多重复,四大类三十多个提示词模板 (https://zhangwenbao.com/seo-ai-prompts-for-writing.html)可以直接拿去改。 批量取数这件事可以完全脚本化,用Python批量抓关键词数据 (https://zhangwenbao.com/google-rank-checker-python-serpapi-tutorial.html)是一个可直接跑的例子。 四样里最容易被省掉的是第一样。很多人抓完就直接读文件了,没有单独记状态码——而这正是我两次踩坑的根源。抓取和分析必须分成两个阶段,中间用一份记录连接,这是这类普查唯一靠谱的结构。 ## 规则写得越多,越接近你想要的结果吗? 把157个站按规则条数排开,能看到一条很清楚的规律,而它跟大多数人的预期是反的。 把力气花在刀刃上更重要,二十个提升电商排名与营收的进阶策略 (https://zhangwenbao.com/ecommerce-seo-advanced-tips-2026.html)按投入产出排过序。 结构决定了要写多少规则,架构搭错了爬虫根本找不到商品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是更上游的问题。 ## 规则条数和冲突数几乎是线性的 规则最多的十个站,撞车数也是最多的十个站里的九个。rituals.com 324条规则对应135条撞车,nespresso.com 217条对应84条。反过来,规则在20条以内的站,撞车数基本是零。 分页方案选错会连累一大片,五种分页方案的对比与配置 (https://zhangwenbao.com/category-pagination-seo.html)可以先看结论再动手。 分页地址是规则膨胀的常见来源,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)有具体做法。 这不是什么深刻的发现,但值得说破:每加一条规则,它跟已有规则撞上的可能性就增加一分,而没有人在加规则的时候跑过合并判定。文件越长,你对它的实际行为知道得越少。 反过来看那些只写十几条的站,也不能一概认为是偷懒。有几个站的做法很聪明:只挡确定不该被抓的四五类地址,剩下的全交给页面上的索引指令去控制。这种分工把两个工具各自的能力用在了对的地方,文件短、冲突少、意图清楚。 ## 规则多不等于控制得细 把撞车率和空转率放在一起看更有意思。那些规则上百条的站,空转的Allow也最多。rituals.com 78条Allow里10条空转,nespresso.com 86条里8条空转。 同类页面互相抢位也要治理,五个维度的信号区隔实战 (https://zhangwenbao.com/keyword-cannibalization-fix-guide.html)是另一种精细控制。 重复内容的成因得先分类,八类成因地图加诊断清单 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)比一刀切的禁令有效。 换句话说,写得多的人并没有因为写得多而写得更准。他们只是把更多的意图表达了出来,而其中一部分意图在合并之后被抵消了、被覆盖了、或者从一开始就落在空处。 这里有个容易被忽略的成本:规则越多,团队里能看懂这份文件的人越少。二十条的时候产品经理也能读;三百条的时候连技术负责人都要花半天,于是没人再读,改动就只能靠追加。追加又让它更长,循环就此闭合。 还有个现象值得记一笔:规则条数排前十的站里,有六个是做多语言多市场的。语言前缀会让同一类地址在文件里出现好几遍——挡一个搜索页要挡二十种语言下的搜索页,于是二十行。这类膨胀是结构性的,不是维护习惯的问题,用一条带通配符的规则本可以解决,但没人敢改那二十行。 ## 那么多少条才算合适 我不太愿意给一个数字,因为它跟站的复杂度直接相关。但样本给的中位数是41条,而做得最干净的那批站通常在10到25条之间,覆盖的无非是购物车、账户、搜索结果、筛选参数这几类。 技术项做满分也未必涨,问题多半出在搜索意图没对齐 (https://zhangwenbao.com/search-intent-alignment-vs-technical-seo.html)提醒别把力气全花在配置上。 现在要顾的层比以前多,从AI爬虫到可访问性的42步实战 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)列了完整范围。 一个判断标准比数字管用:文件里的每一条规则,你都能说出它是哪年为了什么加的、以及删掉它会发生什么。说不出来的那些,先注释掉观察两周。 ## 真正该问的不是数量,是这件事该不该用这个文件做 很多长文件的膨胀来自一个误会:把robots.txt当成了万能的控制面板。可它只能做一件事——建议对方别抓某个地址。它管不了收录、管不了展现、也管不了那些压根不看它的程序。 索引控制该做在内容架构上,帮助中心的索引控制与AI引用工程化 (https://zhangwenbao.com/knowledge-base-help-center-seo-indexing-ai-citation.html)是一个正面例子。 提交了不收录还有别的原因,抓取与索引机制的分步拆解 (https://zhangwenbao.com/baidu-index-crawl-mechanism-why-not-indexed.html)能帮你定位卡在哪一环。 想让页面不出现在搜索结果里,该用的是页面上的索引指令;想让某类程序进不来,该用的是服务器或边缘层的拦截。用错了工具,规则写得再精细也是在做无用功。 最典型的误用是拿它来藏东西。禁止抓取不等于禁止收录——一个被禁止抓取的地址,如果有别的站链向它,照样可能带着标题出现在搜索结果里,只是没有摘要。想藏的东西被藏了一半,反而更显眼。 还有一种常见误用是拿它来控制抓取频率。文件里能写的那个延迟字段,主流搜索引擎里只有一家会读,别家要么忽略要么按自己的算法调节。想真正压住某类程序的请求速率,只能在服务器或者边缘层做限速,那是另一套完全不同的工具。 还有个折中办法:不删,但把过期规则集中挪到文件末尾,用一行注释标成待清理区。这样既不承担删错的风险,又能让下一个人一眼看出哪些是活的、哪些是存疑的。文件长度没变,可读性完全不同。 ## 删规则比加规则难,这是它变长的根本原因 加一条规则的风险是可以估计的:最坏无非是挡多了。删一条规则的风险是不可估计的:你不知道当年为什么加,删了会不会放出一堆垃圾地址。 有些工具留着不用比乱用强,外链拒绝工具还有没有用的决策框架 (https://zhangwenbao.com/google-disavow-tool-guide.html)给了判断依据。 该不该留下一个已经没用的东西,FAQ富结果被砍之后那段标记还写不写 (https://zhangwenbao.com/google-drops-faq-rich-results.html)是同一道选择题。 于是所有人都只加不删,文件单调增长。破局的办法只有一个,就是给每条规则留下加它的理由。这件事必须在加的当时做,事后再补基本补不回来。 ## 除了robots.txt,同样的仲裁问题还出现在哪里? 最后把视野拉开一点。这次实验测的是一份文件内部两条规则的裁决,但同一条声明有两种读法这件事,在整条技术链路上到处都是。 响应头本身能做的事不少,X-Robots、缓存与Vary的实战机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)是一份系统的梳理。 响应头里那些没人读的字段我数过,248个死字段里多数不是你写的 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html)而是平台统一下发的。 ## 同一份响应里,两个字段说相反的话 HTTP响应头是重灾区。X-Frame-Options写着拒绝任何嵌套,同一个响应里的内容安全策略却允许自家子域嵌套;缓存指令里同时写着不许存储和存一年。这些组合在规范里都有明确裁决,而裁决结果往往和写的人以为的相反。 安全策略里的白名单同样会失效,白名单上明明写着那个域名、浏览器还是拦了 (https://zhangwenbao.com/csp-script-src-allowlist-drift-third-party-silent-block.html)是一次真实排查。 缓存那几个字段的配合最容易写岔,怎么配才能既秒开又不出改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)讲得比较细。 Google那边对安全响应头的表态挺有意思:真正跟搜索有关系的只有一类,就是阻止别的站把你的内容嵌进iframe——不管是用老的X-Frame-Options,还是用内容安全策略里的frame-ancestors。这两个恰恰是最容易写出矛盾的一对。 缓存那一对更能说明问题。同一个响应里既写了不许存储,又写了一个很长的有效期,规范的裁决是不许存储胜出——但中间的CDN、代理、浏览器各自实现的严格程度不一样,实际表现可能是三层里有两层照做、一层照存。这种时候你看到的现象是缓存偶尔不更新,排查方向却往往被引到应用层去了。 ## 同一个地址,几个层各有一份声明 再往上一层,一个页面的身份可能同时被四个地方声明:sitemap说它该被收录,robots.txt说它能不能被抓,页面上的meta标签说它要不要进索引,canonical说它是不是正主。这四个声明分属不同的文件、不同的团队、不同的更新节奏。 跨页场景下的冲突形态更多,八种跨页场景与冲突诊断 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)是一份对照表。 最终由谁说了算有明确逻辑,Google选择规范网址的九条决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)可以照着排查。 它们之间没有统一的仲裁者。robots.txt挡住的页面,页面上写的noindex永远不会被读到——因为抓都没抓,怎么读得到那个标签。两条规则叠加的结果,跟任何一方的意图都不一样。 ## 新的声明层还在往上加 八月中旬llms.md发布了第二版规范 (https://www.searchenginejournal.com/llms-txt-v2-formal-markdown-linking-ai-agents/586119/),新增了两种正式的链接关系:一种指向页面的Markdown版本,一种指向覆盖这个页面的说明文件,两种都可以写在HTML里,也可以写在HTTP响应头里。 想知道AI爬虫真正在乎什么,从代码逆向出它的抓取偏好 (https://zhangwenbao.com/ai-crawler-reverse-engineering-fetch-behavior-llms-strategy.html)比看官方说明更实在。 要进AI的候选池得先过技术这关,五步技术优化的实战顺序 (https://zhangwenbao.com/technical-optimization-crawler-friendly-ai-citations-2026.html)把门槛列清楚了。 Google那边的表态很直接:搜索本身不使用这些文件,维护它既不会帮你也不会害你。但这不妨碍它成为第五份声明——而且从第一天起,它跟前四份之间就没有任何一致性检查。 更麻烦的是这五份声明的更新节奏完全不同。sitemap通常是程序每天生成的,robots.txt可能三年没动,页面上的meta标签跟着模板走,canonical由CMS插件控制,llms.md多半是某次赶时髦手写的。节奏不同意味着它们不可能长期保持一致——不一致不是偶发故障,是这套架构的常态。 还有一类情况是规范写了但实现没跟上,或者实现跟上了但版本参差。这时候四问的答案是不确定,唯一的出路是实测:构造一个能区分两种行为的最小样本,实际发一次请求看结果。这套方法从robots.txt到响应头都通用,区别只在于构造样本的难度。 ## 判断谁赢的通用问法 不管遇到哪一层,判断方法是同一套四问:这条声明的接收方是谁?规范有没有写明并存时的裁决规则?裁决依据是长度、严格度,还是先后顺序?我实际写的那一条,在裁决里排第几? 信号之间打架时怎么定夺,六类消歧信号的管控实战 (https://zhangwenbao.com/entity-disambiguation-mechanism-seo-signal-control.html)给了处理顺序。 多份声明怎么合成一个实体,@graph与知识图谱怎么搭 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)是另一套合并规则。 能把这四问答完,绝大多数配置明明写了却没生效的问题当场就有答案。答不完的那些,多半是因为规范本身没写,那就得靠实测——而实测的第一步永远是找到那个真正生效的解析器。 这四问里第三问最容易被跳过。人们通常问完接收方是谁、规范怎么说,就以为结束了,其实还差最关键的一步:裁决依据到底是哪个维度。robots.txt比长度,HTTP缓存比严格度,内容安全策略里多份声明取交集,同名响应头按合并规则拼成列表。四种依据,四种完全不同的写法后果,混着记必然记错。 ## 写规则的人不是裁判,这是本文唯一想说的事 回到开头那条新闻。OpenAI说用户触发的抓取可能不适用robots.txt,很多人的第一反应是气愤。但把这件事和本文的数据放在一起看,会发现它只是同一个问题的最外层——你写下一条规则,它的效力从来不由你决定。 规则之外还得想清楚要什么,四大AI搜索引擎的分引擎策略 (https://zhangwenbao.com/ai-search-engine-geo-optimization-strategy.html)是更靠前的一步。 还有一种思路是干脆换成收费,要不要向AI爬虫按次抓取收钱 (https://zhangwenbao.com/cloudflare-pay-per-crawl-charge-ai-bots.html)已经有平台在做了。 决定它的是对方手里那张裁决表。表在规范里的时候,你至少还能查;表在对方的产品决策里的时候,你连查都没地方查。所以能查的那一部分,更值得花一个下午跑清楚。 ## 常见问题解答 ## Allow和Disallow同时匹配一个地址,到底哪条生效? 按RFC 9309的规定,路径写得更长的那条生效,长度以规则里写的字符数计算,通配符也算进去。如果最长的规则里既有Allow又有Disallow且长度相同,Allow生效。跟这两条规则写在文件的第几行完全无关。 ## 把Allow写在Disallow前面,能让它优先吗? 不能。我用157份真实文件做过验证:把规则随机打乱五遍、跑了32815次判定,结论一次都没变。想让某条Allow赢,唯一的办法是把它的路径写得比对应的Disallow更长更具体,而不是调整行的位置。 ## Allow: /这一行有用吗? 没有用。robots.txt的默认状态就是全部允许,写不写这一行结果一样。样本里45个站写了它,全部属于空转。它唯一的副作用是会让后来接手的人误以为文件是按先总放行再逐条禁止的逻辑组织的。 ## robots.txt的路径区分大小写吗? 路径区分,字段名不区分。写Disallow: /Search挡不住/search这个地址。样本里894条规则的路径带大写字母,涉及107个站。如果你的站URL是全小写的,这类规则很可能一条都没匹配上。 ## 不支持通配符的爬虫会怎么读我的规则? 它会把星号当普通字符做前缀匹配,结果是绝大多数带通配符的规则彻底失效。我用这种读法重跑了一遍,6571条路径里有3535条结论不同,涉及133个站。受影响最重的是拦截筛选参数那一类规则,它们几乎全依赖通配符。 ## 怎么在自己站上验一遍这些结论? 把Google开源的robots.txt解析器编译出来,从sitemap里拉一批真实地址批量喂进去,把判定结果和你的预期逐条比对。重点看三类:你以为放行实际被挡的、你以为挡住实际放行的、以及删掉之后判定不变的那些Allow。 ## 这份文件多少条规则算合理? 样本中位数是41条,维护得最好的那批站通常在10到25条。比条数更好用的判据是:每条规则你都能说出它是哪年为什么加的、删掉会发生什么。说不出来的先注释掉观察两周,多数时候什么都不会发生。 ## 权威参考资料 ## 分类页开了19405个,首页只点得到一成七 - URL:https://zhangwenbao.com/collection-three-lists-mismatch-audit.html - 分类:技术SEO - 发布:2026-08-18 | 更新:2026-09-08 - 摘要:后台建了上千个集合,你知道其中有多少进了sitemap、多少在首页有入口、多少一件货都没有吗? - 关键词:技术SEO,电商SEO,Shopify > **TLDR**:摘要:58个英文电商站,数据出口里一共19405个分类,都是已经发布到网店渠道、有真实地址、能被抓取的。这批分类同时活在三个地方:出口、sitemap、首页导航。三份清单没有一份对得上——sitemap里少了2479个,首页导航能点到的只有2238个,中位覆盖率17.1%,13个站连一成都不到。其中2050个分类(10.6%)一件货都没有,而这批空货架里62.0%被写进了sitemap,还有44个至今挂在首页导航上。逐个请求这些空分类页,146个里有145个回200,只有1个回404。 > 摘要:58个英文电商站,数据出口里一共19405个分类,都是已经发布到网店渠道、有真实地址、能被抓取的。这批分类同时活在三个地方:出口、sitemap、首页导航。三份清单没有一份对得上——sitemap里少了2479个,首页导航能点到的只有2238个,中位覆盖率17.1%,13个站连一成都不到。其中2050个分类(10.6%)一件货都没有,而这批空货架里62.0%被写进了sitemap,还有44个至今挂在首页导航上。逐个请求这些空分类页,146个里有145个回200,只有1个回404。 先摆一个数字。allbirds这个站,商品294件,分类1346个。分类是商品的4.6倍。 这不是个例。58个站里有12个站的分类数比商品数还多:thirdlove是1014对362,italic是171对50,brooklinen是781对471,beistravel是760对460。一个货架比货还多的仓库,听起来像段子,但在电商后台里它是常态——每做一次活动建一个集合,每上一个新系列建一个集合,每接一个应用它自己再建一批,没人回头删。 问题不在于建得多,在于这些分类建完之后,就开始在三个地方各活各的。 ## 一个分类同时活在三个地方,你知道它们对不对得上吗? 做电商SEO的人,脑子里的分类清单通常只有一份,就是后台里能看到的那份。但对搜索引擎来说,它至少能从三条路知道你有哪些分类: - 数据出口。也就是 /collections.json 这个不用登录就能读的地址,返回的是所有已经发布到网店渠道的分类。每一条都对应一个真实可访问的地址。这一族出口保哥之前写过它的商品版 (https://zhangwenbao.com/shopify-products-json-open-data-endpoint-audit.html),那篇讲的是它泄露了什么,这次只把它当分类的权威清单用。 - sitemap。站点主动递给爬虫的那份名单。 - 首页导航。给人走的那条路,也是站内链接权重的起点。 这三份清单本该是同一批东西的三个副本。实测下来,58个站里只有21个站的出口清单和sitemap逐条对得上,首页导航那一份跟另外两份的差距更是数量级的。 ## 先说口径怎么定的 出口那份翻页翻到底,一页250条。sitemap那份要按语言分卷拆开——这一步不做会算错,后面单独说。首页导航那份不能只抓静态HTML,必须用无头浏览器渲染一遍再取链接,理由跟测商品可达性那次 (https://zhangwenbao.com/product-two-click-reachability-audit.html)一样:gymshark的首页静态HTML里一个分类链接都没有,渲染完有92个。 ## 数据出口里到底有多少分类? 58个站合计19405个,中位124个,最大的那个1346个。 注意这19405个不是后台里的草稿,是已经发布、有地址、爬虫走得进去的页面。也就是说,光分类页这一类,这58个站就给搜索引擎准备了将近两万个待抓地址。 按每个分类装了多少货分档,分布是这样: 分类里有多少件货 | 数量 | 占比 | 0件 | 2050 | 10.6% | 1件 | 903 | 4.7% | 2到5件 | 3807 | 19.6% | 6到20件 | 5222 | 26.9% | 21到100件 | 4806 | 24.8% | 101到500件 | 1841 | 9.5% | 500件以上 | 776 | 4.0% | 中位数是12件。三分之一强的分类装的货不超过5件,这里面绝大多数是活动集合、赠品集合、某个应用自己建的辅助集合。它们都有独立地址,都能被抓,都在消耗抓取预算。 ## 这些分类是什么时候建的? 出口会告诉你每个分类的发布时间,把19405个按年份归一下,堆积的过程一目了然: 发布年份 | 数量 | 占比 | 2019年及更早 | 1744 | 9.0% | 2020到2022年 | 3711 | 19.1% | 2023年 | 2066 | 10.6% | 2024年 | 2351 | 12.1% | 2025年 | 4857 | 25.0% | 2026年 | 4676 | 24.1% | 近两年建的占了49.1%,接近一半。这条曲线不是业务在扩张——58个站的商品总数并没有在两年里翻倍。它更像是运营节奏的副产品:每个季度、每次上新、每轮促销,都留下一批地址,而清理这件事从来没被排进过任何一个人的日程。 另一头也值得看:2019年及更早建的分类还有1744个活着,最老的那批发布于2012年。一个十四年前建的集合,今天仍然在被爬虫定期访问。它当年装的货多半早就下架了。这类页面该怎么进出sitemap,百万SKU的sitemap实战 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)那篇给过一套进出场规则,套到分类上同样成立。 ## 首页能点到的,只有其中一成七 把首页渲染后DOM里所有指向分类的链接抓下来,去掉查询参数再去重,跟出口那份对一遍: 站 | 出口里的分类 | 首页能点到 | 覆盖率 | allbirds | 1346 | 29 | 2.2% | thirdlove | 1014 | 48 | 4.7% | untuckit | 769 | 21 | 2.7% | brooklinen | 781 | 29 | 3.7% | marinelayer | 1176 | 48 | 4.1% | chubbiesshorts | 1007 | 135 | 13.4% | parachutehome | 804 | 78 | 9.7% | flyingtiger | 476 | 159 | 33.4% | 全样本的中位覆盖率是17.1%,均值22.1%,最高的那个站88.9%,13个站不到一成。 这个数低到什么程度?意思是你后台里每建六个分类,只有一个在首页有入口。剩下五个要么埋在二级三级导航里,要么只能靠sitemap被发现,要么就干脆没人知道——最后这一类就是孤岛页面 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html),只不过大家平时盯的是商品页,很少有人回头数分类页。 ## 覆盖率低本身不是罪 这里得把话说清楚,不然容易读成“覆盖率越高越好”。 首页导航是个稀缺位置,塞不下1346个链接,也不该塞。真正该担心的是另一件事:那些不在导航里的分类,你到底打算拿它们怎么办?是让它们安静地待着不被索引,还是让它们进sitemap去争抓取预算?多数站的实际状态是第三种——既没打算,也没管过。 ## 出口里有、sitemap里没有的那2479个,是怎么漏的? 把出口和sitemap两份清单逐条对,结果高度不对称:出口里有而sitemap里没有的,2479个;反过来sitemap里有而出口里没有的,只有115个。(reebok的分类清单翻页到上限还没到底,两侧不可比,已经从这一组数里扣掉。) 反向那115个基本可以忽略,正向这2479个才是问题。逐站看: 站 | 没进sitemap的分类 | 占该站分类数 | brooklinen | 724 / 781 | 92.7% | misen | 188 / 219 | 85.8% | rothys | 124 / 198 | 62.6% | aloyoga | 288 / 607 | 47.4% | awaytravel | 72 / 155 | 46.5% | stanley1913 | 96 / 217 | 44.2% | beistravel | 293 / 760 | 38.6% | thirdlove | 265 / 1014 | 26.1% | brooklinen那一行很极端:781个分类,sitemap里只列了57个。剩下724个页面照样能打开、照样能被抓,只是站点自己没把它们写进名单。 这件事本身不算错。sitemap不是必须列全,把低价值页面排除在外反而是正确的用法 (https://zhangwenbao.com/does-sitemap-improve-google-ranking-myth.html)。问题在于:没进sitemap的这批,绝大多数同时也不在首页导航里。两条发现路径都断了,页面还留着——它就成了纯粹的抓取成本,没有任何回报。这批地址还会顺手把站内权重漏掉一部分 (https://zhangwenbao.com/internal-link-decay-equity-reclaim.html),因为导航里那些指向它们的残余链接并没有一起清掉。 顺带说一句,就算进了sitemap也不代表万事大吉。从站点地图里抽585条网址有48条是坏的 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)那次实测,生成程序全程一次都没报错。清单本身的可信度,也得单独验一遍。 ## 分类越多,两份清单越对不上 把58个站按“出口和sitemap是不是逐条一致”分成两组,两组的分类规模差得很清楚: - 完全一致的21个站,分类数中位87个。 - 对不上的37个站,分类数中位155个,接近前者的两倍。 这个关系不难理解。分类少的时候,sitemap生成器把全部集合列一遍就行,没人会去筛。分类多起来之后,主题或者插件开始按某种规则挑——挑的规则通常写在配置里,没人复查过,于是漏掉哪些完全是偶然。生成器说格式正确的时候其实只查了三件事 (https://zhangwenbao.com/sitemap-generator-xml-lastmod-priority-validation-guide.html),少列了谁它不会告诉你。 值得强调的是,这里只能说两者同时出现,不能说分类多导致了对不上。也可能是那些分类多的站本来就用了更复杂的插件组合。要坐实因果得看同一个站在分类数增长前后的变化,这次的数据做不到。 但无论因果如何,实践上的建议是一样的:谷歌那份大站抓取预算文档 (https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget)把这件事叫做“感知到的库存”——搜索引擎会按它以为你有多少页面来分配抓取量。你的库存清单里塞了一堆空集合,分到每个真商品页上的额度就少一份。 ## 有一成的分类,一件货都没有 19405个分类里,2050个的商品数是0,占10.6%。逐站看,比例差得很远: 站 | 空分类 | 占比 | fiskars | 26 / 27 | 96.3% | brooklinen | 446 / 781 | 57.1% | nativecos | 9 / 24 | 37.5% | beistravel | 259 / 760 | 34.1% | allbirds | 397 / 1346 | 29.5% | snowpeak | 185 / 663 | 27.9% | gymshark | 108 / 525 | 20.6% | chubbiesshorts | 166 / 1007 | 16.5% | 这些空货架的去向更值得看:2050个里有1272个(62.0%)被写进了sitemap,也就是说站点主动把它们推荐给了爬虫。还有44个至今挂在首页导航上,用户点进去会看到一个什么都没有的页面。 这件事跟站点架构做得好不好关系不大,扁平三层架构 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)该怎么搭是另一个问题,这里纯粹是没人做清理。建过活动集合的人都知道这是怎么发生的:黑五建一个 black-friday,活动结束把商品移走,集合留着明年用。明年用不用另说,这一年里它一直在那儿,一直被抓。 ## 空货架那一页,服务器回的是什么? 这是本次实测里最值得单拎出来的一项。谷歌对这类页面的要求写得非常明确,在筛选类地址的抓取管理文档 (https://developers.google.com/crawling/docs/faceted-navigation)里只有一句话:当一个筛选组合没有结果时,返回HTTP 404。 我从48个站里各抽了几个声明为0件的分类,一共请求了146个页面。这里的“声明”取的是分类对象自己给的 products_count,按Shopify官方的collection对象文档 (https://shopify.dev/docs/api/liquid/objects/collection),这个字段统计的是当前视图下的商品数,跟包含被筛掉商品的 all_products_count 是两个字段,别拿错。 146个页面里,返回200的145个(99.3%),返回404的只有1个。带 noindex 的(不论写在meta里还是响应头里)41个,占28.1%。页面文案里明确说了没有商品的74个。 也就是说,将近七成的空货架页面既回200、又允许被索引。它对搜索引擎的自我介绍是:我是一个正常页面,请收录我。 抓取这些页面不是免费的。同一份文档里另有一句话:让这类地址被抓,意味着服务器资源消耗增加,而且可能拖慢站点上新地址的发现速度。我顺手量了一下这些空页面的体积——正文中位6346个字符,HTML中位610KB。一个一件货都没有的页面,仍然要传六百多KB。2050个空分类乘一遍,是1.2GB的纯抓取开销。 这笔账跟条件请求能省下多少抓取预算 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)是同一本账,只是那一头省的是重复内容,这一头浪费的是空内容。 ## 怎么判断一个分类页是不是真的空? 这一节是本次踩得最深的一个坑,写出来比结论有用。 我一开始的判据是数页面上的 /products/ 链接:零链接就是空。跑完发现146个空分类页里有124个能数到商品链接,最多的一个数到441个。这个结果显然不对——出口明明说0件。 ## 用浏览器看一眼,答案分成四种 拿几个典型页面用无头浏览器打开,按链接所在的DOM位置分开数: 页面 | 导航里 | 页脚里 | 正文区 | 正文区可见 | 页面怎么说 | casper的frontpage | 108 | 0 | 0 | 0 | 没有任何提示 | chubbies的easy-mesh-2020-lounge | 2 | 0 | 65 | 0 | 明写No Products Found | cluse的sale-70 | 0 | 0 | 0 | 0 | 明写这个分类里没有商品 | bollandbranch的neutral-bedding | 9 | 1 | 67 | 67 | 没有任何提示 | 前三行说明了那124个的来历:导航和页脚会贡献几十个商品链接,筛选器还会把一批卡片预渲染进DOM再隐藏起来。数 /products/ 链接这把尺子,量的根本不是这个分类有没有货。 第四行是另一回事。bollandbranch那一页正文区实打实摆着67个可见的商品卡,标题、H1、canonical一应俱全。我去问了权威口径——这个分类的商品清单接口返回0件,分类对象自己也说商品数是0。两边都对:这个站的分类页内容根本不由Shopify的集合决定,是另一套系统在填。它的 /collections/sheets 直接404就是证据。 ## 改完之后的判据 换成两条一起看: - 权威口径:/collections//products.json 返回0件。 - 人眼口径:浏览器打开后,正文区里可见的商品卡为0——不是页面上所有的商品链接为0。 按这两条重跑48个站各一页:33个是真空货架,14个正文区仍有可见商品卡(分不清是空态页上的推荐位还是像bollandbranch那样口径脱钩,所以这14个站不进比例,只当形态举例),1个页面脚本报错没读到。 真空的那33个里,只有11个页面明确告诉用户这里没有商品,另外22个什么都不说。用户点进去看到一片空白,既不知道是没货了还是页面坏了——这一屏该写什么,类目导航那篇 (https://zhangwenbao.com/category-navigation-scope-custody.html)里讨论过同一个毛病。这跟站内搜索搜不到那一页的处境 (https://zhangwenbao.com/site-search-empty-result-indexability-audit.html)几乎一模一样,只是搜索页至少有一半的站做了noindex,分类页只有28.1%。 ## 顺手做的一组自对照 光看空分类页的数据不够,得知道有货的分类页长什么样。同一批站里我另抽了95个声明有货的分类做对照: 中位数放在一起:商品链接4个对15个,正文字符6346对7553,HTML体积610KB对829KB,带 noindex 的比例28.1%对18.9%。四项都是空的那边低一点,但没有一项低到能当判据用。 按站配对再看一次:32个站的空分类页链接确实更少,13个站两者一样多,3个站空的反而更多。后两类加起来16个站,占了三分之一——在这些站上,光从页面本身分辨不出这个分类有没有货。爬虫面对的就是这个局面。 ## 分类页自己有内容吗? 顺便把分类对象里的描述和题图也统计了一遍: - 描述为空的:12109个,占62.4%。 - 有题图的:2157个,占11.1%。 - 写了描述的那7296个,长度中位223个字符,其中648个不足80个字符。 换句话说,六成以上的分类页,除了一排商品卡之外没有任何自己的文字。分类页想拿排名,靠的就是那段描述加上商品集合本身的语义——两样都没有,它跟站内另外几百个分类页在搜索引擎眼里就很难区分开,这正是电商重复内容 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)最常见的来源之一。至于一个分类页凭什么值得被单独收录,商品列表页那97条准则 (https://zhangwenbao.com/product-list-guidelines-scoring-selection-bias.html)里给的答案是:得有别处拿不到的东西。 ## 这些分类该删、该合,还是该留? 先说结论:绝大多数不该删。删了会掉链接、掉历史、掉可能存在的外链,收益却只是少几个抓取地址。真正该做的是分档处理。 ## 第一档:空的、没进导航、也不打算再用 这一档给noindex,让它继续200着。别做404——如果这个集合明年还要用,404会让它的地址信誉归零。判断标准是:这个集合有没有历史流量、有没有外链。两样都没有才归到这一档。 需要注意的是分类页的noindex只能写在页面上或者响应头里,出口地址那种没有head标签的资源 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)就只能靠响应头,两者别搞混。 ## 第二档:空的、但导航上还挂着链接 这一档先改导航,把链接摘掉,再按第一档处理。样本里有44个分类属于这一档,它们是唯一会被真实用户撞上的一类,优先级最高。 ## 第三档:有货、但既不在导航也不在sitemap 这一档才是值得抢救的。它有真实内容,只是没有任何一条路通向它。做法是在相关的分类页之间加交叉链接——Shopify的交叉分类怎么做不踩重复内容的坑 (https://zhangwenbao.com/shopify-product-cross-classification-seo.html)那篇有完整的写法,核心是canonical要指对,别让同一批货的几个入口互相打架。同时把它补进sitemap。 ## 第四档:活动集合 建的时候就给个期限。活动结束后自动加noindex,从sitemap里移出去,导航链接撤掉,集合本身留着。这件事写成定时任务比靠人记可靠得多。 ## 改完怎么验证 # 1 拉全部分类,看有多少是空的 curl -s "https://你的域名/collections.json?limit=250&page=1" \ | jq -r '.collections[] | "\(.products_count)\t\(.handle)"' \ | awk -F'\t' '$1==0' | wc -l # 2 挑几个空的,看返回码和 noindex curl -sI "https://你的域名/collections/某个空集合" | grep -Ei '^HTTP|x-robots' curl -s "https://你的域名/collections/某个空集合" | grep -o ']*robots[^>]*>' 第一条命令的输出就是你的空货架总数,改造之后它不该变(集合还留着),但第二条命令里的 noindex 应该出现。分面导航治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)那套方案里的抓取预算监控可以直接复用,看Search Console的抓取统计里分类页那一类的请求数有没有降下来。 ## 我在这次测量里踩到的三个坑 都不是小坑,每一个都会让结论差出一个数量级。 ## sitemap把语言版本也算了一份 58个站里有14个的sitemap索引里挂着 /es/、/de/ 这类语言分卷。直接把所有分卷的地址并起来,wusthof的商品数会变成736——444个英文的加上292个西班牙语的,而后者的handle是翻译过的,看起来就像另一批货。ice-watch更夸张,分类数被算成368,出口明明只有118。 修法是按分卷地址里的语言前缀拆开,只取根语言那一份。凡是做多语言站的清单比对,第一步就该问一句:这份清单里是不是同一件东西被算了好几遍。 ## 静态HTML抓不全首页导航 58个站里11个渲染之后分类链接更多,gymshark从0变成92。但反过来也有8个站渲染后比静态还少——菜单还没等脚本挂上去就被读走了。两个通道都会漏,最终口径只能取并集,而且要清楚这仍然是下界。相关的坑在首页空壳那次实测 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)里也遇到过一次。 ## 把链接条数当成分类数 中途我一度以为magicspoon的首页能点到12个分类,跟脚本给的1个对不上。回头看才发现,那12条链接全指向同一个 shop-all,只是带了不同的 ?filter= 参数。去重必须在剥掉查询参数之后做,否则覆盖率会凭空虚高。这个错是我自己看错了中间输出,不是数据的问题,但它提醒了一件事:反常的数先怀疑自己的读法。 ## 常见问题解答 ## 分类开得多本身有害吗? 没有直接害处,有害的是开完之后不管。一个分类页只要有真实内容、有入口、进了sitemap,开一千个也没问题。真正拖累站点的是那批既没内容、又没入口、还占着抓取额度的。判断标准不是数量,是这三样齐不齐。 ## 空的集合到底该404还是该noindex? 谷歌文档对筛选组合无结果的建议是404。但集合和筛选组合不完全是一回事——集合是个持久对象,可能明年活动还要用,返回404会让它的地址信誉清零。折中做法是:一次性的筛选组合走404,可复用的集合走noindex加从sitemap移除。有历史流量或者外链的一律别动。 ## 怎么快速看出我的站有多少空分类? Shopify站一条命令就够:拉 /collections.json,看 products_count 等于0的有几条。别的平台去后台的分类列表按商品数排序,最小的那批就是。要注意 products_count 统计的是当前视图下的商品数,跟前台实际显示的可能有出入,拿不准就再请求一次这个分类的商品清单核对。 ## 首页导航覆盖率17.1%算低吗?该提到多少? 这个数没有目标值,首页本来就装不下所有分类。它的用处是当分母去看另一个问题:不在导航里的那83%,你有没有为它们安排别的路径。比较实用的做法是把分类分成三层——首页直达的核心分类、二级导航能到的、以及只在sitemap里的长尾分类,每一层都要说得清它靠什么被发现。 ## 为什么不直接爬全站,非要用数据出口? 爬全站拿到的是可达的分类,出口拿到的是存在的分类,这次要比的恰恰是这两者的差。用爬虫做分母,那些走不到的分类从一开始就不会出现在样本里,差异自然测不出来。这也是为什么样本只能是出口还开着的那批站。 ## 分类页的描述写多长合适? 样本里写了描述的那批中位是223个字符,不足80个字符的有648个。字数不是重点,重点是那段文字有没有说清楚“为什么这批货被归在一起”。选购建议、尺码差别、材质区别、适用场景,这些是商品卡上没有的信息。如果写出来的东西把商品标题拼一遍就完了,那不如不写。 ## 这次的结论有哪些地方不成立? 至少四处。样本全是商品数据出口还开着的Shopify站,关掉出口的站和别的平台没进来,结论不能直接外推。reebok的分类清单翻页到上限还没到底,凡是涉及两份清单比对的数都把它扣掉了,涉及分布的数没扣,所以19405这个总数是含它的下界。 还有两处更要紧。空货架的判定用的是分类对象自己声明的商品数,遇到bollandbranch那种分类页内容不由平台集合决定的站,这个声明跟页面上看到的完全脱钩,那14个站只当形态举例、不进比例。首页导航那份清单是渲染后DOM的并集,仍然只是下界,二级三级导航里的分类根本没算进来。 ## 这套方法能用在WooCommerce或者Magento上吗? 能,换接口就行。WooCommerce的分类可以从REST API的products/categories拿到,里面有count字段;Magento有分类接口。三份清单的结构完全一样:平台里存在的分类、sitemap里列出的分类、首页导航能点到的分类。唯一不能省的是第三份必须用浏览器渲染,静态HTML在这件事上不可靠。 ## 权威参考资料 ## 写着每次都要回源,CDN手上那份副本已经躺了9小时 - URL:https://zhangwenbao.com/cache-control-directive-audience-scope-audit.html - 分类:技术SEO - 发布:2026-08-18 | 更新:2026-09-04 - 摘要:你在响应头里写下那串缓存指令的时候,心里想的是浏览器。可这句话还有第二个听众站在中间,它只挑属于自己的那几个词听,剩下的按自己的规矩办,不报错也不留痕。 - 关键词:技术SEO,HTTP响应头,缓存策略 > **TLDR**:摘要:115个能正常打开的海外品牌站里,首页响应头有58个一个字的缓存声明都没写,剩下57个写了的,有22个通篇没有一句是说给CDN听的。更反直觉的是另一组:11个站在头里写着max-age=0、必须回源验证,可同一个响应带回来的Age字段显示,CDN手上那份副本已经躺了最长9小时。而47个站在Cache-Control里对浏览器只字未提,却另外发了一个CDN-Cache-Control专门对边缘说“别存”——这个头100%出自同一个建站平台,其余7类平台一个都没有。 > 摘要:115个能正常打开的海外品牌站里,首页响应头有58个一个字的缓存声明都没写,剩下57个写了的,有22个通篇没有一句是说给CDN听的。更反直觉的是另一组:11个站在头里写着max-age=0、必须回源验证,可同一个响应带回来的Age字段显示,CDN手上那份副本已经躺了最长9小时。而47个站在Cache-Control里对浏览器只字未提,却另外发了一个CDN-Cache-Control专门对边缘说“别存”——这个头100%出自同一个建站平台,其余7类平台一个都没有。 缓存这件事,很多人的心智模型是一句话:我在响应头里写多久,东西就存多久。 这句话漏掉了一个前提——你在对谁说话。一个页面从服务器到用户眼前,中间至少站着两拨完全不同的听众:用户自己那台电脑上的浏览器缓存,以及横在中间的共享缓存(CDN节点、反向代理、公司出口的代理服务器)。Cache-Control那一串用逗号隔开的词,不是一句话说给一个人听,而是一堆词各自认领各自的听众。 有的词两拨都读,比如max-age。有的词只有共享缓存会读,浏览器看见了也当没看见,比如s-maxage、proxy-revalidate。有的词反过来,主要靠浏览器兑现,中间那层大多不认,比如immutable。你写下一整行,实际上是同时朝两个方向喊话,而每一拨只挑属于自己的那几个词听——没点到名的那部分,他按自己的规矩办,不报错、不提示、不在任何监控面板上留痕。 这就是这篇要量的东西:一条声明的作用域到底覆盖到哪儿,边界之外那一块发生了什么。我把131个海外品牌站的首页、以及每个站上的一个CSS、一个JS、一张图片、一个网站图标和robots.txt,逐个抓下来读了一遍响应头,顺便用Age字段反查“谁真的把它存下来了”。 先说一句结论性的:怎么配缓存头 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)这类文章已经很多,缺的不是配置模板,而是把“这句话是对谁说的”这一层拎出来单独对一遍。同一份模板抄到不同架构上,听众换了,效果就完全不是一回事。 ## 一行Cache-Control里的每个词,究竟是说给谁听的? 先把受众这件事摊开。RFC 9111把缓存分成两类 (https://www.rfc-editor.org/rfc/rfc9111.html):私有缓存(private cache,实际上就是浏览器为单个用户存的那份)和共享缓存(shared cache,为多个用户存同一份,CDN和反向代理都属于这一类)。规范给每条指令都注明了适用对象,只是这份对照表很少有人完整读过。 指令 | 浏览器(私有缓存) | CDN/代理(共享缓存) | 115个首页里出现 | max-age | 读 | 读 | 34 | no-store | 读 | 读 | 29 | no-cache | 读 | 读 | 31 | must-revalidate | 读 | 读 | 34 | public | 基本无感 | 读,是它的主要听众 | 21 | private | 不针对它 | 读,含义是“你别存” | 11 | s-maxage | 明确忽略 | 读,且优先于max-age | 8 | proxy-revalidate | 明确忽略 | 读 | 0 | immutable | 读 | 多数不兑现 | 0(子资源上37处) | stale-while-revalidate | 部分实现 | 读,主战场 | 9(全样本34个站) | 注意最后一列的形状:出现频次最高的四个词,全是两边都读的通用词;而专门写给共享缓存的那几个,加起来的出现次数还不如max-age一个多。这不是巧合,后面几节会看到它是一种系统性的偏斜。 ## 为什么private不是“给浏览器的” 这是最常被讲反的一个词。private读起来像是在对浏览器说“你可以私下存着”,但它真正的收信人是中间那一层:它是在告诉共享缓存“这份响应带着某个特定用户的信息,你不许存”。浏览器本来就只服务一个用户,它不需要这句话的许可。 所以当你在一个所有人都拿到同一份字节的公开CSS上写private,你并没有给浏览器多一点什么,你只是把CDN从这条链路上赶走了。这个错位在样本里出现了不止一次,后面有一节专门算这笔账。 ## 115个站的首页,这行头到底写了什么? 先把分母说清楚。131个站里,16个对这个客户端根本不给正常响应:11个直接403,4个连续限流返回429,1个返回418。这16个不进任何统计——把“我没拿到”混进“它没有”,是这类审计最常见的一种自伤,也是我上一轮实测吃过的亏。 剩下115个站是全文所有比例的分母。 首页Cache-Control | 站数 | 占115 | 一个字都不发 | 58 | 50.4% | 发了,但没有一句是给共享缓存的 | 22 | 19.1% | 发了,其中1条给共享缓存 | 23 | 20.0% | 发了,其中2条给共享缓存 | 7 | 6.1% | 发了,其中3条给共享缓存 | 5 | 4.3% | 把前两行加起来是80个站,接近七成。这七成的共同点是:在首页这个最值钱的响应上,他们从没对中间那一层说过一个字。 还有一个顺手捡到的小样本。那11个返回403的站里,有6个连拒绝页都带着完整的缓存头,写的是private, max-age=0, no-store, no-cache, must-revalidate, post-check=0, pre-check=0。这一串里的最后两个词是IE 5时代的私有扩展,现代浏览器和CDN都不认识它——一句说给一个已经不存在的听众的话,跟着模板原样传了二十年。 ## 为什么一半的站在这行头里一个字都不写? 不写会怎样?规范里有答案,只是这个答案不太让人安心。RFC 9111允许缓存在没有明确寿命声明时自己估一个“启发式寿命”,通常的做法是拿响应时间减去Last-Modified,取其中的一个比例(常见实现取十分之一)当作可以放心复用的时长。 问题是这个估算需要输入。我数了那58个不发Cache-Control的站: 启发式算寿命需要的输入 | 58个站里有几个 | 带Last-Modified(唯一能直接喂给启发式的字段) | 3 | 带Expires | 0 | 带ETag(只能做验证,算不出寿命) | 48 | 三样能定寿命的输入一个都没有 | 8 | 也就是说,绝大多数沉默的站,连让中间层“猜”的材料都没提供。剩下的空白由每一家CDN自己的默认策略填上——Cloudflare对HTML默认不缓存,Fastly和Varnish的出厂配置又各有各的算法,同一个站放在不同的边缘上,行为可以完全不同。这条缝隙的宽度不由你决定,由你签的那份服务合同决定。 值得单独说一句的是那48个带ETag却不带任何寿命声明的站。ETag解决的是“我手上这份还新鲜吗”,它需要缓存先存下一份、再拿着它去问。可你都没说能不能存,这个ETag就只剩下给浏览器省一次完整下载的价值了,中间那一层压根没被邀请进这个流程。想把条件请求这条路走通,得先把存不存这件事说清楚,这一层的收益账在304状态码那次142个站的实测 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)里算过。 ## 47个站对CDN单独说了一句话,浏览器听不见 这是这轮实测里最干净的一组数字。 除了Cache-Control,还有一个专门写给边缘层的头叫CDN-Cache-Control。它的语义很直接:如果一个响应同时带着两个头,CDN读后者、浏览器读前者,各拿各的那一份。115个站里,有48个发了这个头。 取值分布是:48个全部写着no-cache, no-store,一字不差。 而其中47个,在Cache-Control那一栏里什么都没写。 把这两句话拼在一起读:这47个站对浏览器保持沉默,同时扭过头去对CDN说了一句非常明确的“别存”。同一件事,两个听众,两种完全不同的待遇。 ## 这是谁的手笔 “某某跟着某某走”这种归因,只量支持自己的那一组是不作数的,得同时量不具备这个特征的那一组。我把上一轮实测留下的建站平台标签接过来,对全部115个站做了分组: 建站平台 | 样本站数 | 发CDN-Cache-Control | 发出率 | Shopify | 66 | 48 | 72.7% | Salesforce | 10 | 0 | 0% | Next.js自建 | 9 | 0 | 0% | Magento | 3 | 0 | 0% | BigCommerce | 2 | 0 | 0% | WordPress | 1 | 0 | 0% | 指纹认不出来的 | 24 | 0 | 0% | 对照组干净得有点吓人:除了一个平台,其余6类加上认不出的那批,49个站,一个都没有。这句“别存”不是这47个品牌各自的技术决策,它是出厂时就写在响应里的,绝大多数店主这辈子没见过它。 这个头本身是个好东西——把边缘策略和浏览器策略彻底分开,正是在边缘那一层改SEO (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)这套打法的地基。只是当它以出厂默认的形式写着“别存”、而店主又完全不知情的时候,这个地基就成了一堵墙。想动它得先知道自己那家CDN认哪个头,Cloudflare那套缓存规则的迁移路径 (https://zhangwenbao.com/cloudflare-cache-real-world-optimization-decision-tree.html)是个可比的样本。 唯一一个两边都发、且说的不一样的是fahertybrand:Cache-Control写private, no-store,CDN-Cache-Control写no-cache, no-store。两句话意思相近,但显然出自不同的笔。 ## 写着每次都要回源,为什么那份副本已经躺了9小时? 现在说这轮实测里最反直觉的一组。 有11个站的首页写着max-age=0或者no-cache,同时带回了Age字段。绝大多数人读这一行的理解是“别缓存,每次都来问我”。但Age说的是另一回事——它是共享缓存自己填的,含义是“这份副本在我这儿已经放了多少秒”。它出现,就等于中间那一层承认:我存了。 更整齐的是,这11个里有10个写的是一模一样的public, max-age=0, must-revalidate。 站点 | Age(秒) | 换算 | 它的Cache-Control | traeger.com | 32642 | 9小时4分 | public, max-age=0, must-revalidate | babybjorn.com | 31566 | 8小时46分 | public,max-age=0,must-revalidate | ruggable.com | 2496 | 41分 | public, max-age=0, must-revalidate | bigcommerce.com | 223 | 3分43秒 | public, max-age=0, must-revalidate | anker.com | 197 | 3分17秒 | public,max-age=0,must-revalidate | vuoriclothing.com | 190 | 3分10秒 | public,max-age=0,must-revalidate | lookfantastic.com | 140 | 2分20秒 | max-age=0, s-maxage=900, stale-while-revalidate=300 | soundcore.com | 120 | 2分 | public,max-age=0,must-revalidate | suitsupply.com | 75 | 1分15秒 | public, max-age=0, must-revalidate | eufy.com | 14 | 14秒 | public,max-age=0,must-revalidate | kotn.com | 12 | 12秒 | public, max-age=0, must-revalidate | 这不是CDN在违规。规范里,max-age管的是“这份东西多久之后算过期”,must-revalidate管的是“过期之后不许直接端上来,必须先去问一次源站”。两句话加起来的准确意思是:可以存,但从存下的那一秒起就算过期,每次要用之前都得回源验证一遍。它从头到尾没说过“不许存”。 真正说“不许存”的那个词叫no-store。而这11个站里,一个都没写。lookfantastic那一行更值得看一眼:它把s-maxage写成900,等于亲口请边缘存15分钟,而Age显示副本已经放了140秒——完全在它自己许可的范围内。 ## 这个区别在什么时候会咬人 存与不存的差别,平时确实看不出来——每次都回源验证,用户拿到的内容总是新的。但两个场景下它会突然变得很重要。 第一个是回源不通的时候。副本还在边缘手上,源站挂了或者超时,缓存可以按照配置把这份过期副本直接端出去(stale-if-error就是干这个的)。这时候用户看到的是一个也许几小时前的页面,而你的监控显示源站已经502了。 第二个是这份副本里带了个人化内容的时候。max-age=0没有阻止它被存进一个所有人共用的池子,如果某个响应里恰好夹了上一个访客的购物车或者地区信息,它就有机会被端给下一个人。想避免这件事,得用private把共享缓存请出去,或者干脆用no-store。写max-age=0, must-revalidate解决不了它。 还有两个站更彻底:innisfree和assos的首页一个缓存声明都没有,却分别带回了29119秒和1017秒的Age。没人告诉中间层能不能存,中间层自己做了决定。 反过来的坑也存在,而且更隐蔽:有些运行时会背着你往响应里塞缓存头。PHP只要执行到一句开启会话的代码就自动发三个头 (https://zhangwenbao.com/php-session-cache-limiter-nocache-cdn-audit.html),其中一个写着1981年的日期,效果是把整页从所有共享缓存里踢出去。你在配置文件里怎么写都不管用,因为这句话不是你说的。 ## s-maxage只有8个站写,其中2个写了等于没写 stale-while-revalidate与stale-if-error这两个扩展 (https://www.rfc-editor.org/rfc/rfc5861.html)是另一份文件定义的,而s-maxage是这套语法里唯一一个“专款专用”的词:它给共享缓存单独指定一个寿命,且优先级高于max-age,浏览器看见它会直接跳过。它存在的全部意义,就是让你对两拨听众说两个不同的数字——边缘可以存久一点,浏览器那边短一点,改内容的时候只需要清边缘。 115个站里写了它的有8个,一个不多。 站点 | max-age | s-maxage | 两者的关系 | ikea.com | 900 | 2592000 | 边缘存30天,浏览器15分钟,差2880倍 | lookfantastic.com | 0 | 900 | 浏览器不留,边缘留15分钟 | on.com | 0 | 180 | 浏览器不留,边缘留3分钟 | arcteryx.com | 120 | 600 | 边缘5倍于浏览器 | braun.com | 1801 | 3601 | 边缘2倍于浏览器 | burrow.com | 900 | 1800 | 边缘2倍于浏览器 | bollandbranch.com | 1800 | 1800 | 两个数一样,等于没写 | quince.com | 0 | 0 | 两个数一样,等于没写 | 前6个是把这个词用对了的样子,尤其是ikea那一组:让边缘扛整整一个月,浏览器只留一刻钟,内容更新时只要清一次边缘,全球用户下一次访问就是新的。这是共享缓存最值钱的用法,115个站里认真做了这件事的是个位数。 后2个属于另一种情况:既然两个数字一样,那么删掉s-maxage,行为一个字节都不会变。它出现在那里,多半是从某份模板里抄来的。 把边缘和浏览器的时长拆开定,是边缘缓存TTL分层 (https://zhangwenbao.com/cdn-edge-caching-strategy-ttl-cache-control-purge-origin-shield.html)里最先该做的一步;如果源站前面还压着一层自己的全页缓存,那就是三段时长要对齐,Nginx全页缓存那套配置 (https://zhangwenbao.com/nginx-fastcgi-cache-fullpage-php-wordpress-purge-microcache.html)里可以看到这三段是怎么互相牵制的。 ## 把private写在一张公开的CSS上,谁会照做? 前面说过private的收信人是共享缓存。那么它出现在什么地方最不该出现?答案是所有人拿到的都是同一份字节的静态资源。 样本里,CSS文件上写了private的有10个站,图片2个,JS 2个,robots.txt 4个。其中有9处更有意思,因为它们把两个互相拆台的词写进了同一行: 站点 | CSS上的Cache-Control | 建站平台 | buckmason.com | private, max-age=600, stale-while-revalidate=604800 | Shopify | dollarshaveclub.com | private, max-age=600, stale-while-revalidate=604800 | Shopify | vuoriclothing.com | private, max-age=600, stale-while-revalidate=604800 | Shopify | wusthof.com | private, max-age=600, stale-while-revalidate=604800 | Shopify | charleskeith.com | private, max-age=600, stale-while-revalidate=604800 | Salesforce | sostrenegrene.com | private, max-age=600, stale-while-revalidate=604800 | 认不出 | casetify.com | private, max-age=86400, stale-while-revalidate=604800 | 认不出 | insta360.com | private, max-age=86400, stale-while-revalidate=604800 | Next.js | lookfantastic.com | private, max-age=86400, stale-while-revalidate=604800 | Salesforce | stale-while-revalidate的意思是“过期之后先把旧的端出去,同时在后台悄悄去拿新的”,这个动作只有共享缓存做得漂亮——它替成千上万人做一次后台刷新。而private刚刚把共享缓存赶出了门。一行字里,前半句解雇了后半句要用的人。 更值得注意的是最后一列:这9个站跨了4类建站平台,说明这句话不是某个平台的出厂值,而是某一层CDN或者某一份加固模板留下的。同一句错话能横跨4个技术栈,靠的不是巧合,是复制粘贴。 代价是实打实的字节。静态资源不进共享缓存,每一次访问都得从源站原路取回,而这批文件恰恰是全站体积最大的那部分。同样一批字节反复回源要付多少,压缩协商那次实测 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)算过一笔类似的账:出厂配置只压了HTML一种类型,其余的全额计费。 ## no-cache后面还能跟一个字段名,那句话只有CDN会读 整个样本里最冷门的一处写法,来自quince.com。它的CSS、JS和网站图标上都写着: public, max-age=31536000, no-cache="Set-Cookie" 这个带引号的参数形态在规范里是有定义的:它的意思不是“整份别缓存”,而是“这份可以缓存,但复用给别人之前,请把Set-Cookie这个头字段摘掉”。用途很实在——静态资源上偶尔会挂一个会话Cookie,如果整份存下来发给下一个人,那个Cookie就跟着串了出去。 但规范同时写明:这种带参数的形式只对共享缓存有约束力,私有缓存忽略参数,把它当成一个裸的no-cache来处理。 于是同一行字在两拨听众耳朵里是两个意思。CDN听到的是“存一年,摘掉那个头”;浏览器听到的是“每次用之前都得验证一次”,那个一年的max-age被前面的no-cache直接压掉了。写这一行的人多半只想着前一半。 这类“同一份声明在不同读者那里解析出不同结果”的形态,在响应头这个层面反复出现,248个死字段那次盘点 (https://zhangwenbao.com/http-response-header-dead-fields-audit.html)里还能看到更多化石。 ## 我怎么知道它真的被缓存了,Age这把尺子的边界在哪? 上面好几节的结论都压在Age这一个字段上,所以得先证明这把尺子是准的。Age这个头的定义 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Age)本身很短:由共享缓存填写,单位是秒,含义是这份副本自被存下起过了多久。 方法很笨:同一个URL,隔6秒再打一次,看Age涨不涨、涨多少。如果它是一个诚实的计时器,两次的差值应该约等于我等待的时间。 两次都带Age的24个站 | 结果 | Age变大 | 20个 | Age不变 | 3个 | Age变小 | 1个 | 变大那20个的涨幅 | 最小6秒,中位6秒,最大7秒 | 中位数正好等于我等的秒数,这把尺子可以用。3个不变的是Age本来就极小的站(0秒或1秒),第二次仍在同一秒内。 唯一变小的那个是babybjorn:第一次31566秒,第二次29244秒,倒退了将近39分钟。副本不会返老还童,唯一的解释是两次请求落在了不同的边缘节点上,各自存了各自的一份,年纪不一样。这本身也是个结论:你测到的Age是某一个节点的年纪,不是全球的。 ## 这把尺子测不到的那一半 更要紧的是反过来的情况:不带Age,不等于没被缓存。 115个站里,首页带Age的只有24个,剩下91个不带。但这91个里有72个带着CDN自己的命中标记,取值分布是DYNAMIC 61个、cloudfront的各种MISS 7个,剩下几个是TCP_HIT、HIT一类。这61个DYNAMIC说的是“这次没走缓存,直接回源了”——CDN在场,只是这一次没存。 所以前面那些数字要这么读:11个站是确凿被存过的,而不是“只有11个站的响应会被存”。剩下的多数站,我这一次的请求恰好没命中,或者那家CDN干脆不加Age头。测量能证明发生过什么,证明不了没发生过什么。 要把“被存过多少次”这件事量准,单次抓取不够,得看一段时间的访问记录。服务器日志是唯一说真话的地方,只是那里面的水也不浅——日志里每5次自称谷歌的抓取就有1次IP对不上 (https://zhangwenbao.com/server-log-collection-structured-searchable.html),先把样本清干净再谈统计。 ## 静态资源上那两个出厂值,为什么一个365天一个365.25天? 子资源那一层的数字比首页整齐得多,整齐到能一眼看出模板的边界。 max-age取值 | 换算 | 出现在几个站上 | 平台分布 | 31557600 | 365.25天 | 58 | Shopify,58个全部是 | 31536000 | 365天 | 43 | 横跨7类平台 | 31536000是365乘86400,谁都写得出来。31557600多出来的那21600秒是6小时——也就是把一年按儒略年365.25天算,闰年那四分之一天摊进去了。这个值在58个站上出现,而且平台归因是满分:全部来自同一家。 这类满分归因在响应头审计里出现过不止一次。上一轮那个91.3天的HSTS默认值也是同样的形状:没人管的时候,几十个站异口同声;一旦有人动手改,就改出好几种互不相同的说法。 顺带一提,immutable这个词在样本里出现37处,全在子资源上(CSS 17、JS 14、图片4、图标2),首页一个都没有——这一点大家倒是没搞错,immutable的意思是“这个URL的内容永远不会变”,对一个天天更新的首页说这话等于自找麻烦。 “出厂值原封不动,除非有人动过”这个形态,在响应头之外的地方也一样成立。robots.txt分组不继承那次157个站的实测 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)量的是另一种边界——写在一个分组里的规则管不到另一个分组,而绝大多数站的第二个分组是空的。声明的边界在哪儿,通常不是站长划的,是标准划的。 ## 这行头写歪了,SEO上到底损失什么? 把上面几节的账合并起来看,落到搜索这一侧有三笔。 第一笔是抓取端的响应速度。抓取工具的取样和真人不一样,它对同一批URL的重复访问频率相当高,而边缘命中与回源之间的首字节差距通常在几百毫秒的量级。首页这类被反复抓取的页面如果始终不进共享缓存,这个差价每天都在付。首字节这条线怎么拆成可归因的几段,TTFB与多层缓存那篇 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)拆过一遍。 第二笔是自相矛盾带来的不确定性。当私有指令、共享指令和CDN专用头三份声明同时存在又互相打架时,最终行为取决于路上碰到的是哪一家实现。同一个URL在不同时间点被抓到不同新鲜度的版本,这种波动很难在日志里定位,Vary那次实测 (https://zhangwenbao.com/vary-header-declared-vs-actual-response-variation.html)量到的是同一个病灶的另一个切面:声明的变化维度和实际的变化维度对不上。 第三笔容易被忽略:缓存策略会改变你看到的一切诊断结果。用工具测一个页面,测到的是边缘那份副本还是源站直出,速度报告可以差出一个数量级。这也是为什么同一个站在不同测速工具上得分对不齐——它们打到的不是同一份东西。测量工具本身的偏差怎么排除,HEAD与GET那次对照 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)里有一份现成的清单。 这三笔账都落在同一个终点上,就是页面打开有多快。速度和排名之间的关系被夸大过很多次,真实的权重和优先级页面速度那篇 (https://zhangwenbao.com/page-speed-seo.html)算过;而响应头这一层能撬动的具体开关,X-Robots、缓存与Vary那份机制拆解 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)列得比较全。 ## 自己站上这两拨听众,怎么一次盘清楚? 不需要什么复杂工具,一条命令加4个问题就够了。 先把首页和一个静态资源的响应头都取回来(记得用GET而不是HEAD,有些服务器对HEAD会少给几个字段),然后按顺序问: - Cache-Control这一行里,有没有任何一个词是专门写给共享缓存的?找s-maxage、public、private、proxy-revalidate,MDN那份指令对照表 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)逐条标了谁读谁不读。一个都没有,说明你从没对中间那层表过态。 - 有没有Age字段?有,说明确实被某一层共享缓存存过;数值多大,就是那份副本当时的年纪。没有,再看有没有CDN自己的命中标记头,别把“没测到”当成“没发生”。 - 如果你的意图是“不要存”,写的是no-store还是max-age=0?后者不阻止存,只是让它立刻过期。这两个词的差别在个人化内容上是安全边界,不是风格问题,MDN那份缓存指南 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching)把它们的分工画成过一张图。 - 静态资源上有没有private?有就删掉,你正在把CDN挡在门外,然后自己付回源的流量费。 如果站跑在Apache上,这4件事连同重写规则、规范网址和HSTS往往是同一个文件里的邻居,.htaccess那份分层治理清单 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)把它们的先后顺序排过一遍;跑在Nginx上则要多留一分神,reload每次都通过、抓取却每8次撞一次跳转 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)这种事,配置检查工具是不报的。 还有一件顺手能做的:既然缓存的目的是少传一次字节,那就顺着这条线把条件请求也接上。没改过的页面被对爬虫重发几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html),症结和这里是同一个——你没告诉对方能不能存,它就只能每次全量拿。 4个问题跑完,如果发现要动的地方不止一处,别急着一次全改。缓存这一层的改动有个特点:生效延迟长、回滚成本高、验证窗口窄。保哥自己那台服务器上有过一次很小的教训——为了确认发文后缓存真的清干净了,去数了一遍Redis库里到底有几个键,才发现清的那一层和挡在最前面的那一层根本不是同一个,页面照旧是旧的。那次的排查顺序整理在多层缓存清理顺序 (https://zhangwenbao.com/multilayer-cache-purge-order-and-receipt.html)那篇里,先分清楚有几层、每层归谁管,再决定改哪一行。 把顺序倒过来说更好记:先确定你有几拨听众,再决定对每一拨说什么,最后才是写那一行字。多数站的问题不在于写错了词,而在于从头到尾只想着一拨人。 ## 常见问题解答 ## 写了max-age=0, must-revalidate,我的页面到底会不会被CDN存下来? 会。这一行的准确含义是“可以存,但存下来就算过期,每次用之前必须回源验证”。实测里有11个站写着它,同时带回了Age字段,最长的那份副本已经在边缘放了9小时。如果你的意图是完全不进共享缓存,要写的词是no-store;如果只是不想让共享缓存服务别人,写private。 ## s-maxage和max-age我都写了,浏览器听哪个? 浏览器只听max-age,它会直接忽略s-maxage;CDN和代理反过来,s-maxage对它们优先级更高。这就是这个词存在的意义——让两拨听众拿到两个不同的数字。如果你把这两个值写成一样的,那么删掉s-maxage行为完全不变,实测样本里有2个站就是这种写法。 ## 不写Cache-Control,是不是就等于不缓存? 不是,正好相反:不写等于把决定权交给对方。规范允许缓存在没有明确声明时自己估一个寿命,通常拿Last-Modified来推算。实测中一半的站(58个)在首页上什么都不写,而其中只有3个提供了Last-Modified——剩下的连让对方估算的材料都没有,具体行为完全取决于那家CDN的默认策略。 ## private写在CSS、图片这类静态资源上,有什么后果? 后果是共享缓存不再为你分发这份文件,所有请求都要回到源站。你付了CDN的钱,却只用到了转发功能。实测里有10个站的CSS上写着private,其中9个还同时写了stale-while-revalidate——而后者恰恰是只有共享缓存才会执行的动作,一行字里前后互相拆台。 ## 响应头里没有Age,是不是说明这个页面没被缓存过? 不能这么推。Age只由共享缓存自己填,没命中的时候本来就不会有;而且有些CDN即使命中也不加这个头。实测的115个站里,91个不带Age,但其中72个带着CDN自己的命中状态标记,说明CDN确实在链路上,只是这一次没走缓存。判断“有没有被缓存过”要靠多次取样,单次结果只能证明发生过什么,证明不了没发生过什么。 ## CDN-Cache-Control这个头需要我自己加吗? 看你用哪家CDN,以及你是不是真的需要对两层说不同的话。它的价值在于把边缘策略和浏览器策略彻底分开——比如让边缘存一小时、浏览器完全不存。实测中发这个头的48个站全部出自同一个建站平台,取值一字不差,说明它更多是平台的出厂设定而非店主的选择。自建站点如果没有明确的分层需求,先把Cache-Control里的s-maxage用起来更划算,兼容面也更广。 ## 怎么快速判断一个响应是从边缘来的还是从源站来的? 三个信号一起看:Age字段(有值说明是缓存里的副本)、各家CDN自己的状态头(cf-cache-status、x-cache、x-vercel-cache这类,取值是HIT还是MISS或DYNAMIC)、以及连续几次请求的首字节时间是否稳定。单看任何一个都可能被误导,尤其是DYNAMIC这种取值,它说的是“这次没缓存”,不是“这个站没接CDN”。 ## 权威参考资料 ## 站内搜索页SEO:搜不到商品那一页,一半站允许被收录 - URL:https://zhangwenbao.com/site-search-empty-result-indexability-audit.html - 分类:技术SEO - 发布:2026-08-18 | 更新:2026-09-06 - 摘要:一个卖户外家具的独立站,GSC里被收录的页面数比商品数多出四千多个,点开一看全是搜索地址。站长以为被人刷了,翻完日志才发现是自家热搜词模块和几条外链带进去的,而站点每次都规规矩矩回了200。 - 关键词:技术SEO,抓取预算,索引控制 > **TLDR**:摘要:拿一个不存在于任何语言的乱码词去搜131个英文大站,剔掉根本没在搜的那批之后,40个站能判定。结果是40个全部返回200,一个404都没有。真正分岔的地方在后面:只有42.5%的页面带noindex,9个站的canonical直接指回这个带乱码参数的地址本身,robots.txt里禁了自己搜索路径的占41.7%。把这三样按平台一分组,答案就浮出来了——Shopify那批robots.txt中位104行、有7条指令覆盖六成以上的站,而认不出平台的那24个站中位只有26行、最高一条指令的覆盖率是12.5%。这一页允不允许被收录,多数站主根本没做过这个决定。 > 摘要:拿一个不存在于任何语言的乱码词去搜131个英文大站,剔掉根本没在搜的那批之后,40个站能判定。结果是40个全部返回200,一个404都没有。真正分岔的地方在后面:只有42.5%的页面带noindex,9个站的canonical直接指回这个带乱码参数的地址本身,robots.txt里禁了自己搜索路径的占41.7%。把这三样按平台一分组,答案就浮出来了——Shopify那批robots.txt中位104行、有7条指令覆盖六成以上的站,而认不出平台的那24个站中位只有26行、最高一条指令的覆盖率是12.5%。这一页允不允许被收录,多数站主根本没做过这个决定。 这件事是被一个GSC截图勾起来的。一个卖户外家具的独立站,被收录的页面数比他们的商品数多出四千多个,点进覆盖率报告一看,一长串地址长得都差不多,全是/search?q=开头。 站长的第一反应是被人刷了。但翻日志会发现更普通的解释:那些地址是站内自己的搜索建议、外链、还有以前某个促销活动的落地页留下来的,爬虫顺着链接一路爬进去,站点每次都老老实实回了一个200。 我想知道这是个案还是常态,于是编了个词去问131个站。 ## 搜一个世界上不存在的词,站点会回什么? 用的词是zqxjkvbnmqp7,随手敲的,确认过任何一个站都不可能有这件商品。为了排除偶然,我还准备了第二个乱码词wfrhtygdlpz3,以及一个几乎必然搜得到的词black做对照。 131个站里,首页能正常访问的70个。这70个里,能找到搜索路径并拿到回答的69个。绝大多数站的搜索地址是/search?q=,只有一个用的是WordPress那套/?s=。 探测这一步本身也有点信息量。我按五种常见形态挨个试过去:/search?q=拿到49次200和17次404,/?s=拿到20次200,还有几次撞在限流上。也就是说有相当一批站压根没有/search这条路径,请求要么被路由到别处,要么直接404。写这类批量脚本时不能一刀切认定路径,得先探再问,否则统计出来的全是噪声。 然后是这次最要紧的一步过滤,它决定了后面所有数字算不算数。 ## 怎么确定它是真的在搜,而不是随便给了我一页? 判据只有一条:换一个必然搜得到的词,它的回答必须跟着变。如果搜black和搜一串乱码拿到的HTML一模一样、连标题都跟首页相同,那这个站压根没在搜,只是把某个固定页面塞给了我。 按这条判据把69个站分成三类: - 回落到固定页面:29个。搜什么都给同一页,标题跟首页一字不差。这批站被整体剔出分母。 - 搜索页但结果靠JavaScript填:22个。标题会变,但HTML里搜到和搜不到几乎没差别。 - 服务端把结果写进HTML:18个。换个词,字节跟着变。 后两类合起来40个站,是这篇里所有比例的分母。 被剔掉的那29个站不是就没事了,恰恰相反,它们的形态更粗糙:一个能填任意字符串的地址,填什么都返回同一份HTML,连标题都跟首页一模一样。这等于把重复内容的产能直接开到最大,只是这批地址通常没什么链接指向,爬虫发现得慢一点而已。想知道自己是不是这一类,办法就是上面那条判据——拿一个必然有的词和一个必然没有的词各请求一次,比一比两次响应的字节数。 自基线跑了三条,结果比我预期的干净。同一个乱码词连着请求两次,40个站状态码全部一致,字节相对差的中位数是0.0000、最大0.002。换成第二个乱码词,状态码仍然40个全部一致。把搜索词本身抹掉之后比对标题模板,40个站的两次结果一模一样——说明这一页确实是按模板生成的,不是碰运气。 这套过滤器是从上一次做错误页那批实测 (https://zhangwenbao.com/404-page-crawl-budget-byte-audit.html)里搬过来的思路:判断一个东西开着之前,得先证明这个站会说“没有”。这次的版本更严一点,因为搜索页天生就会返回200,光看状态码什么都判断不出来。 ## 那40个站,搜不到东西的时候回了什么状态码? 全部是200。没有一个站返回404,也没有一个返回410或者其它任何非200。 这件事本身不算错。搜索结果为空跟地址不存在是两回事,语义上200是对的——这个地址确实存在,只是这次查询没匹配到东西。MDN对404的定义 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404)说得很清楚,它描述的是资源不存在,不是结果为空。 问题在于,一个稳定返回200的地址模板,配上一个可以填任意字符串的参数,等于给了外界一个无限生成可索引页面的入口。这一页能不能被索引,就成了唯一的闸门。 顺带记一下这批页面的体量:解压后中位数409KB、压缩后69.8KB。超过512KB的16个站,超过1MB的8个站,最大的两个是misen.com的5.55MB和burrow.com的4.45MB。页面上的链接数中位97条,最多的一个站挂了1694条;脚本数中位29个,最多137个。响应耗时中位1550毫秒,最慢的一个跑了8503毫秒。 这些数字跟样式表那篇 (https://zhangwenbao.com/css-coverage-unused-rules-audit.html)算的是同一类账:一个什么内容都没产出的页面,仍然要把整套站点外壳原样端一遍——导航、页脚、几十个第三方脚本、上百条链接,一个不少。真要看单份响应有多大是不是踩了抓取上限,抓取体积那套工具 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)比肉眼估更准。 ## 搜到和搜不到,爬虫能看出区别吗? 这是我没想到的一格。把每个站“搜得到的词”和“搜不到的词”的HTML体积摆在一起比,字节比的中位数是1.00——两次响应几乎一样大。40个站里只有6个的空结果页比有结果页更大。 原因就是前面分类里那22个站:结果由前端脚本填进去,服务端吐的HTML是同一副骨架。这意味着不执行JavaScript的那一遍抓取,拿到的确实是同一份文件,无论参数里是什么。框架站的渲染模式 (https://zhangwenbao.com/react-nextjs-framework-seo-rendering.html)会直接决定这件事,而空壳页面那篇 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)量过同一个现象在首页上的表现。 回显情况也值得看。40个站里有24个把搜索词原样写进了正文,占60%;写进的只有7个,占17.5%。写进标题的那批风险更实一点,因为标题是搜索结果里最显眼的一行。 标题模板的重合度也说明问题。把搜索词抹掉之后,40个站一共只有29种不同的标题,其中4种出现在两个以上的站上。最集中的一组有7个站,标题就是干巴巴一个单词Search——allbirds、arcteryx、article、buckmason、quince、swarovski、theordinary。另有4个站压根没输出标题:aliexpress、kotn、on.com、temu。剩下两组各两个站,分别是小写的search和Search Results。 这些公司彼此没有关系,做的品类也不挨着,标题却一字不差。原因不复杂:他们用的是同一套主题模板,而模板作者在search.liquid里写了什么,商家多半没去看过。一个只写着Search的标题如果进了索引,在搜索结果里跟别人的完全一样,谁也认不出是哪家。 再往下拆一层,这40个站按平台分是Shopify 17个、认不出平台11个、Next.js 6个、Salesforce 6个。Shopify占了将近一半,这批站的行为高度一致,也正是下一节能拆出归属的原因。 ## 这一页准备好被搜索引擎收录了吗? 三样东西可以拦住它:页面上的noindex、canonical指向哪里、robots.txt里有没有那一行。逐个数。 闸门 | 做了的站 | 占比 | 页面带noindex(meta或响应头) | 17/40 | 42.5% | canonical指向不带词的搜索页 | 20/40 | 50.0% | canonical指回这个带词地址自己 | 9/40 | 22.5% | 完全没有canonical | 6/40 | 15.0% | robots.txt禁了自己这条搜索路径 | 15/36 | 41.7% | 只有四成出头的页面明确说了别收我。noindex这17个里,14个写在meta标签上,7个走的是响应头X-Robots-Tag,有几个两样都写了。这两种写法的适用场景在机器可读端点那篇 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)里分过,对HTML页面来说两者等效,写哪个都行。 把noindex这一栏也按平台拆开,顺序跟后面robots.txt那张表几乎是反的:Salesforce是5/6,比例最高;Shopify 8/17;Next.js 2/6;认不出平台的只有2/11。Salesforce那批robots.txt写得最长、却最少去禁搜索路径,反倒在页面上把noindex补齐了;Shopify正好掉个个儿。两条路都能走通,但各自漏掉的场景不一样:robots禁抓挡不住已收录页面的清理,页面上的noindex挡不住抓取预算被消耗。这笔预算怎么算,跟条件请求那篇 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)算的是同一本账。 canonical那一栏更值得琢磨。有9个站的canonical直接指回/search?q=zqxjkvbnmqp7这个地址本身——canonical的语义 (https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls)是“这是这组重复内容里的首选版本”,指回自己等于主动告诉搜索引擎:这个带着乱码参数的地址,就是它自己那组内容的规范版本。这9个站是allbirds、avocadogreenmattress、awaytravel、canyon、cybex-online、misen、monos、suitsupply、theordinary。 把三样叠在一起看,全都没做的只有theordinary.com一个站:200、canonical自指带词、没有noindex、robots.txt也没禁。这个数字比我预想的小,说明大多数站至少挡住了一层。但“至少挡住一层”和“想清楚了该怎么挡”,差得远。 ## 这三样闸门,到底是谁配上去的? 这是我做这次统计真正想问的。判据很简单:同一个平台里,一条规则的覆盖率越高,它越可能来自出厂模板而不是某个人的决定。 59个站有robots.txt,全文没有任何两份是逐字相同的。但按平台分组数指令覆盖率,形态就出来了: 平台 | 站数 | robots.txt行数中位 | 覆盖六成以上站点的指令条数 | 禁了/search的比例 | Shopify | 13 | 104 | 7条 | 76.9% | Salesforce | 8 | 112 | 1条 | 50.0% | Next.js | 11 | 32 | 0条 | 18.2% | 认不出平台 | 24 | 26 | 0条 | 20.8% | Shopify那13个站里,Disallow: /account出现在84.6%的站上,/admin、/orders、/checkout、/cart各76.9%,/carts和/search各69.2%。还有一批更冷门的,比如/collections/*%2b*——那是把加号URL编码之后的写法,用来挡分面筛选生成的组合地址。 没有一个店主会自己想出要拦截百分号2b。这一整套是Shopify的robots.txt.liquid模板出厂就带的,商家不动它,它就一直在那儿。 反过来看认不出平台的那24个站:中位26行,最高一条指令的覆盖率只有12.5%,也就是24个站里有3个写了同一条。这批站的robots.txt是各写各的,没有共同来源。同样地,Next.js那11个站中位32行、零条高覆盖指令。 Salesforce那8个站有意思:行数中位112行,跟Shopify差不多长,但只有Disallow: /这一条覆盖过六成。它们高频出现的是/*prefn2*、/*srule*、/*pmax*这类分面参数的通配符,覆盖率在25%到37.5%之间——像是从同一份官方建议里各抄了一部分,抄的程度不一样。 把这张表倒过来读就是本文的答案:你的搜索页被不被robots.txt拦住,跟你用的平台高度相关,跟你自己关系不大。Shopify商家里有76.9%拦住了,不是因为他们比别人更懂SEO,是因为模板里本来就写着;自建站那批只有20.8%拦住,也不是因为他们更粗心,是因为没有任何人在他们的robots.txt里预先写好那一行。这跟robots指令有没有人读 (https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html)那篇的发现是一枚硬币的两面:那边是写了没人读,这边是压根没人写。 顺带说一句,Shopify的搜索模板本身在主题模板文档 (https://shopify.dev/docs/storefronts/themes/architecture/templates/search)里是可以改的,主题作者完全可以在空结果时输出noindex。数据里Shopify有8/17带了noindex,说明确实有一部分主题这么做了,另一部分没有。同一个平台上的商家,命运取决于当初买了哪套主题。 ## 一个不设防的搜索页,最后会长成什么样? 三条路径,按发生概率排。 第一条最常见:自己人喂出来的。站内搜索的热搜词模块、导航里的快捷入口、邮件营销里带搜索参数的落地页,都会生成真实的内链,爬虫顺着就进去了。开头那个户外家具站四千多个多余页面,绝大部分是这么来的。 第二条是外部链接。别人在论坛、社媒里贴了一个带搜索参数的地址,这个地址就进了发现队列。你删不掉别人的链接,只能在自己这一端处理。 第三条是被人用来生成内容。搜索词回显进页面,尤其是回显进标题,理论上就可以被外部构造出成千上万个“有内容”的页面。本次样本里有7个站把词写进了标题。这不是漏洞,也不会直接导致处罚,但它把这批页面的数量上限从有限变成了无限。 三条路径最后落到同一个后果上:一批内容高度雷同、对用户没有独立价值的页面进了抓取队列。薄内容那篇 (https://zhangwenbao.com/thin-content-scaled-abuse-diagnosis-fix.html)讲过判定逻辑,电商重复内容 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)那篇里这属于八类成因中的参数变体一类。抓取预算这本账则要对着日志算,日志分析 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)那篇里的做法可以直接照搬——先数一数爬虫每天在/search上敲多少下。 保哥手上有个做宠物用品的客户,当初查这件事花了半天,办法很笨但有效:把三个月的日志按路径聚合一遍,/search?q=这一段占掉了爬虫总请求的11%,而这些地址带来的自然点击是零。腾出来的额度,两周内就体现在新品的收录速度上了。要注意这跟分面筛选 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)产生的地址爆炸不是一回事:那边是组合爆炸、量级更大,这边是单参数、但取值无限。两者常常同时存在,得分开数。 ## 该怎么办,先动哪一样? 按见效速度和风险排,顺序是这样的。 先做noindex,它比robots.txt更该优先。这两件事经常被当成同一件事,其实不是:robots.txt管的是“别抓”,noindex管的是“别收”。Google对noindex的说明 (https://developers.google.com/search/docs/crawling-indexing/block-indexing)里有一条关键的注意事项——如果你用robots.txt禁止抓取,爬虫就读不到页面上的noindex,这个地址反而可能因为外链而以无标题的形式留在索引里。想清除已收录的,必须先让它能抓、读到noindex,收干净之后再考虑要不要禁抓。这个先后关系在noindex与canonical那篇 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)里按九种场景拆过。 第二步是把canonical改成指向不带参数的搜索入口,或者干脆去掉。指回自己是最坏的一种,等于替这个地址背书。要注意canonical只是建议不是指令,Google最终选哪个 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)有它自己的一套决策逻辑,别指望这一条就能解决问题。 第三步才轮到robots.txt。写法上RFC 9309 (https://www.rfc-editor.org/rfc/rfc9309.html)规定的匹配规则跟很多人的直觉不一样,通配符和路径前缀的判定容易写错,动手前值得对着规则生成器那篇 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)核一遍。方案层面的四种选择——Disallow、noindex、canonical、静态化——站内搜索URL该不该屏蔽 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)那篇有一张完整的选型矩阵,本文只是给它补了一组横向实测数据。 第四步,把这件事挪到监控里。GSC的覆盖率报告里按路径筛/search,看有多少地址处于已收录或已抓取未收录的状态。这个数字应该逐月下降,不降就说明前三步有一步没生效。索引覆盖状态那篇 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)解释了每种状态各代表什么。 还有一种情况这套顺序完全不适用:站上根本没有robots.txt。首页正常的70个站里有11个是这样,包括allbirds、misen、monos这几个不算小的牌子。没有这个文件本身不是错误,默认就是全部允许;但它意味着连“我这里有一份没人管过的默认配置”这个认知都不存在。这类站要挡搜索页,只能靠页面上的noindex,没有第二条路。 另外提一句本次样本的分布:59份robots.txt里,最长的431行,最短的只有1行,中位数53行。长短之间差了四百多行,而这个差距的绝大部分不是谁比谁更用心,是平台模板的长度差。 还有一件顺手能做的事:去数一数自己robots.txt有多少行,再数一数其中有几行是自己加的。如果你用的是Shopify,那份文件大概率一百行出头,而你写的可能是零行。这不是问题,模板写得挺好;问题是你不知道它写了什么,于是也不知道它漏了什么。 ## 什么情况下反而不该屏蔽搜索页? 有两种,值得单独说,因为一刀切屏蔽也是错的。 第一种是搜索页本身就是有价值的落地页。有些站把高频搜索词做成了静态化的结果页,配了独立的标题、描述和编辑推荐语,这类页面跟普通分类页没有区别,屏蔽掉纯属自断一臂。判据是:这个页面有没有人工编辑过的内容,有没有稳定的地址,会不会因为库存变化而变成空页。三条都满足才留。 第二种是站内搜索数据本身的价值。就算页面屏蔽了,搜索词的日志也该留着——那是用户用自己的话告诉你他们想要什么,是关键词研究里最便宜也最准的一手来源。屏蔽的是页面进索引,不是关掉这个功能。 最后提醒一句风险。给搜索页加noindex之前,先确认你的搜索路径没有被别的东西复用。有些主题把分类页、标签页也走同一套模板,改模板的时候容易一起波及。改之前把/search下面所有正在被收录的地址导出来看一眼,别把该留的一起关掉。这一步跟改版前的地址盘点 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)是同一个动作。 ## 常见问题解答 ## 搜索结果为空,应该返回404吗? 不应该。404描述的是这个地址不存在,而搜索页是存在的,只是这次查询没命中。返回200在语义上是对的,本次40个站也全部返回200。真正需要处理的不是状态码,是这一页要不要进索引,那是noindex和canonical该管的事。少数站会在空结果时跳转到一个提示页,那样做会额外制造一次跳转,不如原地返回200加noindex干净。 ## 用robots.txt禁掉搜索路径就够了吗? 不够,而且顺序容易搞反。robots.txt禁的是抓取,被禁之后爬虫读不到页面上的noindex,已经收录的地址可能反而清不掉、以无标题的形式留在索引里。正确顺序是先允许抓取、让它读到noindex,等索引清干净之后再决定要不要禁抓。如果站上完全没有已收录的搜索页,直接禁抓也可以。 ## 怎么知道我的站有没有这个问题? 两步。第一步用curl请一个必然搜不到的乱码词,看返回的状态码、meta robots和canonical;第二步去GSC的页面报告里按路径筛搜索路径,看被收录了多少个。第二步的数字是决定要不要动手的依据——如果本来就是零,前面那些配置怎么写都不着急。 ## 搜索结果靠JavaScript渲染,是不是就没这个问题了? 不是,反而多一层麻烦。本次22个站属于这种情况,它们搜到和搜不到返回的HTML体积几乎一样,字节比中位数1.00。对不执行JavaScript的那一遍抓取来说,这些地址返回的是同一份文件,等于凭空制造了一批完全重复的页面。索引指令该配还是得配。 ## canonical指回带参数的地址自己,有多严重? 不算漏洞,但它取消了canonical本该起的合并作用。canonical的意思是“这组重复内容里选我”,指回自己等于宣布这个带乱码参数的地址是一个独立的规范页面。本次有9个站是这样。稳妥的做法是指向不带查询参数的搜索入口,或者在这一页上干脆不输出canonical,让noindex去起作用。 ## 为什么有29个站被剔出了统计? 因为它们没有在搜。判据是换一个必然搜得到的词,回答完全不变、标题跟首页一字不差——这说明请求被路由到了某个固定页面,不是搜索结果。这类站占了69个里的29个,比例不低。如果不做这一步过滤,它们会被当成“回了200的搜索页”一起统计,把结论污染掉。 ## 我用的是Shopify,是不是就不用管了? 不是。数据里Shopify商家禁了搜索路径的比例是76.9%,确实比自建站的20.8%高得多,但那意味着还有将近四分之一没禁。而且noindex这一项,17个Shopify站里只有8个带了,取决于当初买的主题怎么写。花两分钟curl一下自己的搜索页,比猜测靠谱。 ## 权威参考资料 ## robots.txt指令有没有人读?35.7%的站白写了 - URL:https://zhangwenbao.com/robots-txt-directive-no-receiver-audit.html - 分类:技术SEO - 发布:2026-08-17 | 更新:2026-08-17 - 摘要:你在robots.txt里写下的那一行,收件人可能早就不在了。Crawl-delay、Noindex、Host这些字段今天分别还有谁在读?157个真实独立站的文件给出了答案。 - 关键词:robots.txt,技术SEO,独立站运营,爬虫管理 > **TLDR**:摘要:157份真实robots.txt逐行拆开,56个站(35.7%)至少写着一条没人读的指令,合计146条。Crawl-delay最典型:47个站写了129行,只有16行落在会读它的爬虫能看到的位置,另有2行直接写给了明确说过不读它的Googlebot。还有10个站在写Host,收件人是一个自己都弃用了它的搜索引擎;2个站在写Noindex,这条路Google在2019年9月1日就关了。这些行不报错、不消失,也没有工具会提醒你。 > 摘要:157份真实robots.txt逐行拆开,56个站(35.7%)至少写着一条没人读的指令,合计146条。Crawl-delay最典型:47个站写了129行,只有16行落在会读它的爬虫能看到的位置,另有2行直接写给了明确说过不读它的Googlebot。还有10个站在写Host,收件人是一个自己都弃用了它的搜索引擎;2个站在写Noindex,这条路Google在2019年9月1日就关了。这些行不报错、不消失,也没有工具会提醒你。 先说一件反直觉的事:一条规则失效的时候,它不会告诉你。 代码写错了会抛异常,配置填错了服务起不来,证书过期了浏览器会拦在前面。这些失败都有声音。可robots.txt里一条指令失效,没有任何声音。文件照样返回200,语法照样正确,那一行字照样躺在原地,你每次打开都能看见它。唯一变了的东西,是它不再有任何效果——而这件事,文件本身不会写给你看。 这次把211个海外品牌独立站的robots.txt全抓了一遍,一行一行按标准语义拆开,就是想看看这种沉默的失效到底有多普遍。结果比预想的更值得说:问题不在于有人写错了语法,而在于几乎所有人都默认,写下去的规则会有人读。 ## 一条指令写下去之后,究竟是谁负责读它? robots.txt有一件特别容易被忽略的性质:它不是配置文件,它是一封公开信。 同一件事该用哪个手段也常被搞反,robots.txt和meta robots各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)里有清楚的分工。 这份文件写废了的后果不小,整站从谷歌搜索结果里消失的那类事故 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)就是最直接的样本。 配置文件的接收方是你自己的程序,改完重启就生效,生效与否有明确的反馈。而robots.txt的接收方是别人的爬虫,几百家,各写各的解析器,各有各的支持清单。你把文件放上去,谁来读、读到哪一行、读懂几个字段,全部由对方决定。你能做的只有一件事:把话说清楚,然后等。 ## 效力不在语法里,在对方的解析器里 这就带来一个和普通配置完全不同的判断方式。一条指令有没有效,跟它写得对不对关系不大,跟谁读它关系很大。同一行字,在Bing那里生效,在Google那里被跳过;同一个字段,五年前有人读,今天没人读了。文件本身一个字都没变,效力却已经变了。 要弄清对面到底是谁,120种爬虫UA的分类与真假验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)是个可以直接照做的方法。 生成器给的预设并不总跟规范对齐,通配符判定会和标准打架的那几种情况 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)值得先看一眼。 这种变化的方向几乎总是单向的:字段会被弃用,爬虫会退役,支持清单会变短。很少有哪个搜索引擎宣布,从今天起我们开始读一条以前不读的老指令。 ## 这个文件没有版本号,也没有兼容性声明 更麻烦的是,robots.txt连一个声明兼容性的地方都没有。它没有版本号,没有schema,没有类似HTML里那种文档类型声明。爬虫排除协议在2022年才有了正式的标准文档,编号RFC 9309,而在那之前的二十多年里,各家一直在事实标准上各自加料。加进去的那些字段,有的进了标准,有的没进,有的进了又被移出去。 这些字段各自作用在哪一环,抓取、索引、排名三步的分工 (https://zhangwenbao.com/how-search-engines-work-crawl-index-rank.html)讲得比较完整。 结果就是,你打开一份陌生的robots.txt,光看内容根本判断不出哪些行是有效的现役规则,哪些行是历史沉积。它们的排版、语法、缩进完全一样。 ## 沉默不是缺陷,是标准明文要求的行为 这里有个关键机制,弄清它之后前面所有现象就都顺理成章了。 判断某项标记有没有人读也是同一个问题,结构化数据对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)里有官方说法和实测。 同样的沉默在结构化数据里更狠,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)而页面照样正常显示。 爬虫排除协议的正式标准里有一条明确规定:解析器遇到自己不认识的字段,必须忽略它,继续处理后面的内容。不是报错,不是中止,是静默跳过。 这条规定是有道理的。robots.txt是给几百个互不相干的实现读的公开文件,如果某个实现遇到陌生字段就报错或者中止,那么任何一家新增一个私有扩展,都会让别家的解析器集体失灵。为了让这个生态能往前走,标准必须要求大家对陌生的东西保持宽容。 但同一条规定,从写文件这一端看,效果就变了:你写下任何一个不存在的字段名、任何一个拼错的指令、任何一个已经作废的老写法,所有爬虫都会礼貌地跳过它,一句话都不会说。沉默不是没人发现,是标准要求它们不许出声。 ## 这个文件的年纪,也解释了为什么这么乱 顺着标准往回看一段历史,也有助于判断某个字段的成色。 拿这个文件去解决它管不了的事很常见,用robots.txt拦UTM参数的危害 (https://zhangwenbao.com/robots-txt-disallow-utm.html)就是一例。 这套机制1994年就出现了,最初是一封邮件列表里的提案,靠各家自愿遵守运转了二十多年,一直是事实标准而非正式规范。2019年,Google把自己用了二十年的解析器开源,同时向标准化组织提交了草案;2022年,这份草案正式成为编号RFC 9309的标准文档 (https://www.rfc-editor.org/rfc/rfc9309.html)。 标准落地时做的事很克制:只把User-agent、Allow、Disallow这三个字段写进规范,加上一条未识别字段必须忽略的规则。二十多年里各家加过的其他字段,一个都没进去。 这段历史给出一个很实用的判断依据。要确认Google会怎么读你的文件,不用猜也不用只靠在线工具——它的解析器是开源的,可以拿自己的文件在本地跑,得到的是官方实现的真实判定结果。后面会给出用它做差分验证的具体办法,那是本文能提供的最硬的一个动作。 ## 公开信的另一面:写进去的路径谁都能看 把它当公开信还有一层后果,跟收件人问题正好互补:这封信不是只有收件人能读,任何人都能读。 这意味着写进Disallow的每一个路径都是一次公开告示。你想挡住的那个后台入口、那个内部工具页、那个还没发布的活动目录,写进去之后就成了一份索引——想找的人不用扫目录,直接读你的robots.txt就行。 这就构成一个很尴尬的组合:对不遵守规则的抓取程序,这个文件毫无约束力;对想找入口的人,它是一份现成的清单。守规矩的爬虫会绕开,不守规矩的正好照着来。 所以路径要不要写进去,判断标准是它暴露之后有没有风险。纯粹为了省抓取预算的路径,比如筛选参数、站内搜索结果、加入购物车的地址,写进去没问题——它们本来就在页面链接里,不算秘密。真正需要保护的地址不该出现在这个文件里,它们该走访问控制:登录校验、来源限制、地址段白名单。这些手段跟robots.txt的区别是,前者由你的服务器执行,不需要对方配合。 本文前面那几个把管理后台入口写进Disallow的站,其实同时踩了两件事:那个地址在它们自己的域名下压根不存在,所以规则毫无意义;而如果它真的存在,写进去反而是主动指路。两头都不划算。 ## 三种没有收件人的写法,代价完全不同 把这次的数据摊开之后,无效的行其实分得很清楚,一共三种。 边缘层的拦截效果也没那么确定,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测出来的答案挺意外。 真要拦住某类爬虫得分层来,robots、UA识别、WAF三层的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比只改一个文件靠得住。 第一种是对方公开退出了:这条指令曾经有人读,读它的那一家发过公告说不再支持。这种最容易查,因为公告是公开的、有日期的,查一次文档就有答案。 第二种是对方从来没打算读:这条指令在某一家那里是有效的,你却把它写在了另一家的分组里。规范没错,语法没错,只是寄错了地址。这种查起来要多一步,你得先知道每个字段各自的支持者是谁。 第三种最新,是对方还没来:字段是今年才有人提出来的,提出的那一方希望大家读,但真正承诺读它的还只有几家。这种严格说不算失效,算尚未生效,可从效果上看,跟前两种没有区别。 ## 为什么这类问题在任何工具里都不报错 三种写法有一个共同点,这也是它们能长期活下来的原因:所有校验工具都不会报错。 有些检查天生只能看表层特征,十二项语言特征怎么拆 (https://zhangwenbao.com/ai-detector-12-signal-humanize-guide.html)是另一个例子。 这类没人报错的欠账攒起来相当可观,技术债怎么排查和分批还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了一套可执行的顺序。 常规全站审计能覆盖的范围有边界,桌面爬虫能查出的12类问题清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)可以对照看缺了哪一块。 robots.txt的测试工具、平台后台的编辑器、各类SEO插件的体检模块,检查的都是语法层面的事——路径写没写错、通配符用没用对、分组有没有匹配到自己。它们不检查、也没法检查一件事:这一行的收件人还在不在。因为收件人在不在,不是文件里的信息。 于是这些行就留下来了。留一年、三年、五年,穿过几次改版、几次迁站、几任负责人。保哥翻过一个户外装备品牌的建站记录,那份robots.txt从2019年到现在改过11次,每次都是在文件末尾追加新规则,没有任何一次是打开文件从头读一遍——这非常正常,正常到几乎所有站都是这么维护的。 ## 157份robots.txt里,究竟有多少行是白写的? 先把样本和口径说清楚,因为这次的分母本身就出过一次问题。 至于哪些页面真该挡,电商该屏蔽的七类页面 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)里有逐类的判断依据。 同一批157份文件还量过另一件事,给单个爬虫开组会丢掉通配组全部规则 (https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html)的中招比例高得离谱。 ## 211个域名,两类文件必须先剔掉 抓取对象是211个海外品牌独立站的主域名,请求/robots.txt,跟随重定向,超时20秒,裸域拿不到就换www再试一次。回来的状态码分布很分散:200有168个,403有21个,连不上13个,404有4个,429有3个,另有400和301各1个。 首页本身能不能被读到也量过,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)。 同一批域名上做过的另一项实测是,142个站里只有52个回得出304 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)。 168份里还得再剔一层。有9份的状态码是200,正文却是一整页HTML——路由没为这个路径准备处理,请求落到了单页应用的兜底页上。这9份对爬虫来说等同于空文件,也就是全部允许抓取,但它比404更难被发现,因为监控只看状态码的话,200看起来完全正常。 剔掉之后,有效样本157份。下面所有比例的分母都是157。 ## 尺子先失效了一次:把403的响应体也当成了规则 这里有个必须交代的返工。第一遍统计的时候,分母算出来是161,比157多了4。原因很朴素:统计脚本是按目录里的文件枚举的,而抓取脚本无论状态码是多少都把响应体落了盘。于是403页面里那几行纯文本、429返回的限流提示,全都被当成robots.txt参与了统计。 用别人的工具时更该先校准,第三方数据准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 量错口径这种事非常常见,量出74%的页面有差异,补上对照组后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)是同一类返工。 差4份不影响结论方向,但它是这类工作里最典型的一种错:用文件系统里有什么当分母,而不是用抓取记录里成功了哪些当分母。后来改成先按状态码筛出成功清单,再按清单去读文件,数字才对上。 说白了,量别人配置里的失效之前,得先确认自己的尺子没失效。这句话在这个项目里已经不是第一次应验了。 ## 结果:56个站、146条、中位数2条 157份文件里,至少有一条指令属于上面三种情况之一的,有56个站,占35.7%。合计146条。 这类零散错误集中在几个固定位置,电商站十二类高频坑的诊断修复 (https://zhangwenbao.com/ecommerce-seo-common-mistakes.html)可以照单排查。 这种零星失分往往在第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验的汇总。 按每站条数看,中位数是2条,也就是说踩到的站通常不是系统性写错,而是零星留了一两行。少数几个站留得比较多:italic.com有7条,awaytravel.com和wayfair.com各6条,eufy.com有5条。 ## 字段名一共只有9种,问题全部发生在这9种里面 有个数字挺意外:157份文件里出现过的字段名,去重之后只有9种。 字段少不等于没得做,把FAQ这类标记用对的八步 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)也是在有限字段里做深。 字段之外还有例外规则要留意,通配组的星号对广告爬虫不生效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)就是最容易漏的一条。 字段 | 出现在几个站 | 合计条数 | 今天谁在读它 | Disallow | 155 | 10017 | 所有主流爬虫 | Sitemap | 145 | 729 | 主流搜索引擎,全局生效不属于任何分组 | Allow | 91 | 1874 | 所有主流爬虫 | Crawl-delay | 47 | 129 | Bing认,Google明确不读,第三方工具各有各的口径 | Host | 10 | 10 | 原为Yandex专用,Yandex已弃用 | Noindex | 2 | 7 | 无。Google于2019年9月1日停止支持 | Content-Signal | 2 | 2 | 2025年才提出,承诺读它的还只有少数几家 | Llms | 2 | 2 | 无任何厂商承诺,属民间约定 | Llm-Policy | 1 | 1 | 同上,且与上一行是同一个想法的两种拼法 | 这张表其实就是全文的骨架。前三行是现役规则,占了全部行数的绝大多数;中间三行是本文要讲的沉默失效;最后三行是刚出生还没有收件人的新写法。 ## 没有拼写错误,这件事本身值得说一句 值得注意的是,9种字段名里一个拼写错误都没有——没有Disalow,没有User-agents,没有把冒号写成等号的。157份文件、12771行指令,语法层面干净得出乎意料。 真出语法级问题时症状反而很明显,一个看不见的字节头就能让页面白屏 (https://zhangwenbao.com/notepad-edit-saved-code-generate-bom-resulting-web-page-error-white-screen-solution.html)是另一种极端。 这从侧面印证了前面那个判断:出问题的地方从来不是语法。语法有人管,编辑器会提示,平台会校验,抄来的模板本身也是对的。没人管的是收件人。 ## 12771行里,绝大多数在做同一件事 把这12771行按字段拆开看比例,能看出这个文件真正的用途分布。 需要挡的地址里最难缠的是筛选组合,分面导航产生的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)单独讲过一遍。 这一万多条禁止规则最终服务的目标是预算,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)按优先级排过序。 Disallow一项就占了10017行,78.4%;Allow 1874行,14.7%;Sitemap 729行,5.7%。这三项加起来99%不到一点。剩下的一百多行才是本文讨论的对象——Crawl-delay 129行,Host 10行,Noindex 7行,加上5行新字段。 换个说法:robots.txt在现实里几乎是一个单一用途的文件,它绝大部分内容在回答哪些地址不要抓。剩下那1%在试着表达别的意思——限速、不要收录、指定主域名、说明用途授权。而恰恰是这1%,命中无效的概率最高。 这个分布有个直接的实操含义:审查一份robots.txt的时候,不必逐行读那一万多条Disallow,先把非Disallow、非Allow、非Sitemap的行拎出来单独看。这些行数量少、每一行都承载着一个特定意图,也最容易出问题。157个站的数据说明,这么筛一遍,就能覆盖掉全部146条无效行。 ## 还有一类沉默:Sitemap行指向的地址不通 顺带说一个同类现象。Sitemap行是全局的,不属于任何分组,写在文件哪儿都一样。145个站写了它,合计729行,说明这一项的普及度很高。 批量确认地址还在不在有现成办法,死链怎么批量查出来再分类提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接套用。 这一行指向的文件本身也有一堆写法讲究,2400个站踩出来的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)基本都在那份清单里。 但Sitemap行也有它自己的沉默方式:地址写错、指向的文件已经不生成了、或者返回404,robots.txt本身照样是合法的,没有任何提示。它跟前面讲的失效指令属于同一类问题的不同表现——指令本身有人读,但它指向的东西不在了。检查方式很简单,把每一行Sitemap的地址取出来请求一次,看返回码和内容开头是不是XML。这一步花的时间和抽查Disallow路径差不多。 ## Crawl-delay写给了谁,读它的人真的看得见吗? Crawl-delay是这批数据里最值得单独拆开的一个字段,因为它同时踩到了前面说的第一种和第二种情况,而且大多数人对它的印象是错的。 要看清谁在真抓你的站,5000个站样本里的爬虫伪造与抓取预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)是更硬的参照。 限速这件事做在服务器上也有反噬,限速规则拒掉的第4个请求正好是robots.txt (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html)会让全站抓取停十几个小时。 ## 47个站129行,取值10占了82行 先看规模。157份文件里有47个站写了Crawl-delay,合计129行。取值分布很集中: 抓取节奏被压下去往往悄无声息,抓取速率被调低的那几天日志里一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这种情形。 取值 | 行数 | 如果真被执行意味着什么 | 10 | 82 | 每10秒抓一个地址,一天最多8640个 | 1 | 33 | 每秒1个,一天8.6万个 | 5 | 6 | 一天1.7万个 | 0.5 | 4 | 一天17万个 | 0 | 2 | 不限速,写了等于没写 | 0.2 | 1 | 一天43万个 | 30 | 1 | 一天2880个 | 取值10是绝对主流,占了63.6%。这个数字很有来历——它不是算出来的,是抄出来的。二十年前的一批模板里就写着10,后来一层层抄下来,成了默认答案。 顺便算一下代价:一个有5万个可抓地址的电商站,如果某个爬虫真的按10秒一个的节奏走,抓完一轮要将近6天。促销页上线三天才被读到,这个后果比大多数人以为的严重。 ## 先弄清一件事:Crawl-delay不是废弃指令 网上流传最广的说法是Crawl-delay已经废弃了,这个说法不准确,而且这种不准确会直接导致判断错误。 国内引擎又是另一套口径,提交了为什么还不收录 (https://zhangwenbao.com/baidu-index-crawl-mechanism-why-not-indexed.html)从抓取和索引机制拆起。 至于真正吃掉带宽的那一批,AI爬虫抓取量已经超过Googlebot好几倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)改变了限速这件事的优先级。 既然它主要对Bing有效,这个被长期低估的第二搜索引擎怎么做 (https://zhangwenbao.com/bing-seo-complete-guide-organic-ranking.html)值得单独花点时间。 准确的情况是这样:Google在自己的robots.txt文档里明确写着不支持这一行,读到会直接跳过;Bing认,并且在自家站长工具里同时提供了抓取控制的后台设置;Yandex曾经认,后来也改成了后台设置;至于第三方工具类爬虫,AhrefsBot和MJ12bot都在自己的文档里说明会读,各家对数值的解释还不完全一样。 所以它不是一条死指令,它是一条收件人各不相同的指令。判断它有没有用,不能问这条指令还有效吗,得问我这一行写给谁看,那个人读不读。 ## 129行的收件人分布:热门收件人不是搜索引擎 把129行各自所在的分组拆开,收件人的样子就出来了。这129行分布在54个不同的User-agent令牌上,被点名最多的几个是: 被点名最多的那几个其实是外链工具的爬虫,反链分析工具怎么选与竞品反链拆解 (https://zhangwenbao.com/backlink-analysis-tools.html)解释了它们为什么抓得那么勤。 把日志按对象拆开看会很清楚,8类UA的22周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)是一份可对照的样本。 Crawl-delay写给谁 | 有几个站这么写 | 对方读不读 | Pinterest(含PinterestBot) | 27 | 官方文档未承诺,本站59天日志里一次没来 | AhrefsBot | 25 | 读,官方文档明确说明 | AhrefsSiteAudit | 25 | 读,且是站主自己授权的审计爬虫 | MJ12bot | 24 | 读 | bingbot | 5 | 读,这是唯一写对了位置的一批 | ClaudeBot | 3 | 官方文档未提及支持 | Googlebot | 2 | 不读,明确跳过 | 这张表里最有意思的是排序。写Crawl-delay的人心里想的多半是搜索引擎,可实际写下去的行,绝大多数落在了SEO工具和社交平台的爬虫身上。写给bingbot的只有5行,而bingbot恰好是主流搜索引擎里唯一会读它的那个。 清单里还有一个自摆乌龙的对象值得单独指出来:AhrefsSiteAudit被25个站写了限速。这个爬虫和排在它前面的AhrefsBot不是一回事——前者是站主自己在工具后台点了按钮之后,工具派来审计自家站点的;后者是全网抓取用的。 给自己叫来的审计爬虫限速到每10秒一个地址,后果是自己的全站审计要跑好几天才出结果。这不是没效果,是效果打在自己身上了。这25个站里大概有一部分人后来在工具后台抱怨过扫描太慢,却未必想到是这一行造成的。 ## 只有16行落在了会读它的对象能看到的位置 还有一层更细的错位。robots.txt的分组是不继承的,爬虫只执行匹配得最具体的那一组。所以一行Crawl-delay对bingbot有没有效,取决于它写在哪个分组里:写在bingbot自己的组里,有效;写在通配组里且这个站没给bingbot单开组,也有效;可要是站里既有通配组又有bingbot专属组,而Crawl-delay只写在通配组,bingbot就读不到它。 位置和分布决定效果这件事到处适用,从锚文本分布看过度优化风险 (https://zhangwenbao.com/anchor-text-analyzer-penguin-distribution-guide.html)是另一处例子。 写对了位置也未必等于对方进得来,robots.txt说允许,仍有10个站把GPTBot挡在门外 (https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html)是另一层错位。 按这个口径算,47个写了Crawl-delay的站里,能被bingbot真正读到的只有13个:5个写在bingbot组里,8个写在通配组且没有单开bingbot组。折算成行数是16行,占129行的12.4%。 剩下34个站,把Crawl-delay全写给了别的对象——SEO工具爬虫、社交平台爬虫、离线下载软件。这些行不是全无用处,AhrefsBot那25个站确实会被限速,但如果写的人本意是压搜索引擎的抓取频率,那这34个站的目标一个都没达成。 ## 写给Googlebot的那两行 129行里有2行是直接写给Google的爬虫的,这是最干净的白写案例,因为Google的文档里就明确写着不支持。 同一家的爬虫内部也分工,移动优先索引下的渲染机制 (https://zhangwenbao.com/mobile-first-indexing-mechanism-googlebot-rendering-evolution-survival.html)决定了它以哪个身份来抓。 想拦训练数据的话这一行更不够用,内容进模型的四条路 (https://zhangwenbao.com/ai-training-data-four-paths-robots-txt-limits.html)在一份诉讼材料里被摊开过。 同一家的抓取器并不都守同一套规矩,有一整类抓取器压根不看robots.txt (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)这次改名把它推到了台前。 其中一个站的写法特别值得看:gillette.com把42个AI相关的爬虫令牌堆在同一个User-agent组里,从GPTBot、ClaudeBot、Applebot-Extended一直排到Meta的几个抓取器,组里写了一行Crawl-delay: 10。 这42个令牌里混进了Google-Extended和GoogleOther,于是这一行就成了写给Google的Crawl-delay。整组的意图很明确——想给AI爬虫统一限速。可这批爬虫的公开文档里,绝大多数一个字都没提支持Crawl-delay。 ## 想压抓取频率,该把话说到哪里 那如果确实需要降速呢?按对象分开处理,能落地的只有这几条路。 临时降速会用到的状态码也有讲究,301、302、404和410分别该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)是一张速查表。 在服务器上动手要防误伤,拦AI爬虫与限速怎么不把Googlebot一起拦掉 (https://zhangwenbao.com/nginx-ai-bot-blocking-rate-limit-rdns-misblock-account.html)有具体的匹配写法。 对Google,去Search Console的设置里调抓取速率,或者在服务器端对它的请求返回503配合Retry-After做临时降速——注意这是临时手段,长期返回5xx会被当成站点故障。对Bing,站长工具后台有抓取控制面板,比robots.txt里那一行更明确。对SEO工具类爬虫,Crawl-delay确实有用,写在它们各自的分组里就行。对AI爬虫和不认识的抓取器,Crawl-delay基本无效,真要限速得在服务器层做请求速率限制。 换句话说,Crawl-delay不是没用,是能用它的地方比大多数人想的窄得多。 ## 限速这件事,本该在哪一层做 再往深一层看,Crawl-delay之所以这么容易被误用,还有个原因:它把一个服务端的问题,写到了一个客户端自愿遵守的文件里。 这些闸门放在边缘层实现更省事,在CDN边缘改SEO的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)给了几种现成形态。 还有一种思路是干脆换成收费,要不要向AI爬虫按次抓取收钱 (https://zhangwenbao.com/cloudflare-pay-per-crawl-charge-ai-bots.html)已经有平台在做了。 抓取压力大是个真实的运维问题——数据库连接被打满、TTFB变长、真实用户受影响。可robots.txt里那一行是在请求对方配合,不是在限制对方。愿意配合的会配合,不愿意的、或者不读这个字段的,一点影响都没有。真正扛压力的手段全部在服务端。 手段 | 作用范围 | 对方不配合时还有效吗 | robots.txt里的Crawl-delay | 只对读它并愿意执行的爬虫 | 无效 | 搜索平台后台的抓取速率设置 | 只对该平台自己的爬虫 | 有效,但仅限这一家 | 服务器按来源限速 | 所有请求 | 有效 | 边缘层的速率规则与验证挑战 | 所有请求,且不消耗源站资源 | 有效 | 临时返回503配合Retry-After | 所有请求 | 有效,但只能短期用 | 这张表想说明的是分层。上面两行是打招呼,下面三行是设闸门。打招呼很有价值——它让守规矩的爬虫按你的节奏来,成本几乎为零;但如果你的真实处境是服务器已经被抓爆了,那就得往下走,光把数字从10改成20不会有任何变化。 顺着这个思路还能解释一个常见困惑:为什么有人写了Crawl-delay之后感觉抓取量确实下来了。多半是因为他点名的对象里恰好包含了AhrefsBot、MJ12bot这类真读它的第三方爬虫,而这些工具爬虫本来就是抓取量大户。压下来的是它们,不是搜索引擎。 ## 同样写一个10,各家的理解是一样的吗? 假设你运气不错,Crawl-delay写对了位置,收件人也确实会读。还有一个问题在等着:这个数字对方怎么理解。 定义不清的指标最容易误导判断,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭自己的口径。 同一个数字各家算法不同这件事到处都有,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 ## 标准里没有这个字段,所以也没有语义定义 这是个容易被忽略的前提。爬虫排除协议的正式标准文档里,一共只定义了User-agent、Allow、Disallow这三个字段,以及Sitemap这个事实上通用的扩展。Crawl-delay不在其中。 标准写没写这件事,影响的不只是robots.txt,语义化HTML到底影响不影响抓取 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)也是拿样本页跑出来的。 不在标准里,意味着没有任何一份权威文档规定它的单位、取值范围、以及超出范围之后怎么处理。每家实现自己解释,而且不同实现的解释确实不一样。 ## 三种常见解释,结果差几十倍 把各家的公开说明和实际观察对照,Crawl-delay: 10至少存在三种不同的执行方式。 同一个指标不同平台的口径也不同,三平台和300个站的收录速度实测 (https://zhangwenbao.com/seo-kpi-guide.html)能看出差距有多大。 解释不同会直接反映到报告上,抓取报告里五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你分清是谁的问题。 解释方式 | Crawl-delay: 10的含义 | 一天最多抓多少 | 请求间隔秒数 | 两次请求之间至少间隔10秒 | 8640个 | 时间窗口划分 | 把一天划成若干时间片,每片内允许一次抓取 | 取决于片长,通常也在万级 | 相对权重 | 作为降速倾向的参考值,不承诺具体数值 | 不确定 | Bing在自家文档里用的是第二种表述,把它描述成对抓取节奏的划分而不是简单的秒数间隔,还提示取值过大会影响新内容被发现的速度。第三方工具类爬虫多数走第一种或第三种,AhrefsBot的文档 (https://ahrefs.com/robot)明确说会读这个值并据此放慢,但不承诺精确的换算关系。 ## 取值上限也是各家自定的 还有个实操细节:不是所有实现都接受任意大的数值。有些实现对超出自己上限的取值直接按上限处理,有些干脆忽略整行。所以写Crawl-delay: 86400想让某个爬虫一天只来一次,很可能什么都不会发生。 超过上限之后会发生什么很关键,页面体积超出之后商品链接被截在外面 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)是实测过的后果。 各家自定上限这件事在别处也有,Googlebot那个2MB抓取上限 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)就是一条硬边界。 样本里最大的取值是30,出现1次;有2个站写了0。写0这件事挺有意思——按第一种解释,0就是不限速,那这行等于没写,但它占着一个位置,让人以为限速已经配置过了。 ## 数值型指令的通用判断 这一节想说的其实不止Crawl-delay。凡是往别人系统里写数值的场景,都有同一个问题要问:这个数字的单位和语义,是谁定义的,写在哪儿。 服务器上那些数值配置同样值得逐条问一遍,服务器配置影响SEO的20项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着核。 定义在标准里,各家实现基本一致,可以放心写;只在某一家的文档里有定义,那就只对这一家有效,别指望别人按同样方式理解;哪儿都没有定义,这个数字就只是一个愿望值。Crawl-delay属于第二种和第三种的混合体,这也是它最容易被误用的原因。 ## robots.txt里的Noindex,Google到今天还认吗? 不认。而且这件事有一个非常明确的日期,明确到可以写进检查清单里。 这两个手段能不能一起用也常被问到,noindex和canonical同时用的九种场景判断 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)给了明确结论。 换成有效手段之后还得等,页面加了noindex要多久才从搜索结果里消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)有六个场景的实测。 ## 2019年那份公告,一次点掉了三个字段 2019年7月初,Google在搜索开发者博客上发了一篇很短的通告,主题是robots.txt里那些从未被写进文档的规则 (https://developers.google.com/search/blog/2019/07/a-note-on-unsupported-rules-in-robots)。文章说得直白:这些规则从来没有出现在Google的官方文档里,代码里的支持是历史遗留,现在要把它们清掉,生效日期是2019年9月1日。 官方砍功能这件事不是第一次,FAQ富结果被砍之后这套标记还该不该写 (https://zhangwenbao.com/google-drops-faq-rich-results.html)是同类决策题。 被点到名的一共三个:noindex、nofollow、crawl-delay。这就是为什么前面那节要专门说清Crawl-delay的处境——它和Noindex是同一份公告里的同一批被清理对象,只不过Crawl-delay在别家还活着,Noindex在任何一家都没活下来。 这份公告的意义不只是宣布三个字段作废。它顺带说明了一件更重要的事:robots.txt里有一部分字段的支持,从头到尾就没有写在文档里。写的人是从别人的文件里看到的,用了之后好像有效,就一直用着。等到哪天对方清理代码,效果就无声无息地消失了。没有报错,没有提示,也没有任何回归测试能发现。 ## 样本里只剩两个站,一共7条 157份文件里还在写Noindex的只有2个站:sostrenegrene.com写了1条,路径是分享链接的参数;wayfair.com写了6条。合计7条。 这些页面真进了索引会拖累全站,大量没用的页面怎么诊断和处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 这个数字小得让人有点意外,说明这几年清理得相当彻底。也正因为剩得少,剩下的这几条才更值得看一眼——它们不是随便留的,写的时候有明确意图。 ## 那6条挡的正是最该挡的页面 wayfair那6条的路径是这样的:/filters/、*/filters/、/*quick_view、/roomplanner/*、/decorator/*、/roomplanner3d/*。 这些页面的另一个毛病是正文占比太低,模板和广告稀释主体内容的七个陷阱 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)有对应的量法。 筛选组合页最大的问题是内容重复,同域、跨域、参数变体六类重复怎么治 (https://zhangwenbao.com/content-duplicate-issue.html)可以对号入座。 看一眼就知道意图:前三条是分面导航和快速预览,后三条是房间规划、软装搭配这类交互工具页。这些恰恰是家居电商最典型的URL膨胀来源——一个筛选组合能生成成千上万个地址,每个地址都是一个可抓取页面,内容却高度重复。用noindex把它们从索引里挡掉,是完全正确的判断。 手段无效,判断正确。这种组合比判断本身就错更难发现,因为你复盘的时候会先看意图,意图一看就对,很容易直接跳过去。 ## 更麻烦的是,同一批路径还被Disallow挡了一遍 把这个站的文件完整读一遍,会发现6条Noindex不是孤零零写在那儿的。同样这几个路径,在文件里还有对应的Disallow: 分页那一层也有同样的取舍,分页页面五种处理方案的对比 (https://zhangwenbao.com/category-pagination-seo.html)列了各自的代价。 不同类型的页面该给什么指示是分开的,五类页面的meta robots与canonical差异 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)可以拿来对照自己的模板。 路径 | 写了Noindex | 写了Disallow | 实际效果 | /filters/ | 是 | 是 | Noindex已失效,Disallow阻止抓取 | */filters/ | 是 | 是 | 同上 | /roomplanner/* | 是 | 是 | 同上 | /decorator/* | 是 | 是 | 同上 | /roomplanner3d/* | 是 | 是,另有一条Allow精确放开目录本身 | 同上 | /*quick_view | 是 | 否 | Noindex已失效,抓取不受限 | 这就构成了一个双重失效。第一层,robots.txt里的Noindex本身没人读;第二层,就算它有人读,Disallow也已经把爬虫拦在门外了——被禁止抓取的地址,爬虫连页面都取不到,自然也无从执行任何不收录的指示。两条规则里任何一条单独存在都不会有效果,两条一起写反而让人更确信这件事办得很稳。 还有个更细的痕迹:这几行里有两行写成了Noindex : /roomplanner/*,字段名和冒号之间多了一个空格。多数解析器会把两边的空白去掉,所以这不影响解析,但它说明这些行是手工敲上去的,不是模板生成的。 同一份文件里还有一行Allow: /roomplanner3d/$——用美元符号做精确结尾匹配,放开目录首页本身,同时用Disallow挡掉目录下的其他地址。这是相当熟练的通配符用法,能写出这一行的人,对robots.txt的语法掌握得比平均水平好得多。 这个对比才是这一节最值得记住的地方:语法水平和收件人判断,是两件互不相关的事。熟练的人一样会写下没人读的指令,因为语法能靠工具校验,收件人只能靠查文档。 ## 为什么这一条比其他白写的行更危险 Crawl-delay白写了,后果是抓取频率没降下来——不好,但不致命。Host白写了,后果是主域名选择这件事没人管——通常有别的机制兜着。Noindex白写了,后果是一批你以为已经从索引里拿掉的页面,其实一直在索引里。 这类假完成状态最容易骗过例行检查,后台那些数字为什么人人都读错 (https://zhangwenbao.com/google-search-console-complete-guide-diagnosis.html)讲了几处常见误读。 页面到底在不在索引里要看后台状态,八种未编入索引状态各自意味着什么 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)是判断的起点。 差别在于,前两种是没得到想要的收益,第三种是拿到了一个假的完成状态。你在项目文档里勾掉了这一项,团队里所有人都以为分面页已经处理过了,实际上它们还在搜索结果里跟主要商品页抢位置。这种问题往往要等到收录量异常、或者有人偶然搜到一个筛选页时才被发现。 ## 正确的替代路径,顺序不能反 要让一个地址不出现在搜索结果里,只有两条真正有效的路:页面头部的meta robots标签,或者响应头里的X-Robots-Tag (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Robots-Tag)。后者对非HTML资源尤其重要,因为PDF、接口返回的JSON、feed这类东西没有地方放meta标签。 非网页资源只能靠响应头下指示,PDF怎么做SEO与六个优化点 (https://zhangwenbao.com/pdf-seo-complete-guide-google-indexing-6-real-optimizations.html)里有具体做法。 没有头部标签的资源只能靠响应头,接口和feed这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)单独量过一次。 响应头这一层能做的事比想象中多,X-Robots、缓存和Vary几个头的实际机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)值得整体过一遍。 关键是顺序,这一步错了会前功尽弃:先允许抓取,让爬虫能读到noindex,等页面从索引里消失之后,再考虑要不要在robots.txt里加禁止抓取来省预算。反过来做——先在robots.txt里禁掉——爬虫就永远读不到那个noindex标记了,这个地址反而可能以没有摘要的形式长期留在索引里。 对wayfair那6条路径来说,正确做法是在这些页面模板的头部输出noindex,或者在服务端按路径规则给响应头加X-Robots-Tag。robots.txt里那6行可以直接删掉,它们现在唯一的作用是让人误以为事情办完了。 ## 按路径下发不收录指示,服务端两种写法 分面导航这类页面有个共同特点:数量多、由参数组合生成、模板可能是共用的。逐个页面改模板容易漏,更稳的做法是在服务端按路径规则统一下发。 要注意缓存层会不会把这个头一起缓住,全页缓存怎么配以及怎么清 (https://zhangwenbao.com/nginx-fastcgi-cache-fullpage-php-wordpress-purge-microcache.html)里有对应的处理。 Apache环境下这类规则常和别的层叠在一起,重写、缓存、canonical六层怎么排顺序 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)有完整示例。 nginx里加一段位置匹配就行,注意用always参数,否则非200响应上这个头不会输出: location ~* ^/(filters|roomplanner|decorator)/ { add_header X-Robots-Tag "noindex, follow" always; } Apache环境用mod_headers,按目录或正则匹配都可以: <IfModule mod_headers.c> <LocationMatch "^/(filters|roomplanner|decorator)/"> Header set X-Robots-Tag "noindex, follow" </LocationMatch> </IfModule> 两处都写了follow,这是有意的。noindex加nofollow会让这些页面上的链接也不被跟随,而分面页往面上常常挂着通往正常商品页的链接,全部掐掉反而损失内链。除非确实不想让爬虫顺着往下走,否则保留follow更稳妥。 配完必须验证一次,验证方式是直接看响应头有没有这一行。用命令行请求的时候记得用GET而不是只取头部,有些服务端对不同方法的响应头处理不一致,只查头部会漏掉实际存在的字段。 ## Host指令是写给谁的,写它的人知道吗? 接下来这一条最能说明抄来的规则是怎么在文件里过日子的。 选哪个版本最终还是搜索引擎自己判断,它挑选规范网址的九条决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)解释了为什么你的声明有时不被采纳。 接管这件事的是另一套机制,canonical该怎么设的九个决策点 (https://zhangwenbao.com/canonical-url-seo-guide.html)是现在的主力手段。 ## 10个站写了Host,其中9个连Yandex的分组都没有 157份文件里有10个站写了Host,每站1行,值全都是自己的主域名,8个带www,2个不带。 要不要管某个搜索引擎得看它的实际份额,全球搜索引擎格局与多平台优化 (https://zhangwenbao.com/search-engine-landscape-seo-strategy-guide.html)给了一份比例参照。 Host从来不是通用指令,它是Yandex的私有扩展,作用是在多个镜像域名之间声明哪一个是正主。所以判断这一行是不是有意为之,只需要看一件事:这个站有没有在管Yandex。 结果是10个站里只有1个(pullandbear.com)给Yandex的爬虫单开过分组,其余9个站的文件里,Yandex这个词一次都没出现过。它们写了一行只有Yandex会读的指令,同时没有任何迹象表明它们在意Yandex怎么抓自己的站。 ## 这一行原本要解决的问题,今天由别的机制接管了 Host要解决的问题是真实存在的,而且现在依然存在:一个站可能同时能从带www和不带www的地址访问,或者同时有http和https版本,搜索引擎需要知道哪个是主版本。 这套声明自己也会打架,跨页场景下canonical的八种冲突 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)有对应的诊断办法。 协议版本的选择也属于同一类问题,从HTTP迁到HTTPS怎么才能不掉排名 (https://zhangwenbao.com/seo-https.html)是完整的迁移路径。 只是这件事早就搬家了。今天负责回答这个问题的有三样东西:服务端的301重定向、页面里的canonical标签、以及各家站长平台后台的域名设置。这三样所有主流搜索引擎都读,Yandex自己也在文档里说改用重定向来判断。 所以Host这一行的处境很特殊:它不是需求消失了,是需求换了地方办理。这两种情况在文件里长得一模一样,但处理方式完全不同——需求消失的行直接删,需求搬家的行删掉之前得先确认新地方已经办好了。 ## 它是怎么进到文件里的 把这10个站的文件放在一起看,来路基本能推出来。这些行的位置很有规律:大多紧跟在Sitemap行的旁边,或者贴在文件最末尾,与上下文的缩进风格不完全一致。 抄示例这件事在各类程序里都有,虚拟文件与物理文件的优先级 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)常被忽略。 这是典型的从示例里整段抄的痕迹。很多年前流传得很广的一批robots.txt模板文章,为了显得完整,会把Host和Crawl-delay一起写进示例。抄的人不需要知道Host是给谁看的,示例里有,抄过来就是了。之后每次改版都只在末尾追加新规则,没人会回头审这一行。 顺着这条线索还能解释另一个现象:为什么Crawl-delay取值10的比例那么高。它们大概来自同一批示例。二十年前有人在一篇教程里写了10,后来抄的人不知道该填几,就照着填了10。这个数字一路传到了2026年的品牌独立站上。 ## 一个能立刻做完的判断动作 遇到一行不确定来路的指令,有个很快的办法:在自己的文件里搜一下这个指令的目标对象名字,看它在别处出现过没有。 两个方向的跳转都要验一遍,双向301在两种服务器上的写法 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)都在一起。 确认主域名跳转是不是通的更实际,多域名统一301到主域名的完整配置 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)可以照抄。 写了Host,就搜Yandex;写了给某个爬虫的Crawl-delay,就搜那个爬虫的名字。如果整个文件里只有这一处提到它,那这行几乎肯定是抄来的——因为一个真在管某个爬虫的人,通常不会只对它说一句话。 ## 被挡住的那个目录,今天还在吗? 前面几节讲的都是收件人不在。还有一种失效方向正好相反:收件人在,规则也有效,可要挡的那个东西已经没了。 改版之后这类地址会成批出现,一次揪出全站404与重定向链 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)有现成的工具流程。 这批地址在后台会以另一种形式冒出来,404报告怎么修以及软404怎么排查 (https://zhangwenbao.com/google-search-console-404-error-fix-guide.html)是配套的动作。 这个方向以前没量过,这次顺手做了一遍,结果比预想的夸张。 ## 实验怎么做:从通配组里抽具体路径,直接请求 做法很朴素。157份文件的通配组里一共有5539条Disallow,其中不带星号、不带美元符号、不带问号的具体路径有1903条,占34.4%。这1903条是可以直接拼成地址去请求的。 换身份请求同一个地址是常用手法,模拟爬虫身份测站的具体做法 (https://zhangwenbao.com/useragent-generator-ua-string-bot-simulation-seo-guide.html)里有可直接用的串。 想知道某个目录在不在索引里还有别的探法,site命令能查什么、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)说清了它的边界。 每个站抽3条——第一条、中间一条、最后一条,避免只抽到同一类。最后得到358条,覆盖127个站。用普通浏览器的User-Agent逐条请求,跟随重定向,记下最终状态码、重定向次数和最终地址。 这里要说清一件事:普通用户访问不受robots.txt约束,这个文件约束的是自动抓取程序。所以用浏览器身份去看一眼这些地址存不存在,本身没有越界,量也控制得很小。 ## 这次抽样有三条边界,得先划清楚 这个53.4%要用得住,边界必须说明白,否则很容易被外推成一个错的结论。 第一条,只抽了通配组里的路径。各个专属分组里的Disallow没有参与,因为专属组大多由平台模板生成,路径高度重复,混进来会把比例带偏。 第二条,只抽不含通配符的路径。带星号或美元符号的规则没法拼成一个确定地址去请求——它们匹配的是一类地址而不是一个。这一类在通配组里占了65.6%,也就是说本次实验覆盖的只是三分之一。 第三条,每个站只抽3条。这是为了把请求量压到最低,代价是单站结论不可靠:某个站三条全404,只能说明它这几条过期了,不能断定整份文件都失效。 所以这个数字的正确读法是:在robots.txt里那些指向具体地址的禁止规则中,能测出结果的部分有一半以上指向了不存在的地址。它不等于所有Disallow有一半失效,也不等于某个具体站点有一半规则没用。把范围说窄一点,结论反而更结实。 ## 能判定的176条里,一半以上指向不存在的地址 358条里有182条没法判定——被边缘防护挡了,返回403、406、422这类。剩下176条能看出结果: 不同工具报出来的死链也常常不是一批,爬虫报的死链和Googlebot抓的从来不同 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html)解释了差异来源。 返回什么状态码这件事本身要配对,自定义错误页与软404的正确配法 (https://zhangwenbao.com/apache-errordocument-custom-error-pages-http-status-codes-soft-404.html)最容易配错。 结果 | 条数 | 占可判定的比例 | 含义 | 404或410 | 89 | 50.6% | 这个地址服务器上没有 | 200但跳回首页 | 5 | 2.8% | 路径没了,被兜底路由接走 | 200且跳到另一个路径 | 50 | 28.4% | 目标还在,只是换了地址 | 200且原地就是它 | 32 | 18.2% | 规则挡的东西确实在 | 把前两行合起来,94条(53.4%)挡的是一个不存在的地址。真正原地命中的只有32条,不到五分之一。 还有9个站的3条抽样全部404,一条都没命中:assos.com、buckmason.com、columbia.com、dji.com、lookfantastic.com、purple.com、soundcore.com、stokke.com、weber.com。这几个站的robots.txt多半已经很久没有对着实际站点结构核对过了。它不是一份现役配置,是一份存量档案。 ## 404的路径长什么样,一看就知道它经历过什么 把404的清单摊开,路径名本身就是一部简史。 测试环境留下的地址更麻烦,预发布环境被索引之后的八步清除 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)是一套应急流程。 路径名本身也是资产,URL结构与slug影响抓取和排名的九个细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)值得在改版前定好。 有一类是老技术栈的遗留:gillette.com挡着/postreview.php和/account.php,两个都是PHP时代的地址,站早换过架构了,现在请求前者会被兜底路由送回首页,后者会跳到新的登录页。canyon.com挡着两条Demandware平台的商店路径,实际访问会跳到语言子目录。 有一类是测试和临时页:buckmason.com挡着/testing,dji.com挡着/cache/,assos.com挡着/poll/和/report/。这些名字看起来就是当年临时开的,用完就删了,规则忘了收。 还有一条堪称本次抽样的最佳画面:assos.com在robots.txt里写着Disallow: /404/,而这个地址返回的正是404。挡一个专门用来显示找不到页面的目录,而那个目录本身也找不到了。 另一类是带店铺编号的:bollandbranch.com挡着/11547838/orders,burrow.com挡着/93232202030/orders。这是电商平台早期版本的订单路径格式,平台自己升级之后这个编号段就不用了。 把404清单按来路归一下,正好四类: 来路 | 样本 | 为什么会留下 | 老技术栈遗留 | gillette.com的postreview.php与account.php、canyon.com的两条商店平台路径 | 架构换过,规则没跟着换 | 测试与临时页 | buckmason.com的testing、dji.com的cache、assos.com的poll与report | 用完删了页面,忘了收规则 | 平台旧版路径 | 两个站的带编号订单路径、多个站的登录跳转服务路径 | 平台自己升级了地址格式 | 压根不在这个域名下 | anker.com、eufy.com、buckmason.com、govee.com各自挡着的admin与checkout | 后台其实在另一个域名上 | 最后一类值得多说两句。这几个站用的是托管电商平台,管理后台根本不在自己的域名下,而是在平台自己的域名上。也就是说/admin这个地址从来就不存在于这个站点,挡它不会有任何效果,也不会有任何风险——它纯粹是一种防护姿势。 这类行的心理来源很好理解:写的人见过别的站挡后台入口,觉得挡一下总不吃亏。问题是它给了一种已经加固过的错觉。真正需要确认的是那个后台入口实际在哪儿、有没有做访问限制,而这件事robots.txt既回答不了也管不着——它本来就不是安全机制,任何人都能读到它,把敏感路径写进去反而是给人指路。 ## 模板路径和自定义路径的过期率,几乎一样 这里有个反直觉的结果。原本猜测平台模板带来的路径(/cart、/checkout、/admin、/services/login_with_shop这一类)过期率应该更高,因为它们不是站主自己写的,跟自家结构未必对得上。 结构一改这些路径就集体过期,独立站架构怎么搭才不让爬虫找不到产品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是更上游的决定。 实际数字是:模板常见路径165条,404率25.5%;其它自定义路径193条,404率24.4%。基本没有差别。 这说明过期不是模板的问题,是时间的问题。自己写的规则一样会过期,而且因为是自己写的,你更不会怀疑它。 ## 那182条测不出来的,本身就是一个发现 358条里有一半(50.8%)被边缘防护挡住了,返回403、406或422。这个比例高得出人意料,也顺带说明了一件很实际的事:你想验证自己的规则对不对,第一道障碍可能是自家的防护把验证请求也当成了可疑流量。 自家防护的口子在哪要自己清楚,端口放行与云安全组怎么配 (https://zhangwenbao.com/linux-ufw-firewall-server-port-rules-ssh-cloud-security-group.html)是最基础的一层。 从外面测不通还有很多别的成因,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)能帮你分清卡在哪一层。 服务器配置的副作用往往也不出声,每次reload都通过,Googlebot每8次抓取却有1次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类沉默。 这不是无解的。自查的时候直接在服务器上对本机发请求,或者带上内网来源和白名单UA,就能绕开边缘层。要点在于意识到这一层存在——不然你会以为自己的地址全都好着,实际上你测到的只是防护的反应,没测到应用的反应。这跟前面那个分母算错的返工是同一类问题:先确认自己量的是什么。 ## 自己的站怎么把这一遍跑完 同样的检查在自己站上跑一遍不需要写程序,一段命令行就够。思路是从通配组里取出具体路径,逐条请求,把状态码打出来: 不过不是所有事都该自动化,哪些能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条比较清楚的界。 这种检查适合挂成定时任务,用cron把备份、sitemap、缓存这些活自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)有一份可直接改的脚本集。 curl -s https://example.com/robots.txt | awk 'BEGIN{IGNORECASE=1} /^user-agent:[[:space:]]*\*/{f=1;next} /^user-agent:/{f=0} f&&/^disallow:/{print $2}' | grep -v '[*$?]' | grep '^/' | sort -u | while read p; do c=$(curl -s -o /dev/null -w '%{http_code}' -L "https://example.com$p") echo "$c $p" done | sort 输出按状态码排好序,404那一段就是要处理的清单。几点提醒:把域名换成自己的;路径很多的话先取前二三十条看看趋势;如果大批返回403或者406,说明请求被自家边缘防护挡了,换到服务器上把域名改成127.0.0.1并带上Host头再跑。 跑完之后不用急着删。先把404的那批路径拿去问一个问题:这个目录当年是干什么的,现在那件事由哪个地址承担。答得出来就改成新地址,答不出来就是纯遗留,可以删。 ## 这些死规则要不要清,代价在哪里 先说不用紧张的部分:挡一个不存在的地址,不浪费抓取预算,也不会带来收录问题。爬虫读到规则只是记下来,不会去试探这个地址存不存在。所以从性能和收录角度看,这些行的直接危害接近于零。 要让清理这件事持续下去得留痕,把变更做成日志的十三类信号 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)讲的就是这套办法。 同样的决策在内容侧更常遇到,上千篇旧内容的留、改、并、删、转怎么定 (https://zhangwenbao.com/content-audit-pruning-decision-system.html)是一套可复用的判据。 代价在别的地方,而且是长期的。一份有一半路径已经失效的robots.txt,会让所有读它的人对它失去判断力。下次有人要加一条规则,他不敢删任何旧行——因为分不清哪些还有用;他也不会通读全文——因为读了也判断不了。于是文件只能往下追加,越长越不可读,越不可读越只能追加。 这份157个站的样本里,光通配组的Disallow就有5539条,平均每份35条。那些一眼看不到头的文件,基本都是这么长起来的。 ## 平台默认模板,会替你写下没人读的行吗? 用建站平台的站主最关心这个问题:文件不是我写的,锅要不要我背。 把模板之外的部分单独审一遍更高效,从抓取到AI可见度的完整诊断框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以拿来当清单。 平台自带、通用工具、专属应用各管一段,这三层怎么分工与选型 (https://zhangwenbao.com/shopify-seo-tools-three-layer-selection.html)能省掉不少重复投入。 ## 67个站出自同一套平台模板 157份文件里,有67份带着同一套平台模板的特征——给广告爬虫单开分组、屏蔽购物车和结算路径这几个组合一起出现。占比42.7%,跟前一轮统计的41.4%基本吻合。 平台默认给的东西不止这一个文件,128种标记类型里该怎么挑 (https://zhangwenbao.com/shopify-schema-seo-guide.html)也是接管前要弄清的。 这套模板在别的地方也有默认判断,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)是最常需要接管的一处。 这个比例值得记一下:接近一半的独立站,robots.txt的第一版不是人写的。 ## 模板本身是干净的,有问题的行是后来加的 然后看这67个站里有多少存在前面说的那些无效行:27个,占40.3%。剩下40个一条都没有。 批量生成的东西质量取决于模板,从模板化转向语义化的八步 (https://zhangwenbao.com/semantic-programmatic-seo-blueprint.html)讲了怎么把默认做扎实。 人后加的那一层最容易和默认打架,插件与主题各输出一套标记怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一种病。 这个分布本身就是答案。如果模板自带无效指令,那67个站应该全中,因为它们用的是同一套生成逻辑。实际只中了四成,说明那些行不是模板给的,是站主或者服务商后来自己加进去的。 换句话说,模板把基础写对了,然后有人在上面加了一层自己也不确定有没有用的东西。这个顺序很关键——它意味着排查的时候,应该重点看模板之外的那几行,那才是人写的部分。 ## 模板不带Crawl-delay,但加它的人特别多 顺着这条线索还能看出加的是什么。写了Crawl-delay的47个站里,绝大多数点名的对象是Pinterest、AhrefsBot、AhrefsSiteAudit、MJ12bot这四个,被点名次数分别是27、25、25、24次。 照抄清单这件事在工具选型里也常见,用第一性原理做工具选型 (https://zhangwenbao.com/seo-tools-martech-replacement-trend-2025.html)比跟着别人的清单走稳。 这四个对象凑在一起出现,几乎可以断定来自同一份流传很广的清单。有人整理过一份限速名单,包含这几个吃流量的第三方爬虫,后来被大量转载和照抄。抄的人各自把它贴进了自己的文件里。 这批行有意思的地方在于它一半有效一半无效:AhrefsBot和MJ12bot确实会读,Pinterest那27个站则是彻底白写。同一份清单里既有真收件人也有假收件人,抄的人无法分辨——因为清单本身不写这个信息。 ## 接管模板之前,先想清楚接管的是什么 要不要把平台生成的robots.txt改成自己维护的版本,判断标准只有一条:你有没有一个明确的、模板满足不了的需求。 如果是自建程序,责任边界从一开始就在自己这边,从主机、插件到核心指标的完整做法 (https://zhangwenbao.com/wordpress-seo-guide.html)可以对照排期。 接管的范围有时比预想的大得多,这套基建换了架构就得自己重搭 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是个提前的提醒。 有需求就接管,接管之后这份文件的全部内容都归你负责,包括平台后续更新的那部分你再也拿不到了。没需求就别动,尤其别为了看起来更专业而加几行不确定的规则——本文这56个站的146条无效行,绝大多数就是这么来的。 ## 刚发明的那几个字段,眼下有人在读吗? 数据里还有一批行,方向和前面完全相反:它们不是被弃用的老字段,是刚出生的新字段。 要判断这些新约定值不值得投入,先把爬虫的真实抓取偏好逆出来 (https://zhangwenbao.com/ai-crawler-reverse-engineering-fetch-behavior-llms-strategy.html)比看提案更实在。 同一家还在推另一套给机器读的交付方式,用内容协商给AI直接送Markdown (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是更进一步的做法。 ## 5个站写了三种全新写法 157份文件里,出现了三个此前从没在这批样本里见过的字段名,一共5个站在用: 整体该怎么排先后,从AI搜索到结构化数据的实施顺序 (https://zhangwenbao.com/geo-strategy.html)有一版可执行的策略。 这些表态最终服务的是同一个目标,让AI爬虫抓得到、读得懂、引得出 (https://zhangwenbao.com/geo-technical-optimization-crawl-render-extract-guide.html)是技术端的落地清单。 站点 | 写了什么 | 意图 | delonghi.com | Content-Signal: ai-train=yes, search=yes, ai-input=yes | 三类用途全部允许 | seed.com | Content-Signal: search=yes, ai-input=yes, ai-train=no | 允许搜索和即时引用,拒绝训练 | jackery.com | Llms: 指向自己域名下的llms.md | 告诉AI去读另一份文件 | underarmour.com | Llms: 指向well-known目录下的llms.md | 同上,位置更规范 | liu-jo.com | Llm-Policy: /llms.md | 同一个想法的第三种拼法 | ## Content-Signal的来路,以及承诺读它的是谁 Content-Signal不是某个搜索引擎提出来的,是一家边缘网络服务商在2025年发起的一套内容信号约定 (https://blog.cloudflare.com/content-signals-policy/)。核心想法是把用途拆开表态:允许被搜索索引,不代表允许被拿去训练模型,也不代表允许在AI回答里被当作即时输入。 有时候替你做决定的是主机商,托管主机可能正悄悄拦掉AI爬虫 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)而监控一声不响。 这个拆分回应的是一个真实痛点。老的robots.txt只有允许抓和不允许抓两种表态,而站主真正想说的是可以抓但别拿去训练——这句话在旧语法里没法表达。 问题在收件人。这套约定的推动方能替自家网络上的站点自动加上这一行,但它没法替任何AI公司承诺会读。目前明确表态会尊重的只有少数几家,大多数抓取方要么没回应,要么只在自己的文档里另立一套控制方式。 ## Llms和Llm-Policy:同一个想法的两种拼法 另外三个站写的是指向llms.md的引导行。llms.md本身是一份民间提案,想法是给站点准备一份专供大语言模型阅读的精简说明文档,把最重要的信息按机器友好的方式列清楚。 新写法要不要跟,得看它能不能带来引用,3000条数据揭开的引用认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)可以当参照。 提案有一定影响力,但两件事都没定:一是没有任何主流厂商公开承诺会去读这份文件;二是连字段该怎么拼都没统一——这三个站分别写了Llms和Llm-Policy两种,路径也分别放在根目录和well-known目录下。 三个站,两个字段名,两个路径位置。这种分歧本身就说明它还处在很早的阶段。 ## 那份被指向的文件里,通常写着什么 顺着这三个站给的地址看过去,llms.md的内容结构大体是统一的:开头一行站点名称,接一段这个站是干什么的说明,然后按主题分成几个区块,每个区块下面列出若干个地址,每个地址后面跟一句这是什么的解释。整份文件用最朴素的标记语法写,不含样式和脚本。 真正影响被引用的还是内容本身的组织方式,七种更容易被引用的结构 (https://zhangwenbao.com/optimize-content-structure-ai-citations-2026.html)有实测对比。 给机器准备一份精简说明这个思路,帮助中心怎么做索引控制与AI引用 (https://zhangwenbao.com/knowledge-base-help-center-seo-indexing-ai-citation.html)早就在实践了。 它和sitemap的分工可以这样理解:sitemap回答的是我有哪些地址,追求全量和机器可解析;这份文件回答的是我最重要的内容是哪些、各自讲什么,追求的是让读它的模型少走弯路。前者是索引,后者更像一份导览。 需要说清的是,目前没有任何主流抓取方公开承诺会去读它。有些站点观察到AI相关的抓取器请求过这个路径,但请求过不等于会按它行事,更不等于会持续这么做。 ## 如果决定做一份,成本该控制在哪儿 建议是可以做,但把它当一次性投入,不要变成需要长期维护的第二套内容体系。 维护成本这件事要提前算,内容新鲜度的五条实战法则 (https://zhangwenbao.com/maintain-content-freshness-fast-indexing-ai-citations-2026.html)说明了哪些内容值得持续更新。 与其多做一份文件,不如先提高事实密度,提升引用率的七个动作 (https://zhangwenbao.com/boost-content-fact-density-ai-citations-2026.html)投入产出更清楚。 具体说:内容只列真正稳定的东西——品牌介绍、主要品类入口、政策条款、常见问题这类一年不会大改的;每条说明写一句话,不要写成营销文案;不要把商品列表放进去,那种东西一更新这份文件就过期了。做完之后在自己的排期里放一个半年后的复核提醒,到时候看看有没有厂商真的开始读它,再决定是加投入还是删掉。 反过来说,如果你现在的精力还不够把页面本身的结构化数据和正文可读性做扎实,那就别急着做这一份。读得到你正文的抓取方是确定存在的,读这份文件的还不确定存在——投入的顺序不该反。 ## 新字段和死字段的失效方式,一模一样 把这三行新字段和前面那些老字段并排放着看,会发现一个挺有意思的对称:它们失效的方式完全相同。 要判断某个标记的成色,看它在知识图谱里怎么被消费 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)比看文档更直接。 有些标记提出来很久也没等到广泛支持,用两个链接类标记提升内链效果 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)就是这种处境。 都是语法正确,都不会报错,都不会被工具提示,都得靠去查对方的文档才能知道有没有人读。唯一的区别是时间方向——老字段的收件人已经走了,新字段的收件人还没到。 这个对称给出了一条通用判据,比记住哪些字段作废了更耐用:不要问这个字段是不是有效的,要问现在有谁承诺会读它,以及在哪儿能查到这个承诺。能查到就写,查不到就当它是一个心愿,别当成一道防线。 ## 那到底该不该写 该写,但要清楚写的是什么。 真正决定能不能进候选池的是技术侧,突破AI候选池的五步技术优化 (https://zhangwenbao.com/technical-optimization-crawler-friendly-ai-citations-2026.html)是更该先做的。 表态之外还有更要紧的准备,从被看见到被AI推荐的三层框架 (https://zhangwenbao.com/ai-crawler-aeo-optimization-guide.html)列了六步行动。 写这几行的成本几乎为零,多几个字节而已,不会有任何副作用。它的收益也是真的:一旦哪天某家厂商开始读,你的表态已经在那儿了,不需要临时补。这跟提前把话说清楚是一个道理,成本低、时机不吃亏。 不能做的是把它当成已经生效的控制手段。如果你的真实需求是不想让内容进训练集,那么在今天这个时点,能起作用的仍然是老办法——在robots.txt里针对各家公开的训练爬虫令牌明确写Disallow,加上服务器层的访问控制。新字段是表态,老办法才是拦截。两件事不能互相替代。 ## robots.txt测试工具为什么查不出这些行? 看到这里可能会有个疑问:这么多现成的检测工具,怎么一个都没发现? 每类工具的能力边界都不一样,五大类工具各自能回答什么 (https://zhangwenbao.com/seo-tools-recommendation-2026.html)可以拿来配自己的组合。 越熟练的团队越容易漏掉这类问题,资深团队的技术SEO为什么会失灵 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)讲的是结构性盲区。 ## 工具校验的是语法,不是收件人 把常见的几类工具过一遍就明白了。搜索平台自带的robots.txt测试器,做的事是模拟自家爬虫对某个地址的匹配结果,回答的是这个地址我抓不抓;各类在线校验器,检查字段拼写、路径格式、通配符用法;SEO插件的体检模块,检查文件能不能取到、有没有意外屏蔽重要目录。 工具盲区这件事各处都有,六个工具盲区里的捡漏方法 (https://zhangwenbao.com/keyword-research-tool-blind-spots-overlooked-methods.html)是同一种思路的应用。 语法层的检查还是该做,页面骨架的六个维度体检 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)能揪出标题层级和图片说明的短板。 这三类工具都没有回答本文这个问题的能力。因为一行指令的收件人还在不在,不是文件里的信息,它在别人的文档里、在别人的更新公告里、在你自己的服务器日志里。工具读不到这些。 还有一层更微妙的:搜索平台自带的测试器只回答自家的行为。你在Google的工具里测,它当然不会告诉你写给bingbot的那一行有没有效——那不是它的事。 ## 几个在线校验器的结论为什么会互相矛盾 还有个现象经常让人困惑:同一份文件丢进三个在线校验器,得到三种说法。有的说某一行无效,有的一句话不说,有的甚至报语法错误。 原因不复杂。这些工具各自实现了一套解析逻辑,而它们参照的对象不一样——有的对齐标准文档,只认三个字段,其余全标成不支持;有的对齐某一家搜索引擎的实际行为;还有的对齐一份很多年前的字段清单,把Crawl-delay、Host一律当合法字段放过。三套参照物,三种结论。 所以工具报了不支持,不等于这一行对所有人都无效;工具没报错,更不等于它有效。要判断的还是那个老问题——你在意的那个收件人怎么读。工具能替你查语法,替不了你查收件人。 实操上有个折中办法:拿两类工具交叉看。一类是官方出的测试器,它代表这一家的真实行为;一类是对齐标准的校验器,它能告诉你哪些字段不在规范里。两边的差集,基本就是需要人工判断的部分。 ## 平台后台的编辑器同理,甚至更少 建站平台后台那个robots编辑框,通常只做两件事:语法不合法时不让保存,覆盖平台关键规则时给个警告。它不会告诉你新加的那个爬虫名字是不是真实存在的令牌,也不会告诉你Crawl-delay对你点名的对象有没有意义。 后台的告警也需要分级看,三平台后台告警怎么分级诊断 (https://zhangwenbao.com/webmaster-alert-triage-gsc-bing-baidu-three-platform.html)给了一套处理顺序。 这也解释了为什么无效行在用平台的站点上一样常见——保存按钮不报错,就等于通过了。 ## 唯一能证明生效的证据,在自己的日志里 要确认一条规则有没有起作用,能拿到的最硬证据只有一个地方:服务器访问日志。日志能回答两个问题——这个爬虫来没来过,以及它有没有去请求你禁止的路径。 想确认某个AI爬虫有没有来过,从日志一步步挖真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)是唯一可靠的路子。 日志读起来枯燥但信息量最大,怎么从日志里读懂抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)有一步步的示例。 这两个答案合起来才是完整的:如果它来了但不碰禁止的路径,说明规则被执行了;如果它来了还照样请求,说明规则对它无效或者它不遵守;如果它压根没来过,那么无论规则写成什么样都不产生任何差别。 第三种情况在本文的样本里占比高得惊人:同一批文件里点名的爬虫,有相当大一部分从来没在真实日志里出现过。 ## 日志里怎么查一条规则到底有没有被执行 具体做法比想象的简单。先确定要查的对象名字,然后在访问日志里筛出它的请求,看两件事:来了几次,都请求了哪些路径。 日志留多久决定了你能问多远的问题,日志怎么管才不爆盘又查得到 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)是配套要先做的事。 前提是日志本身记全了,访问日志怎么配才查得清问题 (https://zhangwenbao.com/apache-customlog-logformat-access-log-configuration-remoteip.html)包括CDN后面的真实来源地址。 grep -i 'bingbot' /www/wwwlogs/example.com.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -30 把输出里的路径和自己robots.txt里的禁止清单对一下,三种结果对应三种结论:路径里完全不出现被禁的目录,规则被执行了;出现了,说明这个对象不读或者不遵守你的规则;这个名字在日志里一条都搜不到,那么它那一整组规则写成什么样都不产生任何差别。 有两个坑要留意。一是User-Agent可以随便伪造,看到名字不等于真是它,重要判断要反查来源地址是不是属于对方公布的地址段。二是日志通常有保留期,短的只留七天,判断某个对象来没来过之前先确认自己的窗口有多长——用三天的日志得出它从来不来的结论,是不成立的。 ## 用差分法验证一行规则到底有没有被采纳 还有一个办法比日志更快,而且能在上线之前就用上:拿官方解析器做差分。 把差分结果存下来就成了基线,怎么搭一套能在掉量前报警的监控 (https://zhangwenbao.com/seo-monitoring-alerting-regression-detection-system.html)讲的就是这套积累。 差分这个思路在别处一样好用,对比爬虫和用户看到的页面 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)也是靠两次结果相减。 Google把自己用了二十年的robots.txt解析器开源了,编译出来是个命令行程序,喂给它三样东西——一份robots.txt、一个爬虫名、一个要测的地址——它输出这个地址允许还是不允许抓。这是唯一能拿到官方实现判定结果的通道。 关键用法不是单次判定,是差分。步骤只有三步: 第一步,准备一份待测地址清单,覆盖你关心的各类页面,几十个就够。第二步,用原始的robots.txt跑一遍,把每个地址的判定结果存下来。第三步,把你怀疑的那一行删掉,再跑一遍同一份清单,比较两次结果。 判断规则很简单:如果删掉那一行之后所有判定结果完全没变,那这一行对Google就是不起作用的。不需要读文档,不需要猜测,也不受任何人说法的影响——官方实现自己给出了答案。 把这个方法用在本文那些字段上,结果是可预期的:删掉Crawl-delay、Noindex、Host这三种行,判定结果一个都不会变。这不是推测,是标准里那条未识别字段必须忽略的规定所决定的必然结果。反过来,删掉一条Disallow或者一条Allow,一定会有地址的判定发生翻转。 这个办法有它的边界,得说清楚:它只能回答Google怎么读,回答不了Bing和其它爬虫怎么读,因为别家没有开源自己的实现。所以完整的验证还是要分两半——Google那一半用解析器差分,其它爬虫那一半只能靠日志和对方的文档。 ## 这些行为什么能在一个团队里活五年? 技术上讲,删掉一行没人读的指令是几秒钟的事。可实际上它们能待很久,这背后是组织问题不是技术问题。 只进不出这件事在工具栈上更明显,12个站样本里的冗余与八步瘦身 (https://zhangwenbao.com/ai-tool-stack-annual-audit-12-sites-4-dimensions-8-steps.html)是同一个治理思路。 这类活最后往往压在一两个人身上,这一行的慢性透支比多数人以为的严重 (https://zhangwenbao.com/seo-health-zhang-xuefeng-insight.html)附了一套自查办法。 ## 这个文件通常没有明确的负责人 问一个独立站团队谁负责robots.txt,答案往往要停顿一下。它躺在网站根目录里,改动方式是提交一次代码或者在后台点一下保存,涉及的知识横跨抓取、索引、服务端配置和内容策略。 没人负责往往不是态度问题,团队怎么搭、考核怎么对上 (https://zhangwenbao.com/seo-team-structure-and-output-based-performance.html)才是根子上的事。 结果是三方都能改,三方都不认领。前端觉得这是SEO的事,运维觉得这是内容策略的事,做SEO的人经常没有直接改文件的权限,得提需求。一个谁都能改、谁都不负责的文件,最自然的状态就是只进不出。 ## 三个角色看同一份文件,看到的东西不一样 更微妙的是三方的判断依据不同。运维看到一行Crawl-delay,第一反应是这跟服务器负载有关,不敢动;前端看到一个陌生的爬虫分组,觉得应该是有人特意加的,不敢动;做SEO的人看到那些路径,认出是老结构留下的,但他不确定删掉之后会不会影响别的东西,于是只在需求单里写建议清理,然后这条建议排到了下个季度。 人力怎么分也影响谁来管这类文件,内容、技术、外链三类分工与配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)有几种现成结构。 这类跨角色的活得有交接口径,后端与SEO协作的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)把责任切得比较清楚。 保哥前年帮一个跨境3C品牌做技术审查,那份robots.txt里有一行给某个不存在的爬虫令牌写的全站禁抓。追下去发现是四年前一次安全事件之后加的,加的人已经离职,工单里只留了一句按安全建议处理。这行字之所以能活四年,不是因为有人认为它有用,是因为没有人能证明它没用。 ## 只增不删,在个体层面是理性的 换个角度看,每一个不敢删的人都做出了对自己最优的选择。删掉一行没人读的规则,收益是零——文件干净一点,没有任何指标会变好;风险不是零——万一它其实有用,出了问题这笔账算在你头上。 排序的依据最好来自实测,500个站实测排出来的优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)比凭经验准。 要打破这个循环得先排出优先级,三类站点各自的高回报修复项 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以直接借。 零收益对上小概率大损失,理性选择当然是别碰。这个结构不改变,光靠提醒大家定期清理是没有用的。 ## 把风险从判断改成记录 能打破这个循环的做法,是把删除的风险从个人判断变成集体记录。具体就是前面提到的注释法:任何非常规字段和专属分组上面,必须有一行注释说明依据和确认日期。 内容侧也是靠同一招把责任落到流程上,内容运营与SEO协作的七个动作点 (https://zhangwenbao.com/content-operations-seo-collaboration-7-actions-topic-audit-22weeks.html)有可抄的表格。 这条规矩一旦立起来,文件里的行就分成了两类——有依据的和无依据的。删掉一行无依据的规则不再需要勇气,因为它不符合团队自己定的规矩,责任从个人转移到了流程。 ## 接手一份陌生的robots.txt,头五分钟看什么 换个场景。假设你刚接手一个站,打开robots.txt看到七十多行,完全不知道来路。按什么顺序读最快? 先数分组,不看规则。有几个User-agent组、每组点名了谁,这决定了这份文件的复杂度。只有一个通配组的文件,通常是模板默认状态,基本不用担心;分组超过五个的,说明有人认真管过,也说明踩坑的可能性更高。 然后比条数。通配组的Disallow有多少条,每个专属组有多少条,两边一减。哪个专属组明显少,就把它的路径差集列出来——那些是对这个爬虫放开的地址。 接着挑异常字段。把不是User-agent、Disallow、Allow、Sitemap的行全都拎出来,一行一个地问收件人是谁。本文那9种字段的表可以直接当对照表用。 最后抽路径。挑三条具体路径请求一下,看还在不在。三条里两条是404,就把通读整个文件排进日程。 四步下来五到十分钟,你对这份文件的判断已经比大多数长期维护它的人清楚了。这不是因为方法高明,而是因为绝大多数人从来没有系统地读过它——他们只是一次又一次地往末尾追加。 ## 这条规矩落地时会遇到什么 实际推行的时候会碰到两个具体阻力,提前知道能省不少来回。 责任怎么划清最终要落到文字上,达标定义与违约责任怎么写 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)有几个真实纠纷案例。 把审查交给自动化之前有几个前提,数据、方法、人工复核这三条 (https://zhangwenbao.com/ai-seo-geo-audit-agent-pitfalls.html)缺一条结论就不能用。 第一个是存量怎么办。文件里已经有几十行没注释的规则,要求一次性补齐注释,等于要求有人把每一行的来历都考古一遍,这个任务分不下去。可行的做法是只对增量立规矩:从今天起新增的行必须带注释,老行不动。等下一次有人因为别的原因要改到某个区块时,顺手把那个区块的注释补上。半年下来文件会自然地分成有注释的新区和无注释的旧区,旧区越来越小。 第二个是注释会不会泄露信息。robots.txt是任何人都能读的公开文件,注释里当然不能写内部系统名、人名、工单号这类东西。写法上有个简单原则:只写判断依据和日期,不写内部上下文。写某家文档说明支持这个字段,不写某某在某个工单里要求加的。前者对外人无意义,对自己人足够;后者反过来。 还有个额外好处容易被忽略:这些注释行会被所有读robots.txt的爬虫忽略,不影响任何解析结果。井号开头的行在标准里就是注释,各家实现一致跳过。所以这件事的技术风险是零,唯一的成本是打字。 这个办法对付前面讲的新字段同样好用。你今年写下Content-Signal,注释里写清是哪家的提案、当时有谁承诺读、什么时候该回头复核,那么两年后无论这套约定是普及了还是消失了,接手的人都能判断该留还是该删。 ## 五分钟怎么把自己文件里没人读的行找出来? 最后给一套能立刻做完的动作,不需要工具,一个文本编辑器加一个终端就够。 ## 第一步:把字段名列出来数一遍 打开自己的robots.txt,把所有冒号左边的词提取出来去重。正常结果应该只有4到5种:User-agent、Disallow、Allow、Sitemap,可能还有一个Crawl-delay。 同样的列举法用在链接上也管用,一次扒清链接结构与扣分项 (https://zhangwenbao.com/link-analyzer-internal-external-audit-guide.html)有现成的输出格式。 出现第六种就停下来查。本文157个站的样本里,全部字段名去重后只有9种,多出来的那4种全部属于本文讨论的对象。这一步花不了一分钟,命中率却相当高。 ## 第二步:给每个字段和每个爬虫名写上收件人 接着做一份两列的小表:左边是文件里出现的每一个字段和每一个爬虫名字,右边写谁读它,以及这个说法你在哪儿看到的。 新出现的抓取器要及时补进名单,这一类智能体爬虫怎么识别和应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是最近才有的功课。 每个对象的硬限制也值得记在同一张表里,抓取体积上限的实测拆解 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)给了具体数值。 右边填不出来的,就是要处理的行。注意这里要填的是来源,不是印象——凭印象填等于没填。查不到官方说明的爬虫令牌,通常意味着这个令牌是编的,或者早就改名了。 ## 第三步:抽三条具体路径实际请求一下 从Disallow里挑三条不带通配符的具体路径,直接在浏览器或者用命令行请求。看返回什么。 返回200也不代表内容在里面,抓取和渲染分几步、内容在哪一步丢 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)需要另一套检查。 请求方法选错会得出反向结论,用HEAD查说没配缓存头,换成GET那五个头全在 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)就是这么来的。 如果三条里有两条是404,那么这份文件已经和站点的实际结构脱节了,值得安排一次通读。要注意从外部请求可能被自家防护挡住,出现403、406、422这类状态码时,改成在服务器上对本机请求。 ## 第四步:把判断结果写成注释留在文件里 这一步最容易被跳过,但它决定了这次排查有没有长期价值。 判断依据最好和证据放在一起,把日志收成结构化可检索的形式 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)让复核变得可行。 robots.txt支持用井号写注释。在每个非常规字段和每个专属分组上面加一行注释,写清楚三件事:为什么写它、谁会读它、什么时候确认过。像这样: # 2026-08 确认:AhrefsBot 官方文档说明会读 Crawl-delay User-agent: AhrefsBot Crawl-delay: 10 一行注释的好处是,下一个人打开这个文件的时候,能立刻分清哪些行有依据、哪些行来路不明。少了这行,两年之后连你自己都会犹豫要不要删。 ## 完整的判断顺序 把整篇的判断压成一条链,遇到任何一行不确定的指令都可以照着走: 出问题时也是靠这种链式排除,四类原因的诊断决策树 (https://zhangwenbao.com/seo-traffic-drop-diagnosis-decision-tree-manual-algorithm-tech-seasonal.html)能快速缩小范围。 分层提问这个习惯用处很广,收录、排名、流量是三件事,先分清卡在哪 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)是最常用的一版。 先问这一行的收件人是谁——是所有爬虫,还是某一个具体的爬虫。再问这个收件人有没有公开承诺读这个字段,能不能找到那份文档或公告。找不到就当它无效。找到了,第三问是我这一行写的位置,对方按分组匹配规则能不能看到它。最后问,就算它能看到、也愿意执行,我想挡的那个东西现在还在不在。 四问全过,这行才是真正在起作用的规则。四问里任何一环断掉,它就只是一行看起来很负责的字。 ## 这套判断能迁移到别的地方 最后跳出robots.txt说一句。这四问之所以有用,不是因为它跟robots.txt有什么特殊关系,而是因为robots.txt恰好是最典型的那类配置:你写的东西,执行权在别人手里。 链接属性同样是写给别人看的声明,这几个标记到底还传不传权重 (https://zhangwenbao.com/nofollow-sponsored-ugc-link-rel-attribute-marking-mechanism.html)各家的处理并不一致。 缓存头也是各家客户端各读一部分,怎么配才让回头客秒开又不出改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)讲了取舍。 邮件那一侧有个几乎一样的例子,一键退订必须写两层,少一层整个域名就被限流 (https://zhangwenbao.com/one-click-unsubscribe-header-body-two-layers.html)也是收件人各认一套。 符合这个特征的地方还有不少。页面里的结构化数据,各家搜索引擎认的字段不一样;HTTP响应头里的一堆声明,读它的客户端各不相同,有些客户端早就不存在了;给邮件服务商看的域名策略记录,各家的执行严格程度差着级别;Cookie上的各种属性,浏览器之间也不完全对齐。 这些场景共享同一个特点:写下去不会报错,生效与否取决于对面那个你看不到的实现。所以判断方式也共享同一套——先问收件人是谁,再问能不能查到他的承诺,再问自己写的位置对方看不看得见,最后问要处理的那个对象还在不在。 这套问法还有个附带好处:它能挡住一类很常见的时间浪费——为一个根本没有收件人的声明反复调参数。把Crawl-delay从10改成5再改成2,把某个字段换三种拼法试一遍,都属于这一类。收件人不在的时候,参数怎么调都不会有反馈,而没有反馈的调整可以无限进行下去,还会让人觉得自己一直在优化。先确认对面有人,再谈调什么,顺序不能颠倒。 回到开头那句话。一条规则失效的时候,它不会告诉你。所以这件事只能反过来做:不等它告诉你,你主动去问收件人还在不在。这个动作花不了多少时间,麻烦的地方只在于,得先想起来该问。 ## 常见问题解答 Crawl-delay现在到底还能不能写? 能写,但要写清楚给谁。Google明确不读,写给它等于没写;Bing会读,它后台还另有抓取控制面板;AhrefsBot、MJ12bot这类第三方工具爬虫会读,写给它们是有效的。关键是位置——robots.txt的分组不继承,只写在通配组里而站内又给对方单开过分组,对方就读不到。157个站里写了Crawl-delay的有47个,能被bingbot真正读到的只有13个,占27.7%。想压Google的抓取频率,去Search Console调抓取速率设置,或者临时用503配合Retry-After。 怎么判断某个字段今天还有没有人读? 只认一种证据:能找到出处的公开说明。具体做一张两列表,左边写字段名或爬虫令牌,右边写谁承诺读它、这个说法在哪儿看到的。右边填不出来源的就当它无效。这里要防的是凭印象填——很多字段给人的感觉是通用的,实际只有某一家读,比如Host只有Yandex读过,而Yandex后来也改用重定向判断了。补充一个更硬的办法:Google的robots.txt解析器是开源的,拿自己的文件跑一遍,能直接看到它认了哪些行、忽略了哪些行。 robots.txt里的Noindex删掉,页面会不会又被收录? 不会,因为它本来就没在起作用。Google在2019年9月1日之后就不再读robots.txt里的Noindex,这一行在那之后写与不写没有区别。但删之前要确认一件事:你原本想让这些页面不收录的目标,现在有没有别的机制在承担。如果没有,删掉这行的同时要补上真正有效的手段——页面头部的meta robots标签,或者服务端按路径下发X-Robots-Tag响应头。注意顺序:必须先允许抓取,爬虫才能读到不收录的指示,先在robots.txt里禁抓会让它永远读不到。 Host这一行删了,对Yandex有影响吗? 基本没有。Yandex早已改成按301重定向和站长后台设置来判断主镜像域名,Host指令不再是必要条件。判断自己这行是不是有意为之,有个很快的办法:在文件里搜Yandex这个词,看它在别处出现过没有。本文这10个写了Host的站里,只有1个给Yandex的爬虫单开过分组,其余9个全文只在这一行提到过它——那基本就是从示例里抄来的。删之前顺手确认www与非www之间的301是通的、页面canonical写的是主域名,这两件事在位,Host有没有都一样。 Disallow了一个已经返回404的路径,需要清理吗? 不急,但值得记账。挡一个不存在的地址不浪费抓取预算,也不影响收录,直接危害接近于零。真正的代价是可读性:本文抽样的358条具体路径里,能判定存在性的176条有53.4%指向不存在的地址,这种文件会让接手的人失去判断力——分不清哪些行还有用,于是谁都不敢删,只能往后追加,越追加越没法读。建议的做法是给每条留下来的规则加一行注释,写清依据和确认日期,让删除变成一件有据可依的事而不是一次冒险。 Content-Signal和llms.md这类新写法,现在值得写吗? 值得写,但别把它当拦截手段。写的成本几乎为零,一旦哪天有厂商开始读,你的表态已经在那儿了。问题是目前没有主流抓取方公开承诺会读llms.md,Content-Signal也只有少数几家表态尊重。所以如果真实需求是不让内容进训练集,眼下能起作用的仍然是老办法:针对各家公开的训练爬虫令牌明确写Disallow,再加服务器层的访问控制。新写法是表态,老办法才是拦截,两件事不能互相替代。写的时候顺手加一行注释,标上是哪家的提案、什么时候该回头复核。 把后台入口写进Disallow,到底算不算加固? 不算,而且方向是反的。robots.txt是任何人都能读的公开文件,写进去的路径等于挂了一份清单:守规矩的爬虫会绕开,不守规矩的正好照着找。真正需要保护的地址应该走访问控制——登录校验、来源限制、地址段白名单,这些由自己的服务器执行,不需要对方配合。robots.txt适合写的是那些暴露了也无所谓、只是不想浪费抓取预算的路径,比如筛选参数、站内搜索结果页、加购地址。本文抽样里那几个把管理后台写进Disallow的站还多踩了一层:那个地址在它们自己域名下压根不存在,规则本身也是空转。 抽样只查了通配组,各个爬虫的专属分组要不要也过一遍? 要,而且专属组比通配组更值得看,因为它是人写的那部分。检查重点有两个:一是组名对不对,也就是那个爬虫令牌今天还存不存在、有没有改名;二是组里的规则条数,跟通配组比一比差多少——分组不继承,专属组少写的那些路径对这个爬虫就是放开的。本文的抽样之所以只取通配组,是因为专属组多由平台模板生成、路径高度重复,混进来会把比例带偏。真要动手排查,顺序应该反过来:先看专属组,再看通配组。 平台生成的robots.txt要不要改成自己维护? 看有没有明确的、模板满足不了的需求。本文157份文件里有67份出自同一套平台模板,这67个里只有27个存在无效指令——说明那些行不是模板给的,是后来有人加的。模板把基础部分写得不差。接管的代价是从此全部内容归你负责,平台后续更新的部分你也拿不到了。所以没有具体需求就别动,尤其别为了显得专业而加几行自己也不确定的规则,本文统计到的146条无效行,绝大多数就是这么进来的。 ## 权威参考资料 ## 商品页从首页点两下到不了,六成还挂在sitemap上 - URL:https://zhangwenbao.com/product-two-click-reachability-audit.html - 分类:技术SEO - 发布:2026-08-17 | 更新:2026-09-08 - 摘要:商品页迟迟不收录,改完标题补完sitemap还是没动静?多半是它在站内根本没有一条路可以走到。 - 关键词:技术SEO,电商SEO,Shopify > **TLDR**:摘要:拿41个英文电商站做了一次可达性实测。分母是这些站自己的商品清单,一共15643件;从首页出发、经过首页上能点到的分类页,两跳之内能走到13087件,走不到2556件,占16.3%。走不到的那批里有1520件仍然老老实实地写在sitemap里——爬虫知道有它,站内却没有一条路指过去。走得到的也不是都在明面上:按每页36件算,70.7%落在分类第一页,4.7%要翻到第11页往后才见得到,最靠后的一件排在第1033位。 > 摘要:拿41个英文电商站做了一次可达性实测。分母是这些站自己的商品清单,一共15643件;从首页出发、经过首页上能点到的分类页,两跳之内能走到13087件,走不到2556件,占16.3%。走不到的那批里有1520件仍然老老实实地写在sitemap里——爬虫知道有它,站内却没有一条路指过去。走得到的也不是都在明面上:按每页36件算,70.7%落在分类第一页,4.7%要翻到第11页往后才见得到,最靠后的一件排在第1033位。 先说清楚这件事的起点。做电商SEO的人多半有过这么一段经历:某个商品页迟迟不进索引,于是去改title、补描述、加结构化数据、往sitemap里再推一次。折腾一圈没动静,最后才发现——那个页面在整个站里没有任何一条链接指向它。 这个毛病有个不太好听的名字,叫孤岛页面。站内工具能扫出来,但扫出来的准不准,本身就是另一件事(保哥之前专门拆过孤岛页面检测的抽样口径怎么影响结论 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html))。这次换个角度:不扫自己的站,去看别人的。 ## 这次实测是怎么搭的,你要复现该注意什么? 先把口径钉死,不然后面所有数字都没意义。 ## 分母:这个店到底有多少件货 用的是各站自己的商品清单接口,也就是Shopify那个不用登录就能读的 /products.json。这个出口本身保哥单独写过一篇 (https://zhangwenbao.com/shopify-products-json-open-data-endpoint-audit.html),那篇讲的是它泄露了什么;这次只把它当尺子用,拿它回答一个问题:这个店对外发布了多少件商品。 它带分页,一页最多250条。我一直翻到返回不足250条为止,最多翻12页。翻满12页的站说明还没到底,分母只是个下界,这类站全部单独列出来,不进任何比例。 ## 分子:从首页出发两跳能走到的货 第一跳是首页上出现的 /collections/ 链接,第二跳是这些分类各自的商品清单。两跳的并集,再加上首页直接链到的商品,就是分子。 为什么卡在两跳?因为这是绝大多数电商站的设计意图——首页挂导航,导航进分类,分类列商品,也就是常说的扁平三层架构 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)。谷歌在电商站点结构那份文档里 (https://developers.google.com/search/docs/specialty/ecommerce/help-google-understand-your-ecommerce-site-structure)把这条路径写得很直白:从菜单链到分类页,从分类页链到子分类页,最后从子分类页链到所有商品页。文档里还有一句话,基本上就是本文要验证的东西:如果分类页没有直接链到这个分类下的全部商品,光靠爬取,Googlebot可能找不到你所有的货。 ## 哪些站被扣掉了,为什么 这一步花的时间比采集本身还长。60个候选站里,2个域名当时打不开,2个的商品清单返回空,剩下56个进了分析,最后只有41个进了干净口径。扣掉的理由分五类: 扣除理由 | 站 | 怎么发现的 | 出口列的地址前台打不开 | ugreen | 抽6个handle只有1个是200,页面还提示This site doesn't match your current location | 出口把颜色尺寸拆成了独立记录 | bollandbranch、peakdesign | 浏览器打开发现全部收敛到主商品页加参数 | 站里根本不用 /collections/ 这套地址 | harrys、functionofbeauty | 首页导航43条链接全挂在 /en/ 下面 | 商品清单翻页到顶还没到底 | aloyoga、everlane、flyingtiger、gymshark等 | 翻满12页仍返回250条 | 导航分类数超过采样上限80 | chubbiesshorts、fahertybrand、menuspace等 | 脚本自己记的标志位 | 第二类值得单独说几句。peakdesign的出口给了208条商品记录,sitemap给了247条,两边居然一个都对不上。第一反应是这站的sitemap漏得离谱。 实际不是。浏览器打开出口给的那个地址,比如 city-tote-15l-eclipse,直接301到了 city-tote?Size=15L&Color=Eclipse——它不是一件商品,是一个颜色尺寸组合。bollandbranch更彻底,2188条记录里2177条的handle结尾带一个下划线,全部收敛到主商品页加 ?color= 参数。这两个站的出口条数根本不是商品数,跟sitemap放在一起比是自找的。变体到底该合还是该拆,本身就是个老问题,产品变体的URL策略 (https://zhangwenbao.com/product-variant-seo-url-canonical-indexation-strategy.html)那篇讲得更全。 ## 从首页点两下,到底走得到多少件货? 41个站,15643件商品,两跳走得到13087件,整体覆盖率83.7%。但逐站算的话,中位是96.5%,均值86.5%,最低的那个站只有27.2%,另有14个站是满分。 中位96.5%和整体83.7%差了13个百分点。这个差距本身就是结论:大多数站没问题,问题集中在少数几个站,而这几个站恰好是商品最多的那几个。拿中位数汇报会让你觉得天下太平,拿总量汇报又会让你觉得遍地是坑。两个数得一起看。 ## 最差的那个站,问题不在漏了几个链接 magicspoon的覆盖率是27.2%,184件商品只有50件走得到。这个站的出口里有37个分类,但首页导航里能点到的只有一个,叫 shop-all。 一开始我以为是浏览器没把菜单展开完。换了一套更凶的展开逻辑重跑,又数了一遍首页导航里的链接——确实有十几条指向 /collections/,但它们全是 /collections/shop-all?filter=granola、/collections/shop-all?filter=pastries 这样的写法。去掉参数之后,还是同一个分类。 这就是问题的全貌:整站的商品导航是靠一个分类页加前端筛选参数实现的。对用户来说很顺手,点一下就换一组货;对爬虫来说,这些筛选参数不产生新的可抓取地址,shop-all 里装了50件,剩下134件就没有第二条路可走了。分面导航这套东西的治理老早就有成熟方案,筛选过滤怎么不拖垮抓取预算 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)那篇拆过完整清单,只是多数人担心的是筛选器生成太多URL,很少有人反过来担心它一个URL都不生成。 ## 其余几个低覆盖的站,各有各的毛病 站 | 商品 | 两跳走得到 | 走不到 | 其中在sitemap里 | magicspoon | 184 | 50(27.2%) | 134 | 41 | framebridge | 239 | 71(29.7%) | 168 | 47 | dreametech | 485 | 241(49.7%) | 244 | 57 | mackweldon | 575 | 306(53.2%) | 269 | 11 | liquiddeath | 210 | 121(57.6%) | 89 | 89 | brooklinen | 471 | 287(60.9%) | 184 | 14 | marinelayer | 2556 | 1680(65.7%) | 876 | 872 | decathlon | 518 | 347(67.0%) | 171 | 171 | 这几个站的分类页本身做得都不差(商品列表页那97条准则 (https://zhangwenbao.com/product-list-guidelines-scoring-selection-bias.html)里,大半他们都照做了),问题出在上一层。marinelayer那一行最值得盯着看:走不到的876件里,872件在sitemap里。decathlon更整齐,171件走不到,171件全在sitemap里,一件不多一件不少。 ## 走不到的那2556件,都去哪儿了? 把41个站走不到的商品并到一起,2556件里有1520件出现在自家sitemap中,占59.5%。剩下1036件两头都没有。 这两拨货的处境完全不一样,得分开说。 ## 在sitemap里的那1520件:能被发现,但没有分量 sitemap的作用是帮搜索引擎发现地址,它不负责说明这个地址有多重要。sitemap能不能提升排名 (https://zhangwenbao.com/does-sitemap-improve-google-ranking-myth.html)这个话题被讨论烂了,结论一直没变:能被发现和值得被排名是两码事。谷歌自己在电商文档里那句话也说得很客气——站内指向一个页面的链接越多,这个页面相对于站内其他页面就越重要。反过来读就是,一条站内链接都没有的页面,重要性下限是零。 所以这1520件的状态是:地址交出去了,Googlebot大概率也抓了,但站内没有任何一个页面替它说过话。它进不进索引全看内容本身够不够硬,一点外力都借不上。 ## 连sitemap都没有的那1036件:真的谁都不知道 rothys是个极端例子。这个站有734件商品,175件两跳走不到,而这175件一件都没进sitemap。既不在导航路径上,也不在给爬虫的清单上,它们唯一的存在证明是那个不用登录就能读的商品出口。 mackweldon也类似:269件走不到,只有11件在sitemap里。 这类货怎么被发现?大概只剩三条路——外部链接、站内搜索结果页(多数站这类页面是noindex的,而且查得到和查不到长得还一模一样 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html))、或者商品出口本身被当成feed抓走。都不是能指望的路。 ## 走得到,不等于看得见 第一问答完了,还有半个问题没答:走得到的那些货,是站在门口,还是排在队伍最后面? 我记了每件商品在它所在的每个首页可点分类里的位置,取最好的那个名次。能算出名次的有13027件——比可达的13087件少60件,那60件是首页直接链过去的,压根没经过分类页,不参与排队。这13027件里,中位名次是14——大半的货确实站在门口。往后就陡了:第75百分位是46,第90百分位跳到150,第95百分位333,第99百分位796,最靠后的一件排在第1033位。 名次要换算成页码才有意义,而每页放几件是主题定的。Shopify官方的collection对象文档 (https://shopify.dev/docs/api/liquid/objects/collection)写明 paginate 每页上限是50件,实际主题常用24、36、50三档。我不去猜哪个站用了哪一档,三档各算一遍: 每页件数 | 第1页 | 第2页 | 第3-5页 | 第6-10页 | 第11页往后 | 24 | 62.8% | 13.1% | 12.4% | 4.8% | 6.9% | 36 | 70.7% | 11.9% | 8.8% | 4.0% | 4.7% | 50 | 76.5% | 10.3% | 6.6% | 3.9% | 2.7% | 三档的结论方向一致:七成左右的货在第一页,但有3%到7%要翻过十页。翻十页是什么概念——用户不会翻,爬虫翻不翻取决于它愿意在这个站上花多少预算,而分页链接本身还会顺手把权重稀释掉一部分(内链权重漏进分页和重定向链 (https://zhangwenbao.com/internal-link-decay-equity-reclaim.html)这件事另有一篇专门讲)。 这个数比“走不走得到”更值得盯。走不到的是16.3%,是明确的病;排在第11页往后的这4.7%,账面上是健康的,实际处境跟前者差不了多少。 ## 哪些站的货排得最靠后? 按每页36件换算,逐站算一遍“有多少比例的货要翻过第一页”: 站 | 可达商品 | 第1页 | 要翻页 | 第6页往后 | 翻页占比 | casper | 215 | 99 | 116 | 22 | 54.0% | baseus | 218 | 102 | 116 | 25 | 53.2% | marinelayer | 1679 | 800 | 879 | 246 | 52.4% | awaytravel | 1011 | 498 | 513 | 300 | 50.7% | outdoorvoices | 590 | 322 | 268 | 205 | 45.4% | untuckit | 530 | 304 | 226 | 125 | 42.6% | parachutehome | 1513 | 981 | 532 | 136 | 35.2% | allbirds | 294 | 218 | 76 | 2 | 25.9% | awaytravel那一行的第四列值得留意:1011件可达商品里有300件排在第6页往后,占了29.7%。这个站的两跳覆盖率是98.3%,账面上近乎满分。 另一头,有六个站一件货都不用翻页:brooklynbedding、drinkolipop、liquiddeath、materialkitchen、oclean、ritual。共同点是商品少(最多210件)、分类切得细,每个分类都装不满一页。货少的站在这件事上天然占便宜,这不是能力问题,是规模问题。拿这几个站当榜样去要求一个几千SKU的站,没有意义。 ## 静态HTML数出来的导航为什么不能信? 整个实验里最容易翻车的是第一跳。我最初的做法是直接抓首页HTML,用正则捞 /collections/。跑完之后有四个站的读数是0——首页一个分类链接都没有。这个结论看着就不对劲。 换浏览器渲染一遍,答案出来了: 站 | 静态HTML | 渲染后DOM | gymshark | 0 | 92 | avocadogreenmattress | 0 | 14 | brooklinen | 5 | 29 | thirdlove | 11 | 49 | chubbiesshorts | 98 | 136 | 58个站里,渲染后更多的有11个,一样的39个,渲染后反而更少的有8个。最后一类挺反直觉:浏览器跑一遍,有的站菜单还没等脚本挂上去就被读走了,也有的站那个组件本身就没能正常起来。 所以两个通道都会漏,最终口径取的是两边的并集。就算这样,这个数仍然只是下界——爬虫和用户看到的页面不一样 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)这件事,从来不是一次测量能测干净的。 ## 我的尺子坏了六次,每次都差点写出一个错结论 这部分本来不打算写,后来觉得比结论更有用。做这类普查,最大的风险不是数据不够,是你量出来的东西根本不是你以为的那个东西。 坏在哪 | 差点写出的错结论 | 怎么发现的 | 把扁平的sitemap当成分卷索引,去抓了8个商品页当地图 | 这个站的sitemap里一件商品都没有 | 打印根文件的头几行,发现是urlset不是sitemapindex | 把 /es/ 语言版本也并进商品清单 | wusthof的sitemap比商品出口多出292件 | 按分卷地址里的语言前缀拆开重算,翻译过的handle被算成了另一批货 | 只用静态HTML抓导航 | 有四个站首页一个分类入口都没有 | 浏览器渲染一遍,gymshark从0变成92 | 把出口条数当商品数 | peakdesign的出口和sitemap完全对不上 | 浏览器打开发现全是变体级地址,301收敛到主商品 | 没验证出口地址在前台还活着 | ugreen有1270件商品没进sitemap | 抽样请求,6个里5个404,站按地区路由到了另一个店 | 把导航里的链接条数当成分类数 | magicspoon的首页其实能点到12个分类 | 去重后只有1个,那12条全指向 shop-all 加不同筛选参数 | 最后一条是我自己看错了自己的中间输出,不是站的问题。写下来是因为这个错误形态很典型:看到一个反常的数,先确认自己读的是哪个口径的数,再去怀疑数据源。同样的道理在补一组自对照就能把74%的差异砍到2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)那篇里讲过一次,这次又碰上了。 ## 这件事在你自己站上怎么查? 不需要写爬虫,三步就够。Shopify站可以照着抄,别的平台把地址换成对应的接口或者站点地图。 ## 第一步:拿到商品全集 curl -s "https://你的域名/products.json?limit=250&page=1" | jq -r '.products[].handle' > all.txt # 一直翻到返回不足 250 条为止,逐页追加 wc -l all.txt 翻页一定要翻到底。这一步偷懒,后面全白做。 ## 第二步:拿到首页真正能点到的分类 别用 curl 加正则,前面那张表已经说明问题了。用无头浏览器打开首页,把鼠标从导航项上依次划过一遍,再取链接: // playwright,取渲染后 DOM 里的分类 handle const s = new Set(); document.querySelectorAll('a[href]').forEach(a => { const m = (a.getAttribute('href')||'').match(/\/collections\/([^/?#]+)/); if (m) s.add(m[1].toLowerCase()); // 注意去掉查询参数再去重 }); 去重必须在去掉查询参数之后做,否则 shop-all?filter=a 和 shop-all?filter=b 会被当成两个分类,覆盖率立刻虚高。 ## 第三步:把两跳的并集减出来 for h in $(cat navcols.txt); do curl -s "https://你的域名/collections/$h/products.json?limit=250" | jq -r '.products[].handle' done | sort -u > reach.txt comm -23 <(sort -u all.txt) reach.txt > unreachable.txt wc -l unreachable.txt unreachable.txt 就是从首页两跳走不到的货。再跟sitemap对一次,就知道它们属于前面说的哪一拨。整个过程对一个几百SKU的站,跑完不超过十分钟。 ## 查出来之后,改哪几处最划算? 按投入产出排,从便宜的开始。 先看筛选参数有没有吃掉你的导航。这是magicspoon那个形态,也是最值钱的一处。判断方法很简单:把首页导航的链接抓下来,去掉查询参数再去重,如果去重后剩下的分类数是个位数、而你的分类总数是几十上百,那么你的分类体系在爬虫眼里几乎不存在。改法是给主要的筛选条件生成真实的分类地址,而不是全部塞进参数里。这件事牵动的不只是抓取,类目导航改版 (https://zhangwenbao.com/category-navigation-scope-custody.html)本身就是个反复返工的活。谷歌那份筛选类地址的抓取管理文档 (https://developers.google.com/crawling/docs/faceted-navigation)是从反面写的——它教你怎么让爬虫少抓一点,但同一套判据反过来用同样成立。 再看有没有一个真正的全集入口。14个覆盖率100%的站里,多数都在导航或者页脚挂了一个装下全部商品的分类。这一条几乎零成本,加一个链接的事——不用担心链接多了摊薄权重,那个稀释惩罚早就是个过时的幽灵 (https://zhangwenbao.com/too-many-internal-links-dilute-pagerank-myth.html)。入口摆在首页首屏的分类区 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)最省事。要注意的是这个入口本身可能很深——如果全集里有两千件货,那商品仍然排在第几十页,只解决了“走得到”,没解决“看得见”。 然后看分类的排序和分页。排在第11页往后的那批货,靠调排序规则就能救一部分。常见做法是给新品、有货、高毛利的商品加权重往前提,而不是一律按上架时间倒序。另外别把每页件数调得太小——每页24件和每页50件,第11页往后的比例差了2.6倍。 最后才是补sitemap。顺序不能反。sitemap解决的是发现,内链解决的是分量,先补sitemap会让你看到收录数上升然后停住,因为那些页面在站内仍然一票没有。顺带一提,生成器说格式正确的时候其实只查了三件事 (https://zhangwenbao.com/sitemap-generator-xml-lastmod-priority-validation-guide.html),它不会告诉你少列了谁。电商站的sitemap该怎么分片、lastmod怎么写才诚实,百万SKU的sitemap实战 (https://zhangwenbao.com/ecommerce-product-sitemap-strategy-sharding-lastmod-image-index.html)那篇有完整方案。 ## 改完怎么确认真的生效了 把第三步的脚本存成定时任务,每周跑一次,只看 unreachable.txt 的行数。这个数应该单调往下走。如果改完之后行数没变,多半是你新加的分类页本身没被首页链到——那就成了套娃,新开的分类页自己变成了孤岛。 ## 这条结论在什么情况下不成立 写到这儿必须把边界交代清楚,不然这篇文章就是在推销一个万能判据。 两跳这个口径本身是人为的。真实站点常有三层结构:首页到大类,大类到子类,子类才到商品。按两跳算,第三层的货全算“走不到”,但它们其实是设计好的、健康的。所以16.3%这个数应该读成“两跳之内的可达率”,不是“孤岛率”。要判断真孤岛,得把爬取深度放开到三跳四跳,代价是请求量翻好几倍。 货少的站没必要看这个指标。几十件商品的站,随便怎么摆都是全可达,测出来100%也说明不了什么。前面那六个零翻页的站就是例子。这套东西的价值区间大概是三百件商品往上。 不用 /collections/ 结构的站,这把尺子直接失效。harrys和functionofbeauty就是被这一条扣掉的。自建站、Magento、Shopify的无头前端,路径结构各不相同,得换成对应平台的分类地址规则重写正则,逻辑不变但代码要重写。 商品出口关掉的站测不了。这一整套的分母依赖那个公开的商品清单,站主把它关掉之后就只能退回到爬全站。这也是为什么样本只有六十个站——一百三十多个候选里,出口还开着的就这些,再走完一遍扣除只剩41个能算比例。 还有一点:这次采集是单线程、每个请求间隔2秒跑的,接口请求合计4893个,另外用无头浏览器打开了130多个页面,全程没有触发任何一个站的限流。如果你要对别人的站做这类测量,请保持同样的克制。 ## 常见问题解答 ## 两跳走不到,是不是就等于孤岛页面? 不等于。孤岛页面的定义是站内没有任何一条内链指向它,而两跳走不到只说明它不在“首页到分类到商品”这条主路径上。它可能挂在第三层的子分类下,可能被博客文章链过,也可能出现在推荐位里。要确认是真孤岛,得把全站爬完再看入链数。两跳这个口径低估了可达性,所以16.3%要读成孤岛率的上界,真实的孤岛只会比它少。 ## 那1520件在sitemap里的商品,Google到底会不会收录? 会抓,收不收录看内容本身。sitemap负责发现,不负责证明重要性。实际影响更多体现在优先级上——同一个站里,一个有几十条站内链接的商品页和一个一条都没有的,抓取频率和进索引的速度会拉开差距。想直观感受这件事,可以拿这两类页面各挑十个,去Search Console的网址检查里对比一下上次抓取时间,量大就走检查API批量拉 (https://zhangwenbao.com/gsc-url-inspection-api-bulk-index-monitoring.html)。 ## 为什么不直接看Search Console的内链报告? 可以看,但它回答的是另一个问题。内链报告统计的是Google已经发现的链接,是结果;本文测的是站点当前的导航结构能通向哪里,是原因。而且内链报告的数字和站内爬虫扫出来的经常对不上,两边口径不同,别硬凑。 ## 把每页商品数调大,是不是就能解决排队问题? 能缓解,但有代价。每页50件比每页24件确实把第11页往后的比例从6.9%压到2.7%,可是每页塞得越多,页面越重、首屏越慢。关键渲染路径 (https://zhangwenbao.com/critical-rendering-path-render-blocking-css-optimization.html)那笔账要一起算。比较稳妥的做法是每页36件加排序优化,而不是一味往上堆。 ## 我的站不是Shopify,这套方法还能用吗? 逻辑通用,实现要换。核心是三样东西:一份完整的商品清单、一份首页真正能点到的分类清单、每个分类下的商品清单。Magento有分类接口,WooCommerce有REST API,自建站最不济也能从sitemap拿商品全集、用无头浏览器爬两层。唯一不能省的是第二步必须用浏览器,静态HTML在这件事上不可靠。 ## 分类页做了无限滚动,这个测量还准吗? 分子的口径不受影响,因为我用的是分类的商品清单接口,不是页面上渲染出来的卡片。但“排在第几页”这个换算对无限滚动没有意义,得换成“要滚多少屏”。粗略换算是把每页件数换成一屏的商品数,通常是6到12件,那么名次150大约要滚十几屏——比翻四页还难指望。 ## 覆盖率要做到多少才算合格? 没有权威阈值,本文样本的中位是96.5%。保哥的经验判断是:低于90%就该查一下原因,低于70%基本可以断定导航结构出了系统性问题,而不是漏了几个链接。更重要的是看趋势——上新之后这个数掉不掉,比绝对值有用得多。 ## 权威参考资料 ## robots.txt分组不继承:157个站的实测 - URL:https://zhangwenbao.com/robots-txt-group-inheritance-default-audit.html - 分类:技术SEO - 发布:2026-08-16 | 更新:2026-08-16 - 摘要:你在robots.txt里给某个爬虫单开了一组,本意是收紧,实际却让它脱离了通配组的全部规则。这个坑在157个真实站点里有多少人踩了? - 关键词:robots.txt,技术SEO,独立站运营,爬虫管理 > **TLDR**:摘要:157份真实的robots.txt里,74个站为Google广告爬虫单开了一组,其中70个因此把通配组的规则整段漏掉,占94.6%,中位漏30条路径,最多的一个站漏了92条。更值得留意的是,这两段规则里绝大多数站主一个字都没写过——41.4% 的文件是建站平台生成的,而65个用同一套模板的站,竟然有64种不同的样子。 > 摘要:157份真实的robots.txt里,74个站为Google广告爬虫单开了一组,其中70个因此把通配组的规则整段漏掉,占94.6%,中位漏30条路径,最多的一个站漏了92条。更值得留意的是,这两段规则里绝大多数站主一个字都没写过——41.4% 的文件是建站平台生成的,而65个用同一套模板的站,竟然有64种不同的样子。 先说一件很多人没意识到的事:robots.txt这个文件里,规则不往下继承。 你在文件开头写了 User-agent: *,底下跟着四十条 Disallow,管住了购物车、结算页、账户中心、带筛选参数的集合页。写完你觉得这是全站的底线规则,谁来都得守。 然后你在文件下半部分补了一段,专门给某个AI爬虫开的,写着 User-agent: GPTBot,下面两三条 Disallow。你的本意是收紧——这个爬虫特别烦,得额外管管。 实际发生的事情正好相反。那一刻起,GPTBot就完全不受上面那四十条约束了。它只看自己那一组,通配组对它彻底失效。你写得越细,放开的越多。 这不是bug,是标准这么规定的。而标准写在一份你大概率没读过的文档里,你的robots.txt里没有任何一行字提醒你这件事正在发生。 近期OpenAI那边的说法把这个话题又推了一把。OpenAI表示robots.txt的规则可能不适用于它的取页机器人 (https://www.searchenginejournal.com/openai-says-robots-txt-may-not-apply-to-chatgpts-fetch-bot/585864/),理由是那次访问是真人在对话框里问出来的,不是爬虫自己在爬。同一份报告里,欧洲站点中约15% 被识别的AI取页请求,落在了站点明确标了禁止的地址上。 于是就有了这么个局面:一边是爬虫方说规则可能不适用,一边是站点自己写的规则根本没盖住想盖的对象。前者吵得很热闹,后者几乎没人查。 这次把211个海外品牌独立站的robots.txt全抓了一遍,能正常解析的157份,逐份按标准语义拆成分组,再逐个爬虫算它实际落在哪一组、和通配组差了多少条规则。下面全是这157份文件里数出来的。 ## 你的robots.txt里,有多少行是你自己写的? 先从这个问题开始,因为它决定了后面所有讨论的性质。 插件后台那一堆开关同样默认帮你选好了,一个出海独立站的逐项取舍清单 (https://zhangwenbao.com/rank-math-best-seo-settings.html)是照着过一遍的做法。 这个文件写废了的后果有多大,整站从搜索结果里消失的那类事故 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)就是最直接的样本。 ## 41.4% 的文件出自同一套模板 157份文件里,65份带着同一组特征:禁 /cart、禁 /checkout、禁 /orders,专门给 adsbot-google 开一组,禁掉一堆 /collections/*sort_by* 和 /collections/*%2B* 这样的排序与筛选参数组合。凡是做过独立站的人一眼就认出来,这是Shopify自动生成的默认robots.txt。 同一个平台还有别的东西是它替你生成的,一百二十八种结构化数据类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)是另一处要接管的默认。 模板禁的那几类页面是否合理,电商该屏蔽哪七类页面 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)里有逐类的判断依据。 65份,占41.4%。也就是说,这批站里每五个就有两个,robots.txt是开店时系统给的,不是人写的。 再往里看一层:这65个站里,只有16个(24.6%)在模板之外加过自己的 User-agent 分组。剩下49个站,文件从头到尾都是平台的默认内容,站主对里面每一条规则的知情程度,可能仅限于知道有这么个文件。 这本身不算错。默认模板写得其实不差,禁的都是该禁的:结算流程、账户页、会产生无穷组合的筛选URL。真正的问题在下一层。 ## 平台默认为什么普遍质量不低 顺便说说为什么这类默认模板往往写得比自己写的还好,这不是恭维平台,是有机制原因的。 平台替你处理的还有图片这一摊,从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)能看出默认做到了哪一步。 跨平台的共性坑不止这一处,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验的汇总。 一份平台默认模板服务的是几十上百万个店铺,它踩过的坑是所有店铺踩过的坑的并集。某个筛选参数导致索引爆炸,会有客服工单;某个接口路径被大量抓取拖垮服务,会有监控告警。这些反馈汇总到一处,最后变成模板里新增的一行。 而一个单独的站,它的robots.txt通常来自建站那天,之后除非出事,不会再动。默认值背后是海量样本的经验,你的自定义值背后是一个人某一天的判断。 这不是说不该自定义,而是说自定义之前要清楚自己在换掉什么。这也是后面会讲到的一个判断:接管默认值意味着接管它的维护责任,而这份责任原本是免费的。 ## 同一套模板,65个站有64种样子 把每个Shopify站通配组里的 Disallow 路径集合排序后取指纹,65个站得到了64个不同的指纹。换句话说,几乎没有任何两份是完全一样的。 版本不一致最怕赶上迁移,迁移不掉流量的六维度路线图 (https://zhangwenbao.com/site-migration-seo-no-traffic-loss-complete-guide.html)把要核对的东西列全了。 版本漂移要靠记录才看得见,把变更做成日志的十三类信号 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)讲的就是这套办法。 条数分布更直观:40条的有37个站,44条的5个,45条的4个,47条的2个,还有单独出现的3条、4条、7条、12条、33条、34条、35条、36条、38条、43条、48条、54条、56条、75条。中位数40,最小3,最大75。 同一个平台生成的默认文件,规则数能从3条跨到75条,跨度25倍。原因有两类:一类是店铺开得早,模板还是老版本,后来平台加的新规则没有回填;另一类是站主动过手,加了或删了几行,于是从模板的某个版本上分叉出去了。 这两类叠在一起的后果是:你没法靠“我用的是平台默认”来推断自己文件里有什么。邻居家的默认和你家的默认不是同一份东西。 ## 那些只有3条规则的店铺,缺了什么 最短的那份只有3条 Disallow。对照40条的主流版本,它缺的是后来平台陆续加进去的那一批:/cdn/wpm/*.js(网页像素监测脚本目录,54个站禁了)、/recommendations/products(推荐位接口,52个站禁了)、/*?*oseid=*(订单来源追踪参数,59个站禁了)、/apple-app-site-association、/.well-known/shopify/monorail。 平台自己加的追踪参数也会带来一堆地址,srsltid参数的四种处置方案 (https://zhangwenbao.com/google-srsltid-parameter-seo.html)是配套的处理。 筛选参数为什么必须堵,导航筛选URL不爆炸的系统方案 (https://zhangwenbao.com/faceted-navigation-filter-url-seo-crawl-trap.html)把成因拆得比较细。 这些路径的共同点是会产生大量近似重复的地址,或者是纯接口不该被当页面收录。平台后来把它们加进模板,是踩过坑之后的补丁。而老店铺的文件没跟着变,那些补丁对它不存在。 这里就出现了本文要反复用到的那个判断:“我什么都没改”不等于“什么都没发生”。模板在变,你的文件停在了签收那一天的版本。 ## 非Shopify的那92个站,情况反而更散 剩下92个站里,能识别出平台指纹的很少:WordPress特征2个、Magento 3个、BigCommerce 1个,其余大多是自研或者定制程度很高的站。这些文件的长度分布拉得极开,最大的一份13712字节、432行,通配组里265条 Disallow。 另一套电商系统的变体地址也会失控,变体的Schema、canonical与URL三层治理 (https://zhangwenbao.com/woocommerce-product-variations-seo-schema-canonical-url-deep-dive.html)是那边的解法。 换成另一套系统同样有默认值问题,虚拟与物理robots.txt的优先级 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)是那边最常踩的一个。 规则条数中位数是82条,最长的一份有368条规则、110个分组。到这个体量,文件已经不是一个人能通读的东西了,它更像是几年里不同人各加几行留下的地层。 我在做站点体检时习惯先看这个文件的行数。超过150行基本可以断定没人完整读过它。这不是苛责谁,一个没有测试、没有报错、改错了也不会有任何反馈的配置文件,本来就不具备被认真维护的条件。 ## 规模最大的那几份长什么样 把体量拉到极限看一眼。样本里最长的一份13712字节、432行,通配组里265条 Disallow;规则总条数最多的一份有368条;分组数最多的一份切了110个 User-agent 分组。 没人读的配置背后通常是没人负责,团队怎么搭才出活 (https://zhangwenbao.com/seo-team-structure-and-output-based-performance.html)说的是这件事的组织根因。 老站的配置层层叠加最后没人读得懂,资深团队的技术SEO为什么会失灵 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的是同一类结构性问题。 110个分组意味着什么?意味着这个站对110类访问者分别定义了策略,而按前面说的分组不继承规则,这110组里每一组都必须独立完整,任何一组缺了什么,对应的爬虫就获得了额外的权限。110组同时保持完整,靠人工是做不到的。 这类文件通常出现在有历史的大品牌站上,多个团队、多次改版、多个地区站合并,每一轮都往里加了几段。它们不是被设计出来的,是被沉积出来的。 做体检时遇到这种文件,更实际的做法不是逐条改,而是先把它按分组导出成表格,让人第一次看清楚里面到底有几套策略。看清楚之后八成会发现,其中一大半分组的规则内容其实完全一样,可以合并成一组多写几行 User-agent 就完事——文件能从四百行缩到八十行,而行为一个字都没变。 ## 为什么给一个爬虫单开一组,等于放开它? 这一节讲机制。机制不复杂,但它反直觉的程度足以让绝大多数人第一次听说时不相信。 要理解这条规则先得知道爬虫在整条链路的哪一环,抓取、索引、排名三步是怎么走的 (https://zhangwenbao.com/how-search-engines-work-crawl-index-rank.html)讲得最基础。 ## 规范里的原话是:只选一组,不合并 爬虫排除协议在2022年被写成了正式的互联网标准。RFC 9309这份标准文档 (https://www.rfc-editor.org/rfc/rfc9309.html)里对分组匹配的描述很直接:爬虫要在文件里找出所有 User-agent 值能匹配自己的分组,选出匹配得最具体的那一个,然后只执行那一组里的规则。 规则和理解之间隔着好几层,从关键词匹配走到意图理解的演变 (https://zhangwenbao.com/semantic-search-understanding-evolution-hummingbird-bert-mum.html)是另一条线的背景。 站内搜索该不该禁是个典型的分组决策题,四种处理方案的对比 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)可以顺着这条规则重新读一遍。 关键词是“只”。不是把匹配到的几组合并,不是先执行通配组再叠加专属组,是二选一。User-agent: * 那一组只在没有任何专属组匹配上的时候才轮到它。 再说得糙一点:通配组不是全局配置,它是兜底分支。谁被点了名,谁就从兜底里出列了。 ## 怎么判断哪一组更具体 匹配规则是前缀匹配,比较的是长度。文件里写 User-agent: Google,来的是Googlebot,能匹配上;同时文件里还有 User-agent: Googlebot-Image,那么Googlebot-Image这个爬虫会选后者,因为它匹配上的那个串更长、更具体。 前缀匹配这种规则对命名很敏感,slug命名的七维设计与上线后铁律 (https://zhangwenbao.com/url-structure-slug-naming-seo-design-framework-7-dimensions.html)是同一层的讲究。 服务端识别爬虫用的也是同一套名字,五种识别搜索引擎蜘蛛的写法 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)里能看到这些令牌长什么样。 这条规则带来两个实际后果。第一,Googlebot 和 Googlebot-Image 分属两组时,你以为写给Googlebot的规则对图片爬虫是无效的。第二,也是更常被忽略的:你只要在文件任何位置写下某个爬虫的名字,无论那一组内容多简单,都已经把它从通配组里摘出去了。 顺带说一句大小写。协议里 User-agent 的值是不区分大小写的,写 GPTBot 还是 gptbot 效果一样。但指令名和路径值不一样,路径是区分大小写的,/Admin 和 /admin 是两回事。这一点在做过URL大小写规范化的站上偶尔会咬人。 ## 一个可以自己核对的实例 拿allbirds.com这份文件说。它的通配组里有40条 Disallow,从 /a/downloads/-/* 一路禁到 /recommendations/products。 集合页这一类地址还要处理分页,分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)是紧接着的一步。 同一个平台上的集合页还有别的默认行为,集合页没有产品时该怎么处理 (https://zhangwenbao.com/seo-empty-shopify-collections.html)是另一个例子。 文件下半部分有这么一段: User-agent: adsbot-google Disallow: /checkouts/ Disallow: /checkout Disallow: /carts Disallow: /orders Disallow: /11044168/checkouts Disallow: /11044168/orders 6条。而通配组是40条。差出来的33条路径——集合页排序参数、博客的加号编码组合、主题预览参数、政策页、站内搜索、像素监测脚本目录——对Google广告爬虫全部是开放的。 这两段都不是allbirds写的,是Shopify生成的。模板同时提供了严格的通配组和宽松的专属组,而把两者的关系讲清楚的那句话,不在文件里。 ## 这算漏洞吗 严格讲不算,标准就是这么设计的,而且设计得有道理:分组不继承,意味着你可以给某个爬虫写一套完全独立的策略,不用担心被上面的规则牵制。灵活性是有代价的,代价是你必须自己保证专属组的完整性。 不是所有问题都能靠技术项解决,流量暴跌的七大元凶 (https://zhangwenbao.com/seo-cant-fix-broken-brand.html)里有更靠前的那些原因。 把这类问题排进修复队列要看影响面,三类站点的高回报修复顺序 (https://zhangwenbao.com/technical-seo-priorities-guide.html)给了一个可用的排序法。 问题出在心智模型上。大多数人对配置文件的默认想象是层叠的:全局设一套,局部覆盖几条,没覆盖的沿用全局。CSS是这样,nginx配置是这样,环境变量也是这样。robots.txt偏偏不是。 所以我更愿意把它叫做缺省分支被误读,而不是漏洞。你没有做出的那个决定——“专属组里要不要重复通配组的内容”——系统已经替你回答了,答案是不重复。 ## 如果连兜底分支都没有呢 顺着这个逻辑往下推一步:既然通配组是兜底,那不写通配组会怎样? 不设约束的另一面是不做适配,三类站点的移动端改造对比 (https://zhangwenbao.com/mobile-seo-optimization-guide.html)是另一处容易被跳过的基本功。 不设约束的后果最后体现在总量上,三类站点的聚合自然流量实测 (https://zhangwenbao.com/aggregate-organic-traffic-seo-metric-keyword-dead.html)是从结果反推的角度。 没有兜底意味着抓取量完全不受约束,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)是收拾这种局面的第一步。 答案是所有没被点名的爬虫完全不受任何限制。157个站里出现了1个这样的站,yeti.com。它认认真真给9个AI爬虫各写了规则,唯独没有 User-agent: * 这一组。 于是它的实际策略是:这9个被点名的按各自的规则来,其余所有爬虫——包括Googlebot、bingbot、各种SEO工具爬虫、以及所有它没想到的新爬虫——全站畅通无阻。 这个案例的价值在于它把整个逻辑推到了尽头:点名一个爬虫是把它从兜底里摘出来,而不写兜底,等于所有人都在兜底外面。两件事是同一条规则的两面。 要说明的是,yeti.com这么写未必是失误,也可能是有意为之——它想管的就是那9个,其余的本来就不打算管。判断一个配置是不是问题,得看意图;但至少要先知道它实际在做什么。 ## 74个站里70个漏了口子,到底漏了什么? 把机制说完,来看这157份文件里它实际造成了多大面积的影响。 抓来的东西不对路会带来别的麻烦,信息词流量过大的六大危害 (https://zhangwenbao.com/informational-keywords-traffic-dtc-ecommerce-seo-strategy.html)是另一种结构失衡。 口子开着最先长出来的就是垃圾页,索引膨胀的诊断与处置矩阵 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)给了处理顺序。 ## 数字先摆出来 为 adsbot-google 单开分组的站有74个。其中通配组规则条数多于专属组、也就是存在实际泄漏的,有70个,占94.6%。 地址层级本身就影响可达面,目录层级对SEO的六招优化 (https://zhangwenbao.com/impact-of-hierarchical-urls-on-seo.html)可以一起看。 这些数字要和后台报告对上才有用,五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)是配套的读法。 泄漏路径数的中位数是30条,最少3条,最多92条,70个站合计2140条。 站点 | 被漏掉的路径条数 | ikea.com | 92 | purple.com | 87 | peakperformance.com | 57 | chewy.com | 44 | taylorstitch.com | 41 | menuspace.com | 39 | aboutyou.com | 36 | nomadgoods.com | 35 | allbirds.com | 33 | dreametech.com | 33 | 74个站里有70个中招,这个比例高得不像是各自独立犯错的结果。它更像是同一个模板被复制了74份的结果,事实也确实如此。 ## 漏掉的都是哪几类路径 把70个站漏掉的路径汇总起来数频次,排在最前面的是这几类。 标签组合页是最典型的重复源,标签页怎么处理才不稀释权重 (https://zhangwenbao.com/shopify-blog-tag-seo.html)是配套的做法。 这些路径的形态和站点结构直接相关,一万个站的扁平URL实测结论 (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)给了结构层面的判断。 筛选页要不要写禁止其实有判别法,三类筛选URL的分流处理策略 (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)比一刀切靠谱。 路径模式 | 出现站数 | 它是什么 | /admin | 57 | 后台入口 | /collections/*sort_by* | 57 | 集合页排序参数,会生成大量近似页 | /collections/*+* 及其编码变体 | 57 | 多标签筛选组合,理论上无穷 | /blogs/*+* 及其编码变体 | 57 | 博客标签组合页 | /*?*oseid=* | 57 | 订单来源追踪参数 | /checkout | 51 | 结算流程 | /search | 51 | 站内搜索结果页 | /cdn/wpm/*.js | 51 | 像素监测脚本目录 | /recommendations/products | 51 | 推荐位接口 | 这份清单读下来会发现,被漏掉的恰恰是最该禁的那一类:参数组合型URL。一个集合页配三个筛选维度,能展开出成百上千个内容高度重叠的地址。通配组里那一长串 %2B、%2b、+ 的重复写法,就是为了把编码变体也堵上。 结果这些精心写的规则,对74个站里的广告爬虫全部不生效。 ## 为什么在广告场景下这件事更要紧 有人会说,AdsBot又不影响自然搜索排名,漏就漏了。这个判断只对了一半。 商品曝光那条链路上还有别的判定,六万商家实测的产品组排序 (https://zhangwenbao.com/google-product-packs-ecommerce-visibility.html)给了参照。 落地页被抓成什么样会进到排序里,购物广告排序的六大因素 (https://zhangwenbao.com/google-shopping-ranking-factors-traffic-exposure.html)里有这条链路的说明。 AdsBot系列爬虫的职责是抓落地页做广告质量评估。它抓到的是哪个版本的页面,会进到质量得分的计算里。如果它抓的是一个带了七八个筛选参数、内容稀薄、加载又慢的组合页,那么这个页面在广告系统眼里的表现,就不是你投放时指定的那个干净落地页的表现。 更麻烦的是量。参数组合是乘法关系,一个站放开筛选参数之后可访问地址数量可能翻两三个数量级。这些请求全部落在你的服务器上,而且因为是长尾组合,几乎必然全部穿透缓存直接打到源站。 保哥去年帮一个做户外装备的独立站查过一次源站负载异常。那个站的日常自然流量不高,但源站CPU常年在高位,缓存命中率只有六成出头。翻了三天日志,最后定位到大量带排序参数的集合页请求,来源是几个不同的官方爬虫。根因就是专属分组把通配组的参数规则漏掉了。把那几组补齐之后,缓存命中率回到九成以上,源站负载掉了一半。 ## Googlebot那边的情况 顺手也算了搜索爬虫。为 Googlebot 单开分组的站有22个,其中15个存在泄漏,合计377条路径。Googlebot-Image 被点名23次、17次泄漏,Googlebot-News 22次点名、15次泄漏,bingbot 10次点名、7次泄漏。 被抓到的重复地址还得靠规范标记收拢,八种跨页场景与冲突诊断 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)是紧接着的一步。 被抓到之后走哪条分支,八种未编入索引状态的决策路径 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)讲得很细。 同一个爬虫身上还有别的硬限制,抓取正文只读前两兆 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)那条同样很少有人测过。 泄漏最多的是purple.com,87条;awaytravel.com 47条;functionofbeauty.com 44条;eufy.com 43条;brooklynbedding.com 40条。 这里的性质比广告爬虫更直接:这些路径本来是不想让搜索引擎收录的,现在收录通道对最主要的那个搜索引擎敞开着。索引膨胀、抓取预算被参数页吃掉、正经页面更新发现变慢,是这条链路上最常见的三个后果。 ## 参数组合的量到底有多大 说“会产生大量地址”太抽象,算一次就具体了。 交叉分类会把组合数再放大一轮,交叉分类的五种优化方法 (https://zhangwenbao.com/shopify-product-cross-classification-seo.html)是控制它的办法。 地址结构本身决定了组合空间有多大,扁平与层级两种结构的取舍 (https://zhangwenbao.com/flat-urls-vs-hierarchical-urls-for-ecommerce-sites.html)可以一起考虑。 参数白名单是控制组合爆炸的正规做法,分层导航的URL重写与白名单治理 (https://zhangwenbao.com/magento-2-layered-navigation-seo-eav-url-rewrite-parameter-whitelist.html)给了完整配置。 取一个典型的服装类目页,筛选维度有尺码、颜色、价格区间、品类标签四个,各自可选值假设是8、12、5、20。如果这些筛选是通过URL参数实现的,且允许多选与任意组合,理论上可达的地址数是这四个维度可选子集的乘积。就算保守地只算单选情况,8×12×5×20就已经是9600个地址。 再乘上排序维度。sort_by 常见有6到8个取值,乘完接近7万。而这些地址背后是同一批商品,内容重叠度极高。 这就是为什么那一长串禁止规则要把 +、%2B、%2b 三种编码形式分别写一遍——只堵一种,另外两种照样能进。写规则的人考虑得很周到,而这份周到在专属分组那里被整段跳过了。 ## 抓取预算是怎么被吃掉的 抓取预算这个概念常被讲得很玄,其实机制很朴素:搜索引擎对每个站有一个大致的抓取速率上限,它由服务器响应能力和站点重要性共同决定,短期内是个相对固定的量。 资源被占的另一头是存储,增量备份与快照怎么做才不成灾 (https://zhangwenbao.com/linux-server-rsync-incremental-backup-snapshot-link-dest-offsite-restore.html)是同一类账。 预算被占的直接后果是新内容发现变慢,内容新鲜度的五条实战法则 (https://zhangwenbao.com/maintain-content-freshness-fast-indexing-ai-citations-2026.html)是另一头的应对。 预算被谁吃掉只有日志能回答,五千个站的爬虫伪造与抓取预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)是这套分析的样板。 爬虫每花一次请求去抓一个参数组合页,就少一次请求去抓你真正在乎的页面。当参数页的可达数量是正经页面的几十倍时,爬虫的大部分预算会花在自动生成的垃圾上,而新上架的商品要等好几天才被发现。 诊断这件事最直接的证据在日志里:按URL是否带参数分两组,统计各自的抓取请求占比。健康的站这个比例应该很低。保哥见过最夸张的一次是带参数请求占到七成以上,站主完全不知道,因为在搜索平台后台的报告里,这些地址混在总数里看不出来。 ## 为什么这个问题在报表里看不见 这一点值得单独讲,因为它解释了为什么94.6% 这个比例能长期存在而无人察觉。 看不见的东西有时能用正则挖出来,用正则从后台挖AI搜索提问 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)是个可复用的技巧。 报表读错比没有报表更危险,核心指标解析的四个常见错误 (https://zhangwenbao.com/google-analytics-metrics-misuse-guide.html)是同一类提醒。 后台报告本身也有它看不见的部分,三大数据黑洞与补全工程 (https://zhangwenbao.com/gsc-data-hidden-limits-1000-row-url-bucket-threshold-workaround-engineering.html)讲的是怎么绕过去。 搜索平台的抓取统计报告是按状态码、按文件类型、按响应用途分类的,没有一个维度是“这次抓取用的是哪一组robots.txt规则”。爬虫自己知道它命中的是哪一组,但这个信息不会出现在任何面向站长的界面里。 覆盖率报告那边同样看不出来。参数组合页被抓了、被判为重复内容、然后不建索引,最终在报告里体现为“已抓取但未编入索引”这一类——而这个类别下本来就堆着各种各样的地址,多几千个不显眼。 广告后台就更看不见了。它关心的是落地页体验评分,不会告诉你评分是基于哪个版本的页面算出来的。 所以这件事的发现路径只有两条:一条是自己读文件做减法,一条是自己读日志做分组统计。两条都得主动去做,没有任何系统会推给你。这也正是缺省分支这类问题的共同特征——它不产生错误,只产生偏差,而偏差没有告警。 ## 认真管AI爬虫的那26个站,谁做对了? 前面讲的都是平台默认造成的。接下来这一节看的是站主主动动手的部分,因为它更能说明问题——同样是认真在管,做法差异带来的结果能差出几百倍。 这类活得有人长期负责,GEO布局的四层落地框架与监测体系 (https://zhangwenbao.com/geo-team-deployment-four-layer-framework.html)给了组织形态。 这批爬虫的抓取量早就不是零头了,AI爬虫抓取量已经超过传统搜索爬虫数倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)是量级上的参照。 ## 26个站,3317条泄漏 157个站里,在robots.txt中主动点名过至少一个AI爬虫的,有26个,占16.6%。这26个站加起来的泄漏路径数是3317条。 被抓和被引用不是一回事,引用与排名脱钩之后的实战思路 (https://zhangwenbao.com/ai-overview-citations-diverge-rankings-bing-geo-2026.html)讲的是后半段。 想被这批爬虫好好读到,突破候选池的五步技术优化 (https://zhangwenbao.com/technical-optimization-crawler-friendly-ai-citations-2026.html)是正面做法。 要把这些爬虫在日志里分开数,八类UA的识别与流量归因方法 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)是可以直接照抄的。 但这3317条的分布极不均匀。 站点 | 点名的AI爬虫数 | 泄漏路径数 | awaytravel.com | 15 | 705 | flyingtiger.com | 15 | 660 | pullandbear.com | 4 | 300 | brooklynbedding.com | 7 | 280 | stanley1913.com | 7 | 273 | jackery.com | 6 | 270 | minted.com | 1 | 265 | gillette.com | 21 | 210 | framebridge.com | 20 | 0 | swarovski.com | 9 | 0 | yeti.com | 9 | 0 | quince.com | 6 | 0 | 注意最后四行。framebridge.com点名了20个AI爬虫,泄漏0条;swarovski.com点名9个,泄漏0;yeti.com点名9个,0;quince.com点名6个,0。 而awaytravel.com点名15个,泄漏705条。两边做的是同一件事,投入的力气也差不多,结果一个滴水不漏,一个把整份规则全放开了。 ## 差别就在那一段的写法 awaytravel.com那一段长这样: 写法细节决定爬虫能拿到什么,四种渲染模式下AI能读到多少 (https://zhangwenbao.com/ai-search-skips-spa-rendering-passage-level.html)是渲染层的同类问题。 新出现的智能体爬虫该怎么归类,Google-Agent的识别与应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是最近一个具体的例子。 User-agent: GPTBot User-agent: OAI-SearchBot User-agent: OpenAI-Operator User-agent: ChatGPT User-agent: Claude-Web User-agent: ClaudeBot User-agent: PerplexityBot User-agent: Google-Extended User-agent: Storebot-Google User-agent: Applebot Allow: / Disallow: /admin/ Disallow: /private/ Disallow: /checkout/ Disallow: /account/ 十个爬虫共用一组,组里先写 Allow: /,再写4条 Disallow。而这个站的通配组有47条。 意图很清楚:站主想说“这些AI爬虫可以来,但别碰后台和结算”。语义上没毛病,问题是它把通配组里另外43条规则一起免掉了——集合页参数、博客标签组合、追踪参数、主题预览,全部对这十个爬虫开放。而且开头那句 Allow: / 还额外做了一次强调。 framebridge.com那一段的写法完全不同:22个 User-agent 行连着排下来,然后把通配组的全部 Disallow 原样抄了一遍,一条不少。所以它的泄漏是0。 就这么一个差别。抄一遍,还是只写增量。 ## Allow: / 这一行的实际作用 顺便把 Allow: / 说清楚,因为它出现得很频繁,而作用常被高估。 另一个常被写了图安心的标记,规范网址的九大决策与完整设置 (https://zhangwenbao.com/canonical-url-seo-guide.html)里有正确用法。 另一个常被误用的写法是拿它去禁追踪参数,robots.txt能不能禁UTM参数 (https://zhangwenbao.com/robots-txt-disallow-utm.html)给了正确做法。 在robots.txt的语义里,没有被任何 Disallow 覆盖的路径,缺省就是允许。所以在一个只有 Disallow 的组里加一句 Allow: /,实际效果等于没加。它唯一有意义的场合是配合更长的 Disallow 做例外,比如禁掉 /private/ 但放开 /private/public-report/——这时候匹配按最长路径优先,Allow 才真正起作用。 把 Allow: / 写在专属组开头,最大的副作用是心理上的:它让人觉得这一组已经表达了完整策略,从而更不会去想“通配组那些规则是不是也得抄过来”。一句技术上无效的话,掩护了一个技术上很严重的遗漏。 ## 被点名最多的爬虫是哪几个 按点名站数排:GPTBot 14个站、PerplexityBot 14个、OAI-SearchBot 13个、ChatGPT-User 12个、ClaudeBot 12个、Google-Extended 10个、CCBot 9个、Applebot-Extended 9个、Amazonbot 8个、anthropic-ai 7个、Bytespider 7个、Perplexity-User 7个。 这几家的抓取行为差别不小,四大AI搜索引擎的分引擎策略 (https://zhangwenbao.com/ai-search-engine-geo-optimization-strategy.html)可以按名字对照着看。 名单写得再全也不如去日志里看谁真的来了,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)是一步步挖的过程。 被真正全站禁掉(专属组里写了 Disallow: /)的次数很少:Bytespider 4次、CCBot 3次、Amazonbot 2次,其余大多是0或1次。 这个分布本身有意思。大家点名AI爬虫,主流做法不是封杀,而是想做精细化管理——允许一部分、限制一部分。而精细化管理恰恰是最容易触发分组不继承这个坑的做法。真要全封反而不会出事,因为 Disallow: / 一条就覆盖了所有情况。 ## SEO工具爬虫那一栏 顺带看一眼这批站怎么对待第三方SEO工具的爬虫。MJ12bot 被点名34次、其中9次全禁;AhrefsBot 32次点名、4次全禁;BLEXBot 5次点名、4次全禁;SemrushBot 3次点名、2次全禁。 反代那一层可以做更细的分流,upstream与sub_filter的全场景配置 (https://zhangwenbao.com/nginx-proxy.html)是可落地的写法。 真要拦这类爬虫得在服务端做,按User-Agent拦截的三层防护写法 (https://zhangwenbao.com/wordpress-http_user_agent.html)比写在文本文件里管用。 点名多、全禁少,说明大部分站对这类爬虫是限速而不是拒绝——而限速用的正是下一节要讲的那条指令。 ## 两种缺省叠在一起的时候 把这26个主动管AI爬虫的站和前面的平台模板数据交叉一下,会看到一个特别的组合。 换一套架构之后基建得自己重搭,sitemap与重定向这套东西谁来负责 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是同一个归属问题。 两层来源不同的配置打架是常态,插件与主题各出一套canonical该怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一类问题。 26个站里有10个同时是Shopify模板站。这意味着它们的文件里存在两层来源不同的内容:通配组和广告爬虫组来自平台,AI爬虫组来自自己。而这两层是分别演化的——平台会更新前者,站主偶尔动后者,两边谁都不知道对方改了什么。 后果是通配组和AI组之间的差距会随时间自己扩大。平台往通配组加了三条新规则,AI组不会跟着加,泄漏数就从40涨到43。你什么都没做,问题自己长大了。 泄漏最严重的几个站正好都在这个组合里:awaytravel、flyingtiger、brooklynbedding、stanley1913、jackery、bollandbranch,全是Shopify站加自定义AI组。而泄漏为零的那几个里,framebridge也是Shopify站——区别只在于它把通配组整份抄了过去,抄的那一刻两层内容对齐了。 当然抄一次不等于永久对齐,平台下次更新通配组时它同样会开始漂移。所以这件事的正确形态不是“改一次改对”,而是“建立一个会定期重新对齐的机制”。 ## 写给不存在的爬虫的那些规则 还有一类问题,比漏规则更让人无奈:规则写对了,但写给了一个不存在的对象。 平台砍掉一个特性之后旧配置就成了摆设,FAQ富结果被砍之后该怎么办 (https://zhangwenbao.com/google-drops-faq-rich-results.html)是同一种清理。 该退休的东西留着不会报错但会误导,九个该淘汰的SEO指标 (https://zhangwenbao.com/retire-outdated-seo-metrics-2026-strategy.html)是另一份清理清单。 清点了一遍样本里的无效爬虫名,结果是这样:Claude-Web 出现在7个站里,这是Anthropic早期用过、后来已经弃用的名字;anthropic-ai 也是7个站,属于早年社区流传的非官方写法,从来不是官方公布的产品令牌;ia_archiver 3个站,那是互联网档案馆很多年前的爬虫;Slurp 2个站,Yahoo的搜索早已改由Bing提供。 最集中的一份出现在awaytravel.com。它那一组里写了 OpenAI-Operator、ChatGPT、DeepSeek、DeepSeek Assistant、R1、Grok 这几个值,没有一个是官方公布的爬虫令牌。 这些行不会报错,不会有任何提示,它们只是安静地不匹配任何东西。而写下它们的人多半觉得自己已经把这一批新出现的助手都管住了。 ## 名字写长写短都会出事 还有一个更细的坑值得单独说。匹配是前缀匹配,所以名字的长短直接影响命中范围。 类型名写错同样静默失效,十三种结构化数据类型的生成 (https://zhangwenbao.com/schema-generator-jsonld-13-types-guide.html)能避开手写的笔误。 字段名写错同样不会报错,两个内链结构化数据字段的正确用法 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)是可以拿来对照的例子。 精确到字符的写法在别处也一样重要,slug的九个影响抓取与排名的细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)是同一种较真。 写 User-agent: ChatGPT,按前缀匹配,ChatGPT-User 这个真实爬虫是能被它匹配上的——只要文件里没有更长更具体的组。这种时候写短反而误打误撞管住了。 但如果文件里同时还有一组写着 User-agent: ChatGPT-User,那么真实爬虫会选后者,前面那组白写。同一份文件里长短两个名字并存时,短的那个只对“没有更具体分组的那些”生效。 反过来写长了更常见也更危险:写 User-agent: Googlebot/2.1,加了版本号,就再也匹配不上了,因为真实的产品令牌是 Googlebot,前缀匹配比的是文件里的值是不是爬虫名的开头,而不是反过来。 判断方法只有一个:去对方的官方文档里抄那个产品令牌,一个字都不要改。凭印象写、凭直觉补版本号、凭习惯加连字符,都是在生成不会匹配任何东西的行。 ## 写了也不会生效的那几行 缺省分支这件事还有一个变体:你写了一条规则,对方压根不认这个字段。执行结果和你没写完全一样,但你以为自己写了。 要知道页面上到底有什么得扒一遍,一次扒清五种格式的字段缺漏 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)是审查的做法。 服务器这一层有一堆同样容易写了不生效的设置,二十项服务器配置清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以对照排查。 ## Crawl-delay:47个站写了,Google全部忽略 157份文件里,有47份(29.9%)用了 Crawl-delay。取值分布是:10出现82次、1出现33次、5出现6次、0.5出现4次、0出现2次、0.2和30各1次。 真被爬崩了要先定位瓶颈,负载飙高时的CPU、内存与磁盘排查 (https://zhangwenbao.com/linux-server-performance-troubleshooting-high-load-cpu-memory-disk-io-diagnosis.html)比限速更实际。 抓取速率要去后台调,后台过滤器的五步用法 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)是同一处界面里的另一组开关。 这个指令不在RFC 9309里,Google明确说过不支持它,Googlebot读到这一行会直接跳过。Bing和Yandex认,但认的方式和数值含义各家不同——各家搜索引擎对非标准指令的支持差异有一份逐项对照 (https://ahrefs.com/blog/robots-txt/),写规则之前值得先看一眼自己要管的那家在不在列。 取值10出现82次这件事本身也值得说一句。10秒一个请求,一天最多8640次抓取。对一个几万个URL的电商站来说,这个速率意味着全站抓一遍要好几天。如果这条真的生效了,写它的人多半会后悔。它没生效,反而救了一批站。 ## 还有两个已经作废的指令 robots.txt里写 Noindex 的站有2个。这个用法在2019年被Google正式停止支持,之前它是个非官方但确实有效的技巧。现在写它,等于什么都没写——页面照样会被收录,因为爬虫连页面都能抓,只是不会因为这行字而不建索引。 被高估的做法之外也有被低估的,九个被低估的技巧 (https://zhangwenbao.com/underrated-google-seo-tips.html)是另一头的清单。 既然这里的noindex早就失效,页面加了noindex之后多久才消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)说的是真正有效的那条路径。 Host 指令有10个站在用。这是Yandex早年用来声明主镜像域名的字段,Yandex自己也已经不再推荐,改用常规的301和canonical。其他搜索引擎从来没支持过。 另外有10个站存在同一个 User-agent 值在多个分组里重复出现的情况。标准对这种写法的处理是把它们视作同一组来合并,但不同爬虫的实现细节未必一致,属于应该避免的写法。 ## 无效指令比错误指令更麻烦 这一点想展开说说。写错一条 Disallow 路径,后果通常会以某种方式暴露出来——该禁的没禁住,你在覆盖率报告里看到了不该出现的地址;或者不该禁的禁了,页面从索引里掉出去,流量下滑,你会去查。错误是有反馈的。 有没有效最终要拿收录速度验证,三个平台三百站的收录实测 (https://zhangwenbao.com/seo-kpi-guide.html)是这类验证的做法。 有反馈的问题反而好处理,三个平台的告警分级与诊断闭环 (https://zhangwenbao.com/webmaster-alert-triage-gsc-bing-baidu-three-platform.html)讲的就是怎么把反馈用起来。 无效指令不一样。它安安静静地待在文件里,占着一行,给人一种“这件事我已经处理过了”的确定感。你不会再去想抓取频率的问题,因为你觉得写了 Crawl-delay 就管住了。等到真出问题的那天,你排查的方向会绕开这一行,因为它在你的记忆里是已完成状态。 所以做robots.txt体检时,第一步永远不是看规则对不对,而是把所有目标爬虫不支持的字段先挑出来删掉。删掉不改变任何实际行为,但它把文件里的虚假确定感清掉了,剩下的每一行才值得逐条推敲。 ## 还有一个反向的例子:站点地图那一行 不是所有非标准写法都是无效的。Sitemap 这一行同样不属于分组指令,它是文件级的声明,主流搜索引擎都认。157个站里有145个写了,覆盖率92.4%。 主动推送和被动等抓是两条路,API、JS与Sitemap三种推送方式 (https://zhangwenbao.com/baidu-post-real-time-push-tool.html)各有适用场景。 这一行指向的文件本身也很容易写错,两千四百个站踩过的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)都收在一处。 这个对比挺有意思:Sitemap 是社区先用起来、各家陆续跟进支持、最后进了标准;Crawl-delay 是社区先用起来、部分厂商支持、最大的那家始终不认、最后没进标准。写文件的人从表面上看不出区别,两者的行式一模一样,都是一个冒号加一个值。 能不能生效,取决于对面认不认,而不是取决于你写得多正式。这句话在本文后面还会再用一次。 ## Allow用了1874次,其中有多少是必要的 顺着这个话题把 Allow 的实际用量数一下。157个站里有91个用了 Allow,占58%,条数中位是13条,最多的一个站写了115条,全样本合计1874条。 写得多不如写得对,面包屑的四种类型与结构化数据实操 (https://zhangwenbao.com/seo-breadcrumbs-types-schema-implementation.html)是个正面例子。 写了一个属性未必等于产生了效果,nofollow到底还传不传权重 (https://zhangwenbao.com/nofollow-sponsored-ugc-link-rel-attribute-marking-mechanism.html)是另一个被高估的标记。 这个量级说明 Allow 已经是主流写法,不再是补丁。但要它真正起作用有个前提:必须存在一条更短的 Disallow 把它要放行的范围覆盖住。匹配时按路径长度取最长的那一条,长的赢。禁 /private/ 同时放行 /private/report/,后者更长,所以报告目录能被抓——这才是它设计出来要解决的问题。 反过来,在一个只有 Disallow 的组里写一句 Allow: /,没有任何一条 Disallow 会因此失效,因为 / 是最短的路径,永远输。这一行的全部作用就是让人看着安心。 ## 151行站点地图是怎么长出来的 再看一个量的问题。Sitemap 行有64个站写了不止一条,最多的delonghi.com写了151行,其次stokke.com 78行、hoka.com 65行、assos.com 29行。 多站点多语言还要考虑推送队列,实时推送与异步队列怎么搭 (https://zhangwenbao.com/wordpress-baidu-active-push.html)是配套的工程。 站点地图拆分本身有更清爽的做法,索引文件分页与动态优先级 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)是一套可落地的结构。 多写几条是合理的,大站按语言、按内容类型拆索引很常见。但到一百多条这个量级,多半不是设计出来的,是每上线一个新语言站点就往文件末尾追加一行,追加了几年。 这件事本身危害不大——爬虫会挨个去读。真正的信号在于它暴露了这份文件的维护方式:只有人往里加,没有人往外删。一个只增不减的配置文件,最后一定会变成没人敢动的样子,而它上面的每一行规则都还在生效。 ## 282个爬虫名里的地层 把157份文件里出现过的所有 User-agent 值汇总去重,得到282个不同的值。按出现站数排,前面是意料之中的:* 出现在166处,adsbot-google 74个站,MJ12bot 34个,AhrefsBot 32个。 旧公式为什么会失效,从关键词转向主题权威的变化 (https://zhangwenbao.com/keyword-seo-strategy-evolution-2026.html)是同一种代际更替。 陈年配置和陈年链接是一回事,死链批量检测、分类到提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)是清理的常规流程。 配置只增不减的毛病要靠流程治,把SEO配置纳入持续集成的做法 (https://zhangwenbao.com/seo-automation-engineering-ci-maintenance-architecture.html)是治本的那一档。 往下翻就有意思了:Nutch 29个站、HTTrack 8个、WebCopier 8个、Teleport 与 TeleportPro 各7个、WebZIP 7个、SiteSnagger 6个、WebStripper 6个、Microsoft.URL.Control 6个、UbiCrawler 5个。 这些名字属于一个特定年代。它们是二十年前的整站下载工具和实验性爬虫,绝大多数早已停止开发。29个站至今还在防备一个2000年代的开源爬虫,而它们中的大多数是最近几年才开的店。 原因不难猜:这些规则来自某个流传很广的robots.txt模板,被一代代复制下来。没有人删,因为删掉需要判断,而留着不需要。这就是配置文件的地层——每一层都是某个时刻某个人的合理决定,叠在一起就成了没人读得懂的东西。 ## robots.txt本身拿不到的时候,爬虫按什么办? 前面讨论的都是文件存在且能读的情况。但在这次抓取里,211个域名有54个根本没能拿到一份可解析的文件,占四分之一。这些站走的是另一个缺省分支,而这个分支的行为更少人知道。 这个地址在多域名下也得都能取到,多域名跳主域的完整配置 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)要一起检查。 不同状态码触发的处理完全不同,301、302、404与410各自的含义 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)是这一节的前置知识。 ## 21个站返回403,效果是全部放开 状态码分布是这样的:正常返回200的168个,返回403的有21个,返回404的4个,429的3个,400的1个,301之后没跟到目标的1个,完全连不上的13个。 防爆破规则同样容易误伤正常访问,密钥认证与fail2ban的尺度把握 (https://zhangwenbao.com/linux-server-ssh-login-hardening-key-auth-sudo-fail2ban-brute-force-protection.html)是可参照的例子。 防护规则收得太紧会误伤,从识别到应急拦截的处理顺序 (https://zhangwenbao.com/wordpress-ddos-protection-guide.html)里有把握尺度的办法。 边缘那一层怎么判定请求,六层缓存与边缘路由的实战配置 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)能解释403是怎么来的。 先说403这一组,它是非200里最大的一群。403属于4xx,而按主流搜索引擎的处理规则,4xx一律等同于“这个站没有robots.txt”,也就是全站允许抓取。 这里的落差很大。返回403的站,通常是因为边缘防护把请求当成了可疑流量——这次抓取用的是普通浏览器UA,从一个数据中心地址发出,被拦下来完全正常。但站主如果以为“连文件都拿不到,爬虫更进不来”,那就理解反了:拿不到规则文件不等于拿不到页面,前者的缺省是放行,不是拒绝。 更值得警惕的是不一致。防护规则对不同来源的判定不同,很可能出现官方爬虫能正常读到文件、而一部分请求读不到的情况。同一个站在不同爬虫眼里适用着不同的规则,而你从任何一个后台都看不到这件事。 ## 4xx与5xx的缺省正好相反 这是一组必须记住的对照。 跳转链路上的状态码同样要写对,双向跳转的完整配置 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)是最容易出环的一处。 这两类错误在后台报告里的处理也不一样,404修复与软404排查 (https://zhangwenbao.com/google-search-console-404-error-fix-guide.html)是配套的操作。 robots.txt的响应 | 爬虫的缺省处理 | 本次样本 | 200且可解析 | 按文件内容执行 | 157站 | 200但内容是HTML | 解析不出规则,等同于空文件,全部允许 | 9站 | 404 / 403等4xx | 等同于没有文件,全部允许 | 25站 | 429 / 5xx | 短期内视为全站禁止抓取 | 3站 | 连接超时或失败 | 按临时故障处理,倾向于暂停抓取 | 13站 | 4xx放开、5xx关闭,这两个方向相反的缺省背后是同一套逻辑:4xx是“确定没有这个东西”,那就按没有规则处理;5xx是“暂时问不到”,那就先别动,等问得到再说。 这套逻辑对爬虫是合理的,对站长却埋着一颗雷。如果你的站在发布期间短暂返回了5xx,robots.txt也跟着5xx,那段时间抓取会整体收缩。Google的处理是连续较长时间拿不到才会退回按404处理,也就是说这个收缩状态可能持续好几天,而你在任何监控里都不会看到告警——服务恢复了,抓取量却没立刻回来。 ## 9个站给出的是一张网页 还有一类更隐蔽:状态码是200,内容却是HTML。这次遇到9个,包括arcteryx.com、notino.com、temu.com、zalando.com、segway.com等。 单页应用的兜底路由是常见成因,九个维度的架构选型对比 (https://zhangwenbao.com/responsive-web-design-seo.html)能看出各方案的代价。 返回什么和渲染出什么是两件事,抓取和渲染分几步走 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)能解释这种错位。 状态码和内容对不上就是软404,错误页配置怎么写才不踩坑 (https://zhangwenbao.com/apache-errordocument-custom-error-pages-http-status-codes-soft-404.html)讲的正是这种错位。 成因通常是路由配置里没有为这个路径准备处理,请求落到了单页应用的兜底路由上,返回了首页或者一个错误提示页。从状态码上看一切正常,监控也不会报警。 爬虫拿到这份内容之后会尝试按行解析,每一行都不是合法指令,最终得到一份空规则集。结果和404一样是全部允许,但它比404更难发现——404至少会出现在覆盖率报告里,一个返回200的错误内容不会出现在任何报表里。 检查方法只需要一条命令:请求这个地址,看响应头里的 Content-Type 是不是 text/plain,看正文第一行是不是以 User-agent 或者 # 开头。两分钟的事,但很少有人把它写进上线检查项。 ## 还有5个站的文件小到不像有内容 顺带记一笔文件体积。157份里有5份小于100字节:kotn.com只有39字节、liu-jo.com 66字节、shopify.com 62字节、barkbox.com 81字节、hay.dk 94字节。 交付内容少不等于没做事,四板块汇报模板 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)能把工作讲清楚。 交付物有没有达标要事先定义清楚,达标定义与验收条款怎么写 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)是把这件事写进合同的做法。 这个体积通常只够写一个通配组加一两行内容,或者干脆就是一句 User-agent: * 加一句空的 Disallow:。空的 Disallow: 是标准里明确定义的写法,意思是显式声明不禁止任何东西,和不写这一行的效果相同,但它表达了一个明确的意图。 另外顺手数了两个格式细节:0份文件带字节序标记,这点比预期好——带标记会导致第一行被解析器吃掉;36份用的是Windows换行符,这个不影响解析,标准要求实现同时接受两种换行。 ## 这份数据本身的口径限制 把话说完整:上面这些状态码不能直接当成“这些站对搜索引擎也是这个状态”。 不同地区看到的搜索世界不一样,全球搜索引擎格局与多平台策略 (https://zhangwenbao.com/search-engine-landscape-seo-strategy-guide.html)是这种差异的背景。 口径不同结论就不同,网域资源与网址前缀资源的六场景选型 (https://zhangwenbao.com/domain-property-vs-url-prefix-property-in-gsc-which-is-better.html)是同一种口径陷阱。 同一个地址在不同地方拿到的结果不一样,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)能把这种差异定位清楚。 这次抓取是从一台位于中国境内的服务器发出的,用的是普通桌面浏览器UA,请求频率是四个并发。这三个条件里,前两个都会显著影响边缘防护的判定。同一个地址,Googlebot去请求大概率能拿到200,这次抓取拿到403,两件事完全可以同时为真。 13个完全连不上的域名里,有一部分是网络可达性问题,不是站点问题。这一类没有归入任何结论。 所以状态码这一节的正确读法是:它证明的不是“这21个站配错了”,而是“同一个地址会因为来源不同而给出不同的规则文件”。后者才是真正值得警惕的现象——如果规则文件本身就因人而异,那么“我的robots.txt写了什么”这个问题就没有唯一答案。 而前面那157份可解析文件的分析不受这个限制影响,因为那些结论全部来自文件内容本身的结构,与抓取来源无关。 ## OpenAI说这条规则可能不适用于它,那还要不要写? 回到开头提到的那条消息。这一节讲的是当缺省分支的解释权在对方手里时,你还剩下什么。 被看见和被引用是两件事,从被看见到被AI推荐的三层框架 (https://zhangwenbao.com/ai-crawler-aeo-optimization-guide.html)把这条链路拆开了。 ## 用户触发的抓取算不算爬虫 OpenAI的爬虫文档里对 ChatGPT-User 的定位是:用户在对话里提出问题时,它去取那个页面。文档同时表示,因为这类动作由用户发起,robots.txt的规则可能不适用。Perplexity对 Perplexity-User 的说法大体相同。Anthropic的立场不一样,它声明自己的三个爬虫都遵守这个文件。 这类访问在分析工具里怎么落账,过滤器加渠道分组的补法 (https://zhangwenbao.com/geo-ga4.html)是能立刻用的。 用户触发意味着流量来自具体的提问,AI可见度监测的四大误区 (https://zhangwenbao.com/prompt-tracking-guide.html)讲的是怎么把这类访问量起来。 这个分歧的实质是对“爬虫”这个词的定义。传统爬虫是自己排队、自己决定抓什么,站点没法逐次同意,所以需要一份预先声明的规则。而用户在对话框里贴一个网址让助手去读,行为形态更接近浏览器代访问——你不会指望robots.txt管住Chrome。 论证本身站得住。麻烦在于:如今主流助手取页都是这个形态,这个例外覆盖的范围正在从边角变成主流。一条规则如果它的例外大过本体,那它就不再是规则了。 ## 第三方统计给出的数字 TollBit那份关于机器人行为的半年度报告里给了几个可以对照的数:在被观察的欧洲站点里,约15% 被识别出的AI取页请求,落在了站点标记为禁止的地址上。ChatGPT-User、Bytespider、YouBot 三个爬虫各自在“明确列出过它们”的欧洲站点中,有接近一半的站点上出现了这种情况。 指标怎么定决定了结论长什么样,三层可见性指标的拆解 (https://zhangwenbao.com/geo-visibility-metrics-scoring.html)是一套可用的定义。 第三方数据要挑着信,二十款监测工具的深度评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)是判断口径的参照。 禁止率这边的数字则是另一个方向的对照:欧洲只有9% 的站禁 Claude-User,北美是26%;Perplexity-User 欧洲13%、北美26%。绝大多数较新的取页型爬虫在欧洲的禁止率是个位数。 把这两组数放一起:写规则的人不多,写了之后被绕过的比例不低。而在这份157个站的样本里,主动点名任何一个AI爬虫的只有26个(16.6%),和上面那个个位数到二十几个百分点的区间是能对上的。 ## 封掉取页机器人,换掉的是什么 这里有一个容易走错的岔路。有人为了拦住AI流量,把和OpenAI相关的爬虫名一次性全写进禁止清单。 自然流量结构正在重排,流量下滑背景下的生存指南 (https://zhangwenbao.com/organic-search-disrupted-aeo-strategy.html)是做取舍时的大盘参照。 封与不封背后是同一笔账,三千条数据揭开的引用认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)能帮着算这笔账。 问题在于这些名字的职责不同。按OpenAI自己的文档,决定一个站点会不会出现在ChatGPT的搜索结果里,负责的是 OAI-SearchBot,不是 ChatGPT-User。把两个一起禁掉的站,交出去的是被推荐的机会,留下来的是一个对方说可能不适用的抓取控制。 而且这笔交易的两头不对称:被推荐这件事是确定会失去的,因为搜索型爬虫大概率会遵守;抓取控制这件事是不确定会得到的,因为取页型爬虫那边有例外说法。确定的损失换不确定的收益,这个方向基本不用算就知道不划算。 另有数据显示对话式检索的索引里并不是只有大站,中小站点同样有可观的出现比例 (https://www.searchenginejournal.com/chatgpts-search-index-serves-small-sites-too-data-shows/585388/)。对一个刚起步的独立站来说,这条渠道的价值恰恰在早期最大。 ## 那还写不写 写。但要清楚这份文件的性质变了。 声明之外还得让别处也提到你,共识层六信号的九十天实战 (https://zhangwenbao.com/seo-consensus-layer-ai-search.html)是另一条路径。 声明类的东西到底有没有用,结构化数据对AI搜索的官方说法与实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)是同一种验证方式。 小站在这条渠道上的机会窗口更明显,中小网站不被剃光的九种打法 (https://zhangwenbao.com/geo-small-website-visibility-boost.html)讲的是怎么抓住它。 它现在更像是一份公开的意向声明,而不是一道闸门。声明的价值在于:遵守它的一方会照做(这仍然是大多数),不遵守的一方在被追究时没法说不知道,而你自己在做后续判断时有一份可引用的基线。 真正的闸门要放在别处。要拦,就在能拦住的那一层拦;要看,就看真实到达了什么,而不是看你要求了什么。服务器日志和CDN记录里躺着的是前者,robots.txt里写着的是后者,两者从来不是一回事。 ## 声明和执行分家之后,文件的用法要变 如果接受了“这是一份声明而不是闸门”的定位,用法上有几处要跟着调整。 真正的执行要落到权限上,五种环境禁掉目录执行权限的写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是同一种思路。 执行放到边缘层是现在的主流做法,在CDN边缘改SEO的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)给了几种实现。 第一,规则要写得能被外人读懂。既然它的作用是对外表态,那就该像一份公开条款那样写:分组清晰、注释说明为什么禁、必要时留一个联系方式。而不是像现在这样,四百行没有一句注释。 第二,别把敏感路径写进去。这是个老问题但一直有人踩:Disallow: /admin-secret-panel/ 这样的行等于把后台地址公开广播了一遍。这份文件谁都能读,把不想让人知道的地址写进禁止清单,是在做反向索引。 第三,规则和执行手段要配对。想拦训练型爬虫,声明写在robots.txt,执行放在边缘层;想控抓取频率,声明可以写,执行得去搜索平台后台调设置;想让页面不被收录,那根本不该用这个文件,该用 noindex。每写一条禁止,问一句“不遵守的话我怎么知道、我能做什么”,答不上来的那些,就当成纯声明看待。 第四,定期核对被点名的爬虫是不是还存在。前面数过,7个站在给一个已经弃用的名字写规则。这类清理没有收益,但能让文件保持在可读状态,而可读是后面所有工作的前提。 ## 通配组之外,还有谁在替你做决定? robots.txt不是唯一一个有缺省分支的地方。把视野拉开一点,同一条抓取链路上至少还有三层,每一层都有它自己的缺省。 多层叠加之后归因会变难,流量下降怎么跟老板交代 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)是八个维度的拆法。 现在的技术审查得多看几层,从AI爬虫到无障碍的五个新层面 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)是重新划分之后的清单。 ## 边缘层的默认拦截 今年这条链路上最大的变量在CDN。Cloudflare已宣布,从9月15日起,新加入的域名将采用一套新的默认设置:被归类为训练用途或代理用途的爬虫,在带广告的页面上默认被拦;搜索用途的爬虫仍然放行。同时,被判定为兼具搜索与训练双重用途的爬虫,会被所有“拦截AI训练”类的配置一起拦掉,包括那个旧的一键选项。 拦不拦爬虫也是一笔资源账,页面碳足迹与爬虫抓取的同一套规范 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)换了个角度算。 边缘层还能主动给爬虫换一种交付格式,用内容协商给智能体发Markdown (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是另一个方向的用法。 Googlebot正好落在双重用途这一类里。已经有站长报告说打开AI训练拦截之后搜索爬虫抓站点地图开始返回403 (https://www.searchenginejournal.com/report-that-cloudflare-ai-bot-blocking-prevents-googlebot-from-indexing-sites/584673/),关掉就恢复。Google那边的人在讨论串里请对方私信详查,这件事本身还没有定论。 类似的误伤不止这一例。边缘防护配置一旦设错对自然搜索表现的伤害有多直接 (https://www.seroundtable.com/misconfigure-cloudflare-seo-41865.html),是过去一年反复出现的话题——它们的共同点都是规则本身没写错,只是作用范围比设置的人以为的更大。 但不管那个具体案例是配置失误还是产品行为,有一点是确定的:一个你从来没打开过的开关,会在某个日期自动进入新状态,而通知你的方式是一篇博客。官方说明里也写了,9月15日之前所有客户都可以选择不采用新默认——这句话的另一面是,不主动选择就等于采用。 ## 三层规则的优先级 把这几层排一下,从外到内是这样。 非网页资源只能靠响应头管,自托管视频的收录与富媒体机制 (https://zhangwenbao.com/self-hosted-video-seo-indexing-rich-result-mechanism.html)是个具体场景。 这几层的字段各管什么,X-Robots、缓存与Vary的分工 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)有一份逐项说明。 层级 | 控制什么 | 缺省是什么 | 谁定义缺省 | CDN与WAF规则 | 请求能不能到达源站 | 按服务商的分类策略放行或拦截 | 服务商 | robots.txt | 爬虫要不要来抓 | 没被任何组匹配就是全允许 | 协议标准 | HTTP响应头X-Robots-Tag | 抓到之后能不能建索引 | 不写就是可索引可跟随 | 协议标准 | 页面里的meta robots | 同上,但要能读到页面才生效 | 不写就是可索引可跟随 | 协议标准 | 这张表里藏着一个经典矛盾:用robots.txt禁掉一个地址,爬虫就读不到那个页面里的 noindex。结果是这个地址反而可能以无摘要的形式留在索引里。想让一个页面彻底不进索引,正确做法是允许抓取、然后用 noindex,而不是在robots.txt里堵死。 这个坑之所以经典,是因为两个动作的直觉方向一致(都是“不要这个页面”),实际语义却互相抵消。 ## 响应头那一层为什么更可靠 表里那个 X-Robots-Tag 响应头值得多说两句,它是这几层里最被低估的一个。 响应这一层还能顺手做压缩,免插件压缩与压缩算法叠加 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)是同一处的改动。 两个标记同时用会不会打架,noindex和canonical的九种场景判断 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)把边界划清楚了。 它和页面里的 meta robots 语义完全一样,可写的值也一样,区别只在于它写在HTTP响应头里而不是HTML里。这个区别带来两个优势。 一是它能作用于非HTML资源。PDF、图片、纯文本导出文件里没法插 meta 标签,只能靠响应头。很多站的一大堆内部文档PDF被收录进索引,就是因为除了robots.txt之外没有别的手段可用,而robots.txt又恰恰是那个会让 noindex 读不到的手段。 二是它可以在服务器或边缘层按规则批量下发,不需要改模板、不需要重新构建。对一个有上万个动态生成地址的站来说,这是唯一现实的做法。 缺省当然还是“不写就是可索引”。但这一层的好处在于,它的缺省和你的部署流程离得很近——服务器配置是有版本管理、有评审、有回滚的,而robots.txt通常躺在某个后台文本框里,谁都能改,改了没有记录。 ## 爬虫的来源地址也不是你以为的那样 再补一个最近的例子。Google在文档里说明其爬虫的出口位置并不总是在美国 (https://www.seroundtable.com/google-crawlers-location-googlebot-41874.html),也可能来自其他地区,具体取决于调度。这意味着基于地理位置做的边缘拦截规则,可能在你不知道的时候误伤官方爬虫。 靠表面信号推断内部机制常常会错,从法庭文件里看到的真实排序逻辑 (https://zhangwenbao.com/direct-traffic-not-ranking-factor.html)是个很好的提醒。 验证爬虫身份的正确方式一直是反向DNS查询加正向确认,或者对照官方公布的地址段,而不是靠UA字符串或者来源国家。UA是可以随便写的,地理位置是会变的,只有反查是能站住的。 ## 日志里该看哪几个字段 既然结论是“看真实到达了什么”,那就把日志分析要看的东西列清楚,免得这句话停留在口号上。 日志文件本身的权限也得配对,目录权限与Web服务器的最佳组合 (https://zhangwenbao.com/linux-server-sets-files-folders-read-write-permissions.html)是前置条件。 日志要留得住才谈得上分析,日志轮转与检索不爆盘的配置 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)是前置工作。 最少需要五个字段:请求时间、请求地址(含查询参数,不要在日志里把参数截掉)、UA字符串、来源地址、响应状态码。有CDN的话还要加一个缓存命中标记,它能区分请求是打到边缘还是穿透到了源站。 拿到这五个字段之后,按下面几个维度分组统计,问题基本就浮出来了。 分组维度 | 看什么 | 异常信号 | 按UA归类的爬虫 | 各爬虫的请求量占比 | 某个爬虫量级远超预期 | 地址是否带查询参数 | 带参数请求占爬虫总请求的比例 | 比例偏高说明参数页在吃预算 | 命中的是哪类路径 | 结算、账户、搜索这类本该禁的路径有没有被抓 | 出现即说明规则没盖住 | 缓存命中标记 | 爬虫请求的缓存命中率 | 偏低说明抓的都是长尾组合 | 反查验证结果 | 自称是官方爬虫的请求里有多少通过了反查 | 未通过的是冒名流量 | 这几个统计做一次要不了半天,而它给出的是这条链路上唯一的事实。robots.txt里写的是意图,搜索平台报告里写的是结果,只有日志里写的是过程——而绝大多数抓取问题的根因都藏在过程里。 ## 单开一组时的正确写法 讲完机制和数据,这一节给可以直接照抄的做法。 这类改动通常要拉上后端一起做,工程侧七个动作点的分工 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)能减少来回。 ## 三种写法的对照 写法 | 专属组内容 | 实际效果 | 建议 | 只写增量 | 只有想额外收紧的那几条 | 通配组的全部规则失效 | 不要用 | 整份复制 | 通配组全文加上增量 | 与预期一致 | 推荐 | 全禁 | 只有一条Disallow: / | 与预期一致 | 确定要封时用 | 同一个需求有几种实现时先比可维护性,三种面包屑方案加结构化数据 (https://zhangwenbao.com/shopify-blog-breadcrumb.html)是同样的比法。 同一件事有几种方案时先看效果差异,分页SEO的五种方案对比 (https://zhangwenbao.com/category-pagination-seo.html)是同样的比法。 整份复制的缺点是文件会变长,而且通配组以后每加一条规则,所有专属组都得同步加。这个维护成本是真实的,也正是大多数站没这么做的原因。 但换个角度看,这个成本恰恰是你应该感受到的信号:每多点名一个爬虫,维护面就多一份。感受不到成本的时候,人会倾向于把爬虫名越写越多。 ## 五步自查 第一步,把文件里所有 User-agent 行列出来,数一数总共有几组。只有一组的站可以直接跳到第五步,本文讲的坑与你无关。 自查清单越具体越容易执行,十八个无障碍改动带来的自然流量变化 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)是一份可照抄的表。 自查完得排个先后,五百个站实测排出来的优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)是可以直接套的顺序。 第二步,把通配组的 Disallow 条数记下来,再把每个专属组的条数记下来,做个减法。任何一个专属组的条数明显少于通配组,就是候选问题点。 第三步,对候选问题点逐条比对,看通配组里有而专属组里没有的路径都是什么。如果里面出现了参数组合类、站内搜索类、后台类的路径,那就是真问题,不是有意的差异化。 第四步,用搜索平台提供的robots.txt测试工具,拿一个具体的问题地址加上具体的爬虫名去测。工具会告诉你实际命中的是哪一组、哪一行。这一步很重要,因为它是这套配置里唯一一处能拿到直接反馈的地方。 第五步,看那些不会生效的行:Crawl-delay、Noindex、Host,以及针对早已不存在的爬虫写的分组。删掉它们。 ## 改动之前该测什么 这五步里第四步的测试最容易被跳过,因为它需要挑具体的地址和具体的爬虫名,比通读文件麻烦。但跳过它,前三步的判断就全靠推理。 改完要验的不止一处,FAQ结构化数据改成能被引用的形态 (https://zhangwenbao.com/faq-schema-optimizer-rich-result-ai-citation-guide.html)也需要同一套验证。 配置类的东西都该先验后发,一个尾逗号让整页结构化数据失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)是不验就发的代价。 测试要挑的地址有三类。第一类是你明确不想被抓的,比如一个带三个筛选参数的集合页地址;第二类是你明确希望被抓的,比如一个新上架商品的详情页;第三类是处在边界上的,比如某个 Allow 规则想放行的那个子目录。 爬虫名要挑的也有三类:通配组代表(随便填一个没被点名的名字)、你点名过的每一个、以及最主要的那个搜索爬虫。把地址和爬虫名做笛卡尔积,逐个测一遍,工具会直接告诉你命中的是哪一行。 这个矩阵通常不大,三个地址乘五个爬虫名是十五次,十分钟能测完。而它给出的是这份配置里唯一的直接反馈——其余所有环节,包括修改保存成功这件事本身,都不构成任何验证。 测完记得把结果存一份,写清楚测的是哪个版本的文件。下次改动之后重跑同一套,两次结果对比就是回归测试。一份配置文件一旦有了回归测试,它的性质就从“碰运气”变成了“可维护”。 ## 如果文件是平台生成的怎么办 Shopify这类平台允许通过主题模板文件覆盖默认的robots.txt。改之前有两件事要想清楚。 接管平台生成的地址结构要一起处理跳转,标签地址优化与301实战 (https://zhangwenbao.com/shopify-tag-url.html)是配套动作。 接管平台默认和换主题是同一类风险,改版不掉流量的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)列了要接住的那些东西。 一是覆盖之后,平台后续对默认模板的更新就不会自动进到你的文件里了。前面数过,默认模板一直在加新规则,那些规则是踩坑之后的补丁。接管默认值的代价,是从此以后所有更新都得自己跟。 二是覆盖的粒度。多数情况下你需要的只是追加几行,而不是重写全文。能用追加的方式实现就不要整份替换,这样平台更新还能进来一部分。 如果实在拿不准,一个折中做法是:先不动文件,把当前版本存一份带日期的快照,每季度重新抓一次做差分。知道它变了,比控制它怎么变更重要,也便宜得多。 ## 把一份写错的文件改对,具体长什么样 拿前面那个泄漏705条的例子走一遍,因为它的错法非常典型。原来的写法是十个爬虫共用一组,组里一句 Allow: / 加四条禁止,而通配组有47条。 把规则做成可维护的分层,六层重写与缓存的综合治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)是服务器侧的同一思路。 改法有三个层次,按投入从小到大排。 最省事的一档:把这一整组删掉。删掉之后这十个爬虫回到通配组,自动适用那47条规则,而原本那四条禁止(后台、私有目录、结算、账户)本来就在通配组里覆盖着。也就是说,删掉这一组,实际策略反而变成了站主原本想要的那个样子。这一档适用于绝大多数情况。 中间一档:如果确实需要对这批爬虫多禁一个目录,那就把通配组47条原样复制进来,再追加那一条,同时删掉开头那句 Allow: /。文件会变长四十多行,但语义准确。 最讲究的一档:把通配组和专属组都放进构建流程,用模板生成robots.txt,通配组的规则作为一个片段被各个分组引用。这样以后往通配组加规则时,所有分组自动同步。做到这一步,分组不继承这个坑就被工程手段永久绕开了。 顺带把无效的爬虫名一并清掉:那五个不存在的令牌删了不影响任何行为,但能让下一个人少看五行噪音。 ## 怎么在变更发生时知道 最后说监测,这是本文里唯一一件必须做成自动化的事。 监测要闭环才有用,四步闭环与A/B测试方法 (https://zhangwenbao.com/monitor-measure-iterate-ai-citation-optimization-2026.html)是可以套过来的框架。 定时抓取加差分靠计划任务就能跑,用cron把独立站运维自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)给了脚本骨架。 做法很简单,一条定时任务:每天抓一次自己站的robots.txt,存下来,和上一份做差分,有变化就发通知。顺便记录状态码和 Content-Type,两者任何一个不对也发通知。 能抓到的东西比想象中多:平台悄悄更新了默认模板、同事在后台改了一行没说、某次发布把路由配置搞坏导致这个地址返回了首页、边缘防护规则更新之后这个地址开始返回403。这四类事情共同的特点是不会触发任何现有告警,因为站点本身完全正常。 再进一步,可以把同样的做法套到别的缺省上:定期抓自己首页的响应头存下来做差分,定期导出广告账户的关键设置做差分。凡是定义权不在你手里、又不会主动通知你的东西,快照加差分几乎是唯一的办法。 ## 什么时候该单开组,什么时候压根不该开? 这一节是判断题,不是操作题。 什么该做什么不该做要落到人头上,三类分工与团队配比的决策 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)是配套的组织答案。 ## 三种该开的情况 第一种,你确实要对某个爬虫做完全不同的策略,比如允许搜索型爬虫抓全站、只对训练型爬虫封掉正文目录。这种差异化用别的手段实现不了,必须分组。 差异化对待的前提是各平台确实不同,四大模型的差异化布局 (https://zhangwenbao.com/multi-platform-distribution-ecosystem-ai-citations-2026.html)给了具体差异。 区分对待不同爬虫的前提是知道它们各干什么,可见性的五个维度拆解 (https://zhangwenbao.com/ai-search-visibility-deep-seo-strategy.html)可以拿来对照。 第二种,某个爬虫的抓取行为明显异常,你需要给它单独限速,而它所属的搜索引擎恰好支持 Crawl-delay。注意这个前提,Google不在此列。 第三种,你要彻底封杀某个爬虫。这种情况下专属组里只写 Disallow: /,不存在漏掉的可能,是最安全的一种分组。 ## 更多时候不该开 如果你对某个爬虫的要求和对所有爬虫的要求是一样的,就不要给它单开组。把它留在通配组里,规则自动适用,一行都不用维护。 力气该花在更有回报的地方,低竞争词的九大挖掘策略 (https://zhangwenbao.com/low-competition-keywords-strategy.html)是回报更高的那一档。 技术项做满分也不一定有用,问题多半出在意图没对齐 (https://zhangwenbao.com/search-intent-alignment-vs-technical-seo.html)说的是同一种用力过猛。 这话听起来是废话,实际执行时却经常反过来。人在面对一个新出现的爬虫时,本能反应是“我得专门处理一下它”,于是加一个分组,写两条规则,心里踏实了。而这个动作真实的效果,是把它从原本管得好好的通配组里放了出来。 保哥的经验是,在这种场景下先问一句:我对它的要求,和对通配组里其他爬虫的要求,具体哪一条不同?答得上来就开组,并且把通配组整份抄过去再加那一条;答不上来,就别动文件。 ## 为什么“多写一点更安全”在这里不成立 这条直觉在大多数配置场景里是对的。防火墙规则多写一条更严,权限清单多写一条更紧,日志级别调高一档信息更全。写得多等于管得严,是个很稳的经验。 安全加固那边确实是写得越多越紧,版本隐藏、目录权限与访问控制 (https://zhangwenbao.com/apache-server-security-hardening-version-hide-directory-access-control-waf.html)正好是反例。 robots.txt把这条经验反过来了。在这里,多写一个 User-agent 分组,管辖范围是变小的,因为那个爬虫被从原本严格的兜底规则里放了出来。写得越细,管得越松。 之所以会这样,是因为这份文件的组织方式不是“规则列表”而是“对象分派”。它先按对象切分,再在每个对象名下写规则,对象之间彼此独立。而防火墙那类配置是先有一条条规则、再按顺序匹配,两种结构对“新增一条”的语义完全不同。 识别这类结构有个简单办法:看新增的那一行是加在规则序列里,还是加出了一个新的作用域。加在序列里,多写更严;加出新作用域,多写更松。前者像往清单里添一项,后者像开一个新分店,分店不自动继承总店的规矩。 ## 一个可以拿来自问的清单 把上面的判断压缩成四问,做robots.txt变更前过一遍: 不同阶段该问的问题不一样,大促与日常的八维度差异 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)是分场景的清单。 上线前的检查项越具体越好用,开发期十大优化要点清单 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)是同一种写法。 这次改动是不是新增一个 User-agent 分组?如果是,通配组的规则我抄过去了吗? 我打算写的这个字段,我要管的那个爬虫认不认?有没有官方文档写着它支持? 这个地址我是想让它不被抓,还是想让它不被收录?如果是后者,我用的是robots.txt还是 noindex? 这份文件除了我还有谁能改?平台会不会自己动它?我上次看它是什么时候? ## 这套判断能不能用到robots.txt以外的地方? 能,而且这才是本文真正想留下的东西。robots.txt只是一个特别干净的样本。 把一类判断推广开来要有指标支撑,从指标体系到异常诊断 (https://zhangwenbao.com/seo-data-analysis-guide.html)是搭这套支撑的办法。 ## 缺省分支这件事的一般形态 把这一整篇抽象一下,结构是这样:你没有做的那个决定,也已经有了一个答案。系统不会因为你没表态就停在原地等你,它会走缺省分支。而缺省分支的定义权,不在你这边。 不声明就由对方替你选,规范网址的九大决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)是最典型的另一个例子。 robots.txt里,那个没被做的决定是“专属组要不要重复通配组的内容”,缺省答案是“不重复”,定义权在协议标准手上。你查得到这条规定,规范文档是公开的,但你的文件里没有任何东西提醒你它正在生效。 这是缺省分支最温和的一种形态——成文、公开、可查,只是不会主动找上你。应对办法也最简单:把缺省显式写出来。哪怕写出来的值和缺省完全一样,它也从此进入了代码评审、进入了版本历史、进入了下一个人接手时会读到的范围。 ## 同一个结构在别处的样子 找几个身边的例子对照一下就清楚了。 归因窗口这类默认值影响很大,服务器端跟踪还原完整链路的八步 (https://zhangwenbao.com/dtc-ga4-bigquery-user-journey-stape-server-side.html)是把它拿回来的做法。 分析工具那边的默认分组同样没人改,默认渠道组到底怎么归类 (https://zhangwenbao.com/ga4-default-channel-grouping-complete-guide.html)值得先弄明白。 页面上不写 meta robots,缺省是可索引可跟随;不写 canonical,缺省是搜索引擎自己选一个;不写 Cache-Control,缺省是各级缓存按启发式规则自己猜一个有效期;广告系列不设否定关键词,缺省是系统按它认为相关的范围去匹配;分析工具不配转化窗口,缺省是平台给的那个默认天数。 这几件事的共同点是:它们全都不会报错。没有任何一个环节会告诉你“这里你没配置”。系统运行得好好的,只是运行在别人写的那个值上。 ## 把缺省显式化的三条实操 第一条,配置文件里把关键缺省值写出来,加一行注释说明这是缺省值、来自哪份文档。多写一行的成本,换的是下一个人不用去查规范。 分类页的标题描述不写就由系统拼,自定义TDK的现代化方案 (https://zhangwenbao.com/wordpress-categories-seo-add-custom-titles-keywords-descriptions.html)是显式化的样板。 把每类页面的取值明确写死是个好习惯,五类页面的差异化配置 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)是一份现成的表。 第二条,做变更评审时,把“这次没改的部分是什么状态”当成一个正式的检查项。评审天然只关注diff,而缺省分支恰恰不在diff里。 第三条,对那些定义权在第三方手里的缺省,建立定期快照。前面说的每季度抓一次robots.txt做差分就是这个思路,它便宜、可自动化,而且是你唯一能拿到变更信号的方式。 这三条里最容易被跳过的是第二条,最有效的也是第二条。 ## 缺省的三种可见度,处理方式完全不同 把缺省按“你能不能查到、能不能测到、能不能改”分成三档,应对的力气该往哪儿花就清楚了。 能查、能测、能改,三件事要分开看,后台数字为什么人人都读错 (https://zhangwenbao.com/google-search-console-complete-guide-diagnosis.html)讲的是第二档的难处。 类型 | 典型例子 | 判据 | 该做的事 | 成文可查 | robots.txt分组不继承、不写meta robots即可索引 | 有公开规范写着,但没人提醒你 | 照规范把缺省显式写出来 | 不成文但可测 | 响应头随请求方式变化、缓存的启发式有效期 | 文档不写,但两次不同的请求就能试出来 | 实测取基线,纳入回归检查 | 第三方持有且会变 | 边缘防护的默认拦截策略、平台生成的模板 | 你既没参与定义,也不会被单独通知 | 定期快照做差分,抢在生效日前主动选择 | 这三档的顺序不能颠倒。第一档花的是查文档的时间,第二档花的是搭测试的时间,第三档花的是持续监测的时间,成本一档比一档高。而大多数人的实际做法是跳过前两档直接抱怨第三档,这就把最便宜的收益放掉了。 本文整篇讲的都是第一档。robots.txt分组不继承这件事,标准文档里白纸黑字写着,任何人花十分钟都能读完,可它造成的实际影响是74个站里70个漏了几十条规则。不是难,是没人告诉你这里有个决定需要你做。 ## 做决定和不做决定,成本是不对称的 最后留一句可以带走的判断。 不做决定的账最后总要还,老内容流量悄悄下滑的识别与分级 (https://zhangwenbao.com/content-decay-mechanism-portfolio-roi-tiering.html)是另一笔慢慢累积的账。 做一个决定,成本是一次性的:查文档、写下来、评审通过。不做决定,成本是持续的,而且要等到某个不确定的时刻才一次性结算——可能是索引膨胀被发现的那天,可能是源站扛不住的那天,也可能是平台默认变更生效的那天。 更麻烦的是,不做决定这件事在账面上是零成本的。它不占工时,不进排期,不出现在任何一份报告里。所以在资源紧张的时候,被砍掉的永远是“把缺省显式写出来”这类工作,因为它看起来什么都没改变。 确实什么都没改变。它改变的是下一次有人来看这份配置时,能不能看懂它到底在做什么。这个价值在你还在这个岗位上的时候看不出来,等到接手的人换了一轮才显现——而那时候没人会把这笔账算回到当初那个决定上。 ## 常见问题解答 ## robots.txt里的分组真的完全不继承吗? 是的。爬虫排除协议的标准文档里写得很明确:爬虫在文件中找出所有能匹配自己的分组,选出匹配得最具体的那一个,然后只执行那一组的规则。User-agent: * 那一组只在没有任何专属组匹配的时候才生效,它是兜底分支,不是全局配置。所以一旦你在文件任何位置写下某个爬虫的名字,无论那一组内容多简单,它都已经脱离通配组了。 ## 怎么快速判断自己的站有没有中这个坑? 数两个数就行。第一个数是通配组里 Disallow 的条数,第二个数是每个专属组里 Disallow 的条数。只要有任何一个专属组明显少于通配组,就把两边的路径列出来做差集,看漏掉的那些是不是参数组合页、站内搜索、后台入口这类。是的话就是真问题。在这份157个站的样本里,用这个方法查出来的中招比例是:给广告爬虫单开组的74个站里,70个存在泄漏。 ## 我用的是建站平台的默认robots.txt,需要管吗? 需要看一眼,多数情况下不需要改。这批样本里41.4% 的文件出自同一套平台模板,模板本身写得不差。但要注意两件事:一是模板会随平台更新而变化,65个用同一套模板的站里出现了64种不同的规则集合,说明不同时期开的店拿到的是不同版本;二是模板里那个给广告爬虫开的分组,天然就比通配组宽松几十条。知道这两件事,比急着动手改文件更有价值。 ## Crawl-delay到底还能不能用? 看你要管谁。Google明确不支持,Googlebot读到会直接跳过;Bing和Yandex认,但各家对数值的解释不完全一样。样本里有29.9% 的站写了这一行,最常见的取值是10。如果你的目标是压Googlebot的抓取频率,这行字没有任何作用,应该去搜索平台后台调抓取速率设置,或者用服务器端返回503配合Retry-After做临时降速。 ## 想让一个页面不出现在搜索结果里,该用robots.txt还是noindex? 用 noindex,并且必须允许抓取。这两个手段的关系是互斥的:在robots.txt里禁掉一个地址,爬虫就读不到那个页面里的 noindex 标记,结果这个地址反而可能以无摘要的形式留在索引里。正确顺序是先放开抓取,让爬虫读到 noindex,等它从索引里消失之后,如果确实想省抓取预算,再考虑要不要在robots.txt里加禁止。 ## 为什么封掉ChatGPT相关爬虫要慎重? 因为这些名字的职责不同。按OpenAI自己的文档,决定站点会不会出现在ChatGPT搜索结果里的是搜索型爬虫,而不是那个用户触发的取页爬虫;同时对方表示,取页那个可能不适用robots.txt规则。两个一起封的结果是,被推荐的机会大概率真的失去了,而抓取控制那一半对方说可能不适用。确定的损失换不确定的收益,方向上就不划算。 ## robots.txt返回403会怎么样? 会被当成这个站没有robots.txt,也就是全部允许抓取。这次抓的211个域名里有21个返回403,是非200里最大的一群,成因基本都是边缘防护把请求判成了可疑流量。要注意的是4xx和5xx的缺省方向相反:4xx是“确定没有这个文件”,按全允许处理;429和5xx是“暂时问不到”,短期内会被当成全站禁止抓取。所以发布期间如果站点短暂返回5xx,抓取量可能好几天缓不过来,而这段时间任何监控都不会报警。 ## 文件返回200但内容是HTML,算不算问题? 算,而且比404更难发现。这次样本里有9个站是这种情况,大多是路由没为这个路径准备处理,请求落到了单页应用的兜底路由上。爬虫会尝试逐行解析,每行都不是合法指令,最后得到一份空规则集,效果等同于全部允许。检查只需要看两样:响应头里的 Content-Type 是不是 text/plain,正文第一行是不是以 User-agent 或 # 开头。建议把这两条写进上线检查项。 ## 怎么知道爬虫实际到达了什么,而不是我要求了什么? 看服务器访问日志或者CDN的请求记录,按UA和来源地址段分组统计。robots.txt记录的是你的要求,日志记录的是实际发生的事,两者对不上的部分才是需要处理的。验证爬虫身份要用反向DNS查询加正向确认,或者对照官方公布的地址段——UA字符串可以随便写,来源国家也会变,这两个都不能当依据。 ## 权威参考资料 ## 配送和退货承诺,63个站说给人听,11个说给机器听 - URL:https://zhangwenbao.com/shipping-return-promise-human-vs-machine-readable.html - 分类:技术SEO - 发布:2026-08-16 | 更新:2026-08-16 - 摘要:首页横幅上那句满75免邮、30天无理由退货,用户是照着它下单的。可搜索引擎、比价服务和生成式回答一个字都读不到,因为它是一张图,或者只是一行没被标记的文字。 - 关键词:结构化数据,配送与退货,转化数据,跨境合规 > **TLDR**:摘要:136个品牌站的首页里,63个对人做出了配送或退货承诺,占46.3%;而把同一份承诺写成机器能读的格式的,只有11个,占8.1%。只对人说的有56个,两边都说的只有7个。同一句话,说给人听和说给机器听,差了8倍——差的不是技术难度,是说出去之后要不要负责。 > 摘要:136个品牌站的首页里,63个对人做出了配送或退货承诺,占46.3%;而把同一份承诺写成机器能读的格式的,只有11个,占8.1%。只对人说的有56个,两边都说的只有7个。同一句话,说给人听和说给机器听,差了8倍——差的不是技术难度,是说出去之后要不要负责。 先从广告后台的一个数字说起。 你在网站上装了转化跟踪,用户下单之后回传一条记录给广告平台,里面有一个字段叫转化价值。你填200,平台就认为这一单值200美元,然后照着这个数去调整出价、分配预算、决定把广告投给谁。 问题是:平台没有任何办法当场核实这个200是不是真的。它看不到你的订单系统,不知道你的成本,也不知道这单最后有没有退货。它只能先信。 近期有一篇讨论广告账户里价值虚高的文章把这件事拆得很细,指出很多账户的转化价值早就和真实的生意脱节了——把含税价当净收入回传、把询盘按一个拍脑袋的估值折算、把退货率高的品类和低的品类混在一起用同一个系数。那篇关于广告账户价值虚高的排查文章 (https://www.searchenginejournal.com/the-ppc-clean-up-how-to-audit-and-fix-value-inflation-in-google-ads/583009/)里给的建议是做一次彻底的口径清理。 这类数字有一个共同特征:说的时候没人能验,但它一定会在未来某个时点被结果验证。而在被验证之前,它已经在影响真金白银的决策了。 网站上有没有同一类数字?有,而且比广告后台更多、更显眼、更少人当回事。这次把136个品牌独立站的首页拆开数了一遍,看的就是这一类。 ## 你告诉平台这一单值200美元,它只能先信 先把广告这边的机制说清楚,因为它是本文这条线索最干净的样本。 同期广告侧还有别的变动,砍掉五万美元门槛给中小投手的机会 (https://zhangwenbao.com/google-ads-lead-form-50k-threshold-removed.html)。 这个数最终要跟长期价值对上,用留存还原回报的五步财务模型 (https://zhangwenbao.com/dtc-ltv-calculation-cohort-roas-attribution.html)是配套算法。 ## 虚高是怎么一点点发生的 没有人一开始就打算虚报。它通常是这么长出来的。 归因数据平台不给你的那两层,今天就能自己测 (https://zhangwenbao.com/ai-attribution-referral-incrementality-influence.html)。 价值算错之外还有归因算错,多触点归因模型怎么选才不被最后一次点击骗走预算 (https://zhangwenbao.com/dtc-multi-touch-attribution-model-selection.html)。 第一步,装跟踪的时候图省事,把订单总额直接回传,含运费含税。这一步就已经比真实收入高了。 第二步,为了让不同渠道能比较,给非交易类转化也定一个价值。加购算20,注册算5,咨询算50。这些数字通常是拍出来的,而且定完就没人再改。 第三步,业务变了,数字没变。毛利率降了、退货率涨了、客单价结构变了,但那套两年前定的价值系数还在跑。 三步走完,回传的数字已经和真实的生意隔了一层。而整套自动出价系统就建立在这一层之上。 ## 平台为什么不去核 核不了。这是关键。 后台一片空白时怎么补,零点击时代的归因怎么做 (https://zhangwenbao.com/ai-search-attribution-zero-click-proxy-signals.html)。 另一类根本核不了的东西是内容来源,水印测出来也证明不了这段字是谁写的 (https://zhangwenbao.com/ai-watermark-detection-authorship-self-declared.html)。 你的订单在你的系统里,你的成本在你的账上,你的退货记录在你的售后工单里。这些数据平台一样都拿不到,除非你主动给它。而主动给的那一份,还是你自己填的。 这跟前面讨论过的那些字段不一样。页面是什么语言,平台读一遍就知道;页面用什么建的,看资源路径就能推断。但一笔订单值多少钱,答案不在任何它能观察到的地方。 所以这一类字段会一直存在,一直由你填,而且平台会一直采信。这不是它偷懒,是它没有别的选择。 ## 那它什么时候会发现 会发现,只是要等,而且发现的方式很间接。 延迟反馈是常态,收录、爬坡到起量的真实时间线 (https://zhangwenbao.com/how-long-does-seo-take-realistic-timeline.html)也是同一回事。 想知道钱花得值不值,增量测试怎么做才不让本来就会买的人冒领功劳 (https://zhangwenbao.com/incrementality-testing-marketing-measurement-guide.html)。 系统按你给的价值去优化,投出去的钱换回来一批转化。如果这批转化的真实价值和你报的不符,那么长期看,你的账户会呈现出一种矛盾状态:后台的回报率数字很漂亮,而你自己的账上不赚钱。 这个矛盾不会触发任何警报。平台不会说你报错了,它只会继续按你给的数优化,把预算越来越多地推向那些名义价值高、实际未必赚钱的方向。 所以真正的惩罚不是被平台发现,是被自己的财务报表发现。而那时候通常已经烧掉一个季度的预算了。 字段类型 | 平台能不能当场核 | 什么时候暴露 | 谁承担后果 | 页面语言 | 能,读内容 | 立刻 | 无所谓 | 建站平台声明 | 能,看痕迹 | 立刻 | 无所谓 | 转化价值 | 不能 | 几个月后看财报 | 你 | 配送与退货承诺 | 不能 | 用户下单之后 | 你 | 商品评分 | 很难 | 抽查或投诉时 | 你 | ## 还有一类数字虚高更隐蔽 除了金额本身,还有一类虚高藏在转化的定义里,更难被发现。 典型做法是把越来越多的动作算成转化:看了三十秒算一个、滚动到页面底部算一个、点了尺码表算一个。每一个单看都有道理,都能说出用户意图更强的理由。 问题是这些动作的数量级和真实成交完全不同。一天可能有几千次滚动到底,而成交只有几十单。当这两类混在同一个转化目标里时,系统会优先优化那个数量多的,因为它更容易做出成绩。 结果就是投放越来越擅长带来会滚动到底的人,而不是会付钱的人。后台的转化数一路上涨,收款账户毫无变化。 识别办法很简单:把转化目标列表打开,看每个目标的数量级差多少倍。如果最多的那个是最少的那个的一百倍,而它们被放在同一个优化目标里,那这个账户的优化方向基本已经被数量多的那个绑架了。 ## 顺带说一个更基础的问题 还有种情况比虚高更麻烦:同一笔订单被记了两次。 常见成因是转化代码同时装在页面和标签管理器里,或者感谢页刷新一次就再记一次。这类重复不会被任何校验拦住,因为每一次上报单看都是合法的。 查法也简单:拿广告后台的转化次数和订单系统的订单数比一下,如果前者明显多于后者,多半就是这个问题。 这一条要放在所有口径清理之前做。因为如果数量本身就是错的,后面校准金额毫无意义。顺序是:先确认数对不对,再确认金额对不对,最后才是统一口径。 ## 这跟前两类字段有什么不同 把三类自填字段放在一起,区别一眼就出来了。 被废掉的字段有完整脉络,旧的关键词公式为什么失效 (https://zhangwenbao.com/keyword-seo-strategy-evolution-2026.html)。 可被内容核验的那一类长什么样,236条地区声明背后只有6个真页面 (https://zhangwenbao.com/hreflang-region-code-declared-vs-real-pages.html)是个现成样本。 有些字段平台能自己读出来——这一页是什么语言、这个站用什么建的。这类你填不填、填得对不对,长期看都不重要,因为对方有独立的判断路径。 有些字段平台读不出来,也永远验证不了——比如这段文字到底是谁写的。这类会一直悬着,谁也说服不了谁。 而转化价值属于第三类,也是最微妙的一类:当场验证不了,但结果会验证。它不像第一类那样即时穿帮,也不像第二类那样永远无解,它有一个延迟的、必然到来的清算时刻。 这个延迟就是所有麻烦的来源。如果虚报能立刻被发现,没人会虚报;如果永远不会被发现,虚报也无所谓。偏偏是延迟几个月才被发现,才最容易让人在不知不觉中越走越偏。 ## 延迟带来的第二个问题 延迟不只让人放松警惕,它还破坏了归因。 变更记录最好做进固定模板,月报季报的模板与数据管线 (https://zhangwenbao.com/seo-monthly-report-template-data-pipeline-word-ppt.html)。 要在多变量里分清因果,六步实验设计 (https://zhangwenbao.com/backlink-attribution-experiment-design-rank-uplift.html)是最省事的办法。 假设你在三月调整了转化价值的口径,六月发现毛利率不对。这三个月里你还做了别的事:换了落地页、调了预算、上了新品、赶上了大促。到了六月复盘的时候,你很难说清是哪一件事造成的。 这就是为什么这类字段的正确处理方式不是“尽量填准”,而是“把口径固定下来并记录变更时间”。前者做不到——你永远不知道多准算准;后者做得到,而且一旦有了变更记录,事后归因就有了抓手。 这条建议适用于本文讨论的所有承诺型数值。免运费门槛什么时候改的、退货期什么时候延的、转化价值系数什么时候重定的,这三条时间线的价值,比这些数字本身准不准高得多。 ## 一个把口径搅乱的真实过程 保哥去年给一个做露营装备的独立站看账户,他们的问题就是典型的第三步。 品类差异要在选品阶段就想清楚,三角验证的90天框架 (https://zhangwenbao.com/dtc-product-research-3-triangulation-seo-amazon-review-small-budget-test.html)。 信号源不干净时自动化会放大问题,效果最大化六个月实战避坑 (https://zhangwenbao.com/dtc-google-pmax-real-world-pitfalls.html)记过一笔账。 那家店最早只卖帐篷和睡袋,客单价高、退货率低,回传订单总额基本没毛病。后来加了配件线——地钉、绳索、收纳袋,客单价二十几美元,退货率反而更高,因为尺寸不合的情况多。 可是转化跟踪从头到尾没改过,两条线用同一套回传逻辑。系统看到的是:配件线的转化数量多得多,于是把预算大量推向配件相关的词。后台数字一片大好,季度算账才发现整体毛利在掉。 修的办法不复杂,把两条线拆开、按净值回传,两周之后预算分配就回到正常。难的不是修,是发现——因为在被发现之前,所有仪表盘都是绿的。 这件事之后保哥养成一个习惯:接手任何账户,第一件事不是看回报率,是把回传的价值总和跟财务口径对一遍。两个数一对,问题在不在这一层,五分钟就有答案。 ## 网站上有没有同一类数字? 有,而且它们比广告后台的数字露脸得多——它们就印在首页最显眼的那条横幅上。 图片也在传递可信度,六类真实图与视觉信号 (https://zhangwenbao.com/b2b-image-authenticity-trust-6-types-real-photos-eeat-visual-signal.html)。 这些数字属于信任工程的一部分,让陌生买家敢下第一单的社会证明体系 (https://zhangwenbao.com/dtc-social-proof-system-reviews-ugc-trust-conversion.html)。 ## 承诺和描述是两回事 页面上的数字大致分两类。 描述要有人信得靠材料,客户案例研究怎么写才有人信 (https://zhangwenbao.com/customer-case-study-writing-guide.html)。 一句话要拿多少证据来撑,由措辞本身决定 (https://zhangwenbao.com/expert-endorsement-substantiation-by-claim-wording.html)。 一类是描述:这件衣服含棉95%,这个电池容量20000毫安时,这款鞋有12种颜色。这类数字描述的是已经存在的事实,理论上可以被检验——买一件回来测就知道。 另一类是承诺:满75美元免运费,30天无理由退货,100天试睡,终身质保。这类数字描述的不是现状,是你打算在未来做的事。 承诺型数字有三个特征,和广告后台那个转化价值一模一样。 第一,说出口的当下没人能验。你说30天可退,用户在下单那一刻没有任何办法确认这句话是真的。 第二,它一定会被结果验证。只要有一个用户真的在第29天申请退货,这句话就当场被检验了。 第三,验证的时点由对方决定,不由你。你不知道谁会在哪一天来试这句话。 ## 为什么这类数字值得单独拿出来量 因为它处在一个特别的位置:它既是营销文案,又是法律意义上的要约。 约定写得不完整就可能作废,仲裁条款少写一家机构的名字 (https://zhangwenbao.com/arbitration-clause-three-elements-institution-export-contract.html)。 承诺什么时候会失效,一旦出现不符点银行的付款承诺就不算数 (https://zhangwenbao.com/letter-of-credit-discrepancy-document-examination.html)是外贸里最经典的案例。 写在页面上的免运费门槛,用户是照着它下单的;写在页面上的退货天数,一旦短于当地法定期限就直接违规。这不是普通的宣传语,是有约束力的。 而与此同时,这类承诺在绝大多数站上都是由市场部写在图片里的一行字,既没有进系统,也没有人定期复核。这个反差本身就值得测一测。 ## 这些字通常是谁写的 还有一个角度很能解释后面那些数据:首页上这行承诺,写它的人和执行它的人往往不是同一批。 跟品牌岗协作的动作清单,品牌词防御到危机公关 (https://zhangwenbao.com/brand-manager-seo-collaboration-7-actions-keyword-eat-crisis-pr.html)。 跨岗位对账有现成清单,埋点归因看板的七个动作点 (https://zhangwenbao.com/data-analyst-seo-reconciliation-7-actions.html)。 写的人一般在市场部或者内容岗。他们的目标是提高转化率,而免运费和无理由退货是最有效的两个抓手,写上去立竿见影。 执行的人在运营和售后。他们要处理凑单到74块的用户问能不能通融,要处理第31天来申请退货的工单,要承担逆向物流的成本。 两拨人的考核指标不一样,中间也没有一道必须走的评审。于是首页上的承诺经常比系统里的规则更慷慨一点,这个差额平时没人算,出事的时候才发现。 这个组织事实解释了本文后面几乎所有的数据落差。把承诺写成机器可读,本质上需要市场部的一句话进到技术实现里,而这条路径在多数公司根本不存在。 ## 顺带说一句活动期的坑 承诺还有一个时间维度的麻烦:大促。 大促和日常是两套打法,八个维度的差异与监控体系 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)。 大促的时间表要提前排,从T减8到T加4的路线图 (https://zhangwenbao.com/maximize-seo-traffic-conversion-during-promotion.html)。 大促期间免运费门槛会临时下调,退货期会临时延长,这些都是常规操作。麻烦在于活动结束之后,页面上那行字改回来了,但别的地方未必。 常见的遗留有三处:邮件模板里还写着活动门槛、帮助中心的常见问题还是活动版本、结构化数据里的值没跟着改。前两处用户看得见会来问,第三处没人看得见,会一直错下去。 这也是后面讲“会变的东西要么动态生成要么别写”那条建议的来历。一个每年要改四次的数字,写死在模板里迟早出事。 ## 136个首页上,有多少在做承诺? 用的还是那批品牌独立站的首页快照,原始187份,按“字节数超过一万且确实是完整HTML文档”筛下来剩136份,下面所有比例的分母都是这个数。 这属于技术侧体检的一部分,AI时代电商技术SEO的五个新层 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)。 配送信息不只是承诺,配送政策页怎么写才能既降弃购又接住搜索流量 (https://zhangwenbao.com/dtc-shipping-policy-page-seo-delivery-time-cost-transparency-conversion.html)。 ## 怎么量的 两步。第一步,把页面上人能读到的文字提出来——去掉脚本和样式,只留正文,然后用一组模式去匹配承诺类表述:免运费、免退货、多少天退货、多少天试用、多少天送达、多少年质保、终身质保、满意保证,以及各种语言的对应说法。 另一类样本在日志里,读懂抓取行为与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)。 抽样比全量划算得多,按页面模板抽样把百天审计压到半天 (https://zhangwenbao.com/ecommerce-seo-audit-template-level-sampling.html)。 第二步,看同一个页面的机器可读部分里,有没有对应的结构化字段——配送详情、退货政策、退货天数、免运费门槛、处理时长、运输时长这一类。 两步的结果放在一起,就能回答本文最想问的那个问题:同一句承诺,有多少人只说给人听,有多少人也说给机器听。 ## 这个量法的边界,先说清楚 三处要说明,不然数字容易被读过头。 让工具替你审计有三个前提,数据、方法与人工复核 (https://zhangwenbao.com/ai-seo-geo-audit-agent-pitfalls.html)缺一不可。 不设对照会高估,量出74%的差异补上对照之后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)。 第一,只看了首页。很多站把配送退货信息放在商品页或结算页,那里的覆盖率大概率更高。所以46.3% 这个数只代表“愿意把承诺摆到门面上”的比例,不代表这些站有没有这些政策。 第二,做成图片的看不见。前面说过,促销横幅常常是整张图,文字烧在像素里。这类会被统计成“没有承诺”,导致真实比例被低估。 第三,语言覆盖有限。匹配模式主要覆盖英语,外加德语、法语、西班牙语、荷兰语的常见说法。非拉丁文字的承诺表述基本抓不到,好在这批样本以英语站为主,影响有限。 这三条都会让文本承诺的比例偏低,而结构化数据那一侧的统计是精确的——字段名就那么几个,搜一遍就有。所以真实的落差只会比8倍更大,不会更小。这一点对本文的结论是有利的,但正因为有利,更要说清楚。 ## 结果:46.3% 的站在首页做了承诺 136个站里,63个在首页上出现了明确的承诺类表述,占46.3%。 承诺只是信任的一层,独立站信任的七层落地 (https://zhangwenbao.com/dtc-ecommerce-trust-7tier-eeat-mechanism.html)。 退换货这一页值得单独做,既做下单前的信任背书又拿售后搜索流量 (https://zhangwenbao.com/dtc-return-refund-policy-page-seo-trust-conversion-design.html)。 按类型拆开是这样的。 承诺类型 | 站数 | 占有承诺的站 | 免费配送或免费退货 | 48 | 76.2% | 免运费门槛金额 | 42 | 66.7% | 具体退货天数 | 9 | 14.3% | 试用期天数 | 7 | 11.1% | 终身质保 | 7 | 11.1% | 配送时效天数 | 6 | 9.5% | 质保年限 | 3 | 4.8% | 满意保证 | 1 | 1.6% | 分布很清楚:免运费是绝对主力,四分之三的站在说这件事。而具体到天数的承诺——多少天退、多少天到——反而少得多。 这个差别有意思。免运费是一个状态承诺,容易兑现也容易验证;退货天数是一个时间承诺,它把责任延续到未来一个月甚至一年。越是把自己绑得久的承诺,愿意写在首页的人越少。 ## 那69个什么都不承诺的站是什么情况 136减63还剩73,其中69个首页上找不到任何承诺表述。这批站值得单独看一眼,因为比例不低。 首页文字太少还有别的代价,模板与广告的七大稀释陷阱 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)。 首页没有可读文字的站不少,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)。 翻了翻,大致三类。 第一类是把承诺放在了别处。首页只做品牌形象,配送退货信息全在商品页和帮助中心。这类站通常品牌调性偏高端,不愿意在门面上摆促销信息。 第二类是首页几乎没有文字。整屏视频或大图,文案总共十几个词。这类站不是不承诺,是首页承载不了任何信息。 第三类是承诺做成了图片。那条“满75免邮”的横幅是一张图,文字烧在像素里。人看得见,抽取文本的脚本看不见,机器也看不见。 第三类的数量没法精确统计——正因为看不见——但从抽样看不算少。这一类在本文的口径下会被记成“没有承诺”,实际上他们只是把承诺说在了一个所有机器都读不到的地方。这个偏差要说明,它会让46.3% 这个数字偏低。 ## 把承诺做成图片,代价比想象中大 顺着说一句这件事。把促销信息做成图片,好处是设计自由、改起来只要换图。代价是三条: 图片该用在能发挥价值的地方,原创配图怎么把自然流量拉高一倍 (https://zhangwenbao.com/original-visuals-organic-traffic-seo.html)。 页面到底给出了什么,拿样本页跑一遍语义化HTML就知道 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)。 搜索引擎读不到,这条信息对排名和展示零贡献;屏幕阅读器读不到,有无障碍要求的市场会有合规风险;生成式回答读不到,用户问“他家满多少免邮”,模型答不上来。 解法很简单也很老套:图片只放背景和装饰,文字用真实文本叠上去。这在今天的前端实现里没有任何技术障碍,只是需要设计和开发之间有个约定。 ## 免运费为什么成了首选承诺 四分之三的站都在说免运费,这个压倒性的比例值得多想一层。 免运费也常被当成弹窗诱饵,弹窗怎么设计才不招人烦 (https://zhangwenbao.com/email-popup-lead-capture-opt-in-conversion-guide.html)。 运费只是弃购成因之一,结账页放弃率超七成的九个真实成因 (https://zhangwenbao.com/dtc-checkout-abandonment-9-real-causes.html)。 直接原因当然是运费对转化的杀伤力大。购物车放弃的原因调查里,意外的运费常年排在第一位,比价格高、比流程复杂都更致命。用户不是不愿意付这个钱,是不愿意在最后一步被加价。 但更深一层的原因是:免运费是所有承诺里最容易兑现的一个。 它不需要你改变任何流程,不需要多雇人,不需要建新系统。你只要把运费成本摊进商品定价或者接受一点毛利损失,这个承诺就百分之百做得到,不存在做不到的风险。 对比一下其他承诺:配送时效要仓库和承运商配合,退货要售后流程支撑,质保要备件和维修能力。只有免运费是纯财务决策,签个字就能落地。 所以它成为首选一点都不奇怪。人总是先做那件承诺成本最低、兑现风险最小的事,这在个人和公司层面都一样。 ## 门槛这件事的另一面 不过免运费很少是无条件的,四分之三说免运费的站里,三分之二同时设了门槛。 客单价怎么系统性提上去,八模块90天实战 (https://zhangwenbao.com/high-conversion-ecommerce-cro-seo-90day-playbook.html)。 退货成本能从源头压,从尺码、产品图到物流的减少退货预防体系 (https://zhangwenbao.com/cross-border-ecommerce-reduce-return-rate-prevention.html)。 门槛的作用是双向的:对用户是一个凑单激励,对商家是一道成本闸。设了门槛,低客单价订单就不用补贴运费,而这批订单恰恰是最不赚钱的。 但门槛也带来一个副作用,很多人没算过:它会制造一批凑单退货。用户为了达到75块的门槛多买一件不太需要的东西,收到后把那件退掉。结果是你既付了往返运费,又损失了一次逆向物流成本。 这个现象在门槛设得远高于平均客单价的站上尤其明显。判断办法也简单:看那些刚好卡在门槛线上方一点点的订单,它们的退货率是不是显著高于整体。如果是,那门槛可能设高了。 ## 那些承诺里的数字,为什么长得都一样? 把所有承诺里的具体数值抽出来看,会发现一件比覆盖率更有意思的事:这些数字高度集中在少数几个取值上。 另一套数字体系是会员权益,积分、分层与复购飞轮的完整设计 (https://zhangwenbao.com/dtc-loyalty-program-points-tiers-membership-retention-system.html)。 定价本身也是这类决策,从成本加成到价值定价的决策框架 (https://zhangwenbao.com/dtc-pricing-strategy-cost-plus-value-based-framework.html)。 ## 免运费门槛:99是中位数 一共抽到69个免运费门槛金额,最小20,最大1000,中位数是99。 金额之外还有支付方式,德国巴西东南亚的买家怎么才肯付款 (https://zhangwenbao.com/dtc-local-payment-methods-multi-gateway-conversion.html)。 多市场的金额展示另有讲究,把跨境价格排得像本地店 (https://zhangwenbao.com/currency-formatter-cross-border-price-localization-schema-guide.html)。 高频取值依次是:75出现10次、100出现8次、50出现7次、99出现6次、150出现5次、200出现4次、49和55各3次。 把这串数字读一遍就能看出两种定价心理在打架。50、75、100、150、200是整数派,图的是清晰好记;49、55、99是心理定价派,图的是显得低一点。 有意思的是整数派明显占优。这跟商品定价的习惯正好相反——商品价格里99结尾满地都是,而免运费门槛更多用整数。 原因大概是这两个数字的作用不同:商品价格是要让你觉得便宜,免运费门槛是要让你算得清还差多少。让人心算的数字,整数更好使。 ## 退货天数:30天几乎是唯一答案 抽到10个明确的退货天数,其中 30天出现7次,365天2次,90天1次。 责任的时间边界怎么划,仓至仓条款只划范围,赔不赔看出险那刻 (https://zhangwenbao.com/insurable-interest-warehouse-to-warehouse-cargo-policy.html)。 退款争议要有流程兜底,三个渠道的争议处理SOP (https://zhangwenbao.com/dtc-refund-chargeback-3-channel-sop-paypal-stripe-platform.html)。 30天成为事实标准这件事,背后有个不太被提的原因:它是各地法定最低期限的安全上方。欧盟的消费者权利指令给的冷静期是14天,各国实践中普遍更长;写30天,在几乎所有主要市场都不会踩线,同时又比法定下限显得慷慨。 写365天的那两家属于另一种策略:把退货期拉到一年,用极高的确定性换取下单时的犹豫消除。这种做法只在退货率天然很低的品类里划算。 ## 试用期:100天是个行业密码 抽到12个试用期数值,100天出现9次,120天2次,30天1次。 行业惯例之外还有别的杠杆,被低估的九个反直觉设计 (https://zhangwenbao.com/counterintuitive-ui-design-conversion-levers.html)。 客单价越高越靠信任,内容和信任才是胜负手 (https://zhangwenbao.com/high-ticket-dtc-content-trust-geo-strategy.html)。 100这个数字几乎全部来自床垫和睡眠用品品类。它的来历是行业里一个早年的营销共识:让用户完整经历一个季节的睡眠周期,同时用一个三位数造成心理上的宽裕感。 这个数字的传播过程很典型——一家先做,同行跟进,几年之后它就变成了这个品类的入场门槛。没有任何标准规定床垫要试睡100天,但今天不写100天的床垫品牌会显得不专业。 ## 配送时效:出现得最少,也最含糊 只抽到7个配送天数,其中30天出现5次。 时效之外还有可达性,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)。 时效术语本身就容易混,ETD和ETA的九大差异与实操场景 (https://zhangwenbao.com/etd-eta.html)。 30天的配送承诺显然不是“三十天才送到”,而是类似“三十天内发货”或者某种最长时限的兜底表述。这恰恰说明了问题:配送时效是所有承诺里最难写的一个,因为它取决于仓库、承运商、目的地和季节,而这四样你都控制不了全部。 所以多数品牌选择在首页只说免运费,不说几天到。把可控的承诺说满,把不可控的承诺藏进详情页,这是一个非常一致的集体选择。 ## 质保这一栏为什么这么少人写 质保是本次数据里覆盖率最低的一类:只有3个站写了具体年限,7个站写了终身质保。 年限具体的比终身的还少,这个倒挂很有意思。按常理,承诺终身应该比承诺两年更重,愿意写的人应该更少才对。 解释大概是:“终身”是个模糊词,而“两年”是个精确数。模糊词的解释空间在你手上——终身指产品的合理使用寿命还是购买者的一生,条款里可以慢慢定义;而写了两年,就是两年,第25个月来的用户你没得商量。 这跟前面讲的规律是一致的:越精确的承诺越难写,因为精确意味着没有解释余地。模糊承诺看着更慷慨,实际约束力更弱,这是所有营销文案的通用技巧,也是消费者保护法规一直在盯的地方。 对做出海的团队,这里有个实际建议:如果你的产品质量真的过硬,写具体年限比写终身更有说服力,因为用户对模糊的大词已经免疫了。而且具体年限可以写进机器可读的字段,模糊表述写不进去。 ## 满意保证为什么只有1个站写 最极端的是满意保证,136个站里只有1个。 这个承诺的问题在于它把判定权交给了用户。退货有期限、质保有范围,而“不满意就退”没有任何客观标准,全凭对方一句话。 在早期的电商竞争里这曾经是个常见卖点,现在几乎绝迹,原因是行业已经算过这笔账:无条件承诺带来的转化提升,抵不过它在极端用户身上产生的成本。 剩下那1个站还在写,可能是品类特殊,也可能只是文案没更新。但从数据看,这个承诺已经退出主流了——这也是一个自填字段被市场自然淘汰的例子,没有任何规则禁止它,只是没人再愿意承担它。 ## 数字趋同的好处和代价 这些数字如此集中,对行业其实是好事:用户不需要每家都算一遍,看到30天就知道是标准配置。标准化降低了整个市场的决策成本。 区分度这件事在流量结构上也成立,品牌词与非品牌词怎么读 (https://zhangwenbao.com/branded-vs-nonbranded-keyword-traffic-structure-strategy.html)。 同质化里怎么突围,微创新、人群细分与捆绑组合 (https://zhangwenbao.com/dtc-red-ocean-niche-product-differentiation-positioning-bundling.html)。 代价是这些数字失去了差异化能力。当所有人都写30天时,写30天不再是优势,只是没有劣势。它从一个卖点退化成了一张入场券。 这跟前面提到的评分区间是同一个道理。当一个指标被普遍采纳到某个水平,它就不再传递信息,只传递“我没落后”。 想在这一层做出差异,只有两条路:要么显著超出标准(365天退货、终身质保),要么把标准做得更具体(不是“快速配送”,而是“下午三点前下单当天发出”)。第二条路成本低得多,但要求你真的能做到。 ## 怎么定自己的那个数 给个可操作的思路,三步。 不同客群给不同数,分组定价与税务类别实战 (https://zhangwenbao.com/magento-2-customer-groups-segmentation-group-pricing-tax-class-operations.html)。 促销规则要配得住,目录与购物车价格规则的运营实战 (https://zhangwenbao.com/magento-2-catalog-cart-price-rules-coupon-promotion-engine-operations.html)。 第一步,查法定下限。你的主要市场的强制退货期是多少,这是地板,不能碰。 第二步,算成本弹性。把退货期从14天延长到30天,退货率会涨多少?这个数在自己的历史数据里能估出来——看现有退货申请的时间分布,多数集中在收货后一周内,超过两周的很少。如果你的退货申请九成发生在14天内,那把期限延到30天几乎不增加成本,却能明显提升下单信心。 第三步,看竞品的水位。不是为了跟随,是为了知道自己写多少会被视为落后。低于品类中位数会显得不专业,高出太多则要算清楚成本。 免运费门槛的算法类似:设在平均客单价的1.2到1.5倍之间,才能起到拉高客单的作用。设得太低等于白送运费,设得太高用户根本不去凑。 ## 同一个承诺,说给机器听的有几个? 这是本次测量的核心问题,答案的落差比预想的大。 结构长什么样,图谱节点与知识面板怎么搭 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)讲过。 哪些类型真有人用,官方第一次公开的全网使用数据 (https://zhangwenbao.com/schema-org-usage-statistics-priority-guide.html)给了底表。 ## 63对11 136个站里,首页出现承诺文本的有63个;而在机器可读的结构化数据里出现配送或退货相关字段的,只有11个,占8.1%。 写之前先校验,一个尾逗号就能让整页结构化数据失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)。 要自查,结构化数据审计工具 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)一次能扒清页面里的五种格式。 交叉起来看更清楚。 情形 | 站数 | 说明 | 只对人说 | 56 | 首页写着,机器读不到 | 对人说也对机器说 | 7 | 唯一算完整的情况 | 只对机器说 | 4 | 数据里有,首页没写 | 两边都没说 | 69 | 首页不承诺任何东西 | 56比7,正好8倍。每有8个站把承诺印在首页,只有1个站愿意把同一句话写成机器可读的格式。 ## 换个算法,落差还会更大 8倍这个数字其实是保守估计,因为分子分母的口径并不完全对等。 数出来的东西受工具限制,后台数据的三大黑洞怎么补 (https://zhangwenbao.com/gsc-data-hidden-limits-1000-row-url-bucket-threshold-workaround-engineering.html)。 口径不同结论就不同,收录数据到底信site命令还是信后台 (https://zhangwenbao.com/site-search-operator-vs-gsc-coverage-accuracy-decision.html)做过三源校准。 分母那63个是首页上出现承诺文本的站。前面说过,做成图片的承诺抓不到,所以真实做承诺的站只会更多。 分子那11个是结构化数据里出现相关字段的站,这个统计是精确的,字段名就那么几个,搜一遍不会漏。 如果按更严格的口径——只算那些真的写全了关键值的站——分子还会更小。比如免运费门槛,首页写了的有42个,写进结构化数据的只有4个,这一项的落差是10.5倍。 再严格一点,看有多少站的两份声明是数值一致的,那就得逐个核对,本次没做。但按经验推断,一致率不会太高——因为其中相当一部分结构化数据是平台默认生成的,未必跟市场部写的那行字对得上。 ## 这个落差在别的字段上有没有 顺手对比了一下同一批站的其他结构化数据覆盖率,落差是这一项独有的。 身份信息汇总在哪儿,实体主页这块地基怎么搭 (https://zhangwenbao.com/entity-home-seo-ai-brand-guide-html.html)。 纯描述性的字段反而填得全,关于我们页面怎么写才被认成可信实体 (https://zhangwenbao.com/about-us-page-entity-eeat-ai-search-guide.html)。 组织身份信息,六成的站写了;站内搜索入口,一半以上写了;面包屑导航,也有相当比例。这些都是纯描述性的字段,写了没有任何履约责任。 而配送退货这一项,掉到8.1%。同一批站,同样的技术能力,同样的模板体系,唯独在这一类字段上集体缺席。 这个对照基本排除了技术原因和意识原因。剩下的解释只能是那一句:这一类写进去,是要负责的。 ## 具体字段的分布更说明问题 那11个站用到的字段,出现次数是这样的:免运费门槛4次、退货方式4次,退货政策、退货天数、退货费用、适用国家、运费各3次,处理时长、运输时长、配送时间各2次,配送详情、配送条件、配送时效各1次。 商品标识是另一类必须由你提供的事实,商品编码怎么设置才利于SEO (https://zhangwenbao.com/product-gtin-seo.html)。 商品数据的字段还在加,页面标记和数据源的分类终于对上了 (https://zhangwenbao.com/merchant-listing-category-property-google-product-taxonomy.html)。 总量少到可以逐个数出来。整整136个站,把免运费门槛写成机器可读的只有4个。而首页上写着免运费门槛的有42个。 10比1的差距,比总体的8倍还要悬殊。原因不难猜:免运费门槛这一栏一旦写进去,就成了一个可以被拿去比对的具体数值。 ## 为什么不写 把可能的原因排一遍,能排除掉大部分。 责任边界在哪,合规边界与决策红线 (https://zhangwenbao.com/black-hat-white-hat-gray-hat-seo-comparison-risk-decision-line.html)划得比较清楚。 涉及责任的事要跟法务对齐,法务与SEO协作的七个动作点 (https://zhangwenbao.com/legal-counsel-seo-collaboration-7-actions-privacy-trademark-incident.html)。 不是不知道有这个东西。这批站里绝大多数都有完整的结构化数据,组织信息、面包屑、站内搜索都标了,说明技术上完全做得到。 不是没有收益。把配送和退货信息写成机器可读的,在购物结果里可以展示配送时间和退货政策,这是明确的展示位收益。 也不是嫌麻烦。比这复杂的标记他们都做了。 剩下的解释只有一个:写进去要负责。印在首页横幅上的一行字,说到底是营销话术,出了问题可以解释成“那是活动期间的说法”;而写进机器可读的字段里,它就变成了一条结构化的、可被系统读取和比对的声明。 两者的法律效力其实差不多,但心理上的责任感完全不同。前者像广告,后者像申报。 ## 只对机器说的那4个站,反而更值得看 数据里有个小群体容易被忽略:4个站在结构化数据里写了配送或退货信息,首页上却没有对应的承诺文本。 插件默认值该逐项过一遍,一个出海独立站的设置清单 (https://zhangwenbao.com/rank-math-best-seo-settings.html)。 插件自动生成的东西经常没人知道,两套结构化数据怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)。 这个组合乍看奇怪——为什么要把话说给机器听,却不说给人听? 合理的解释有两个。一是这些字段由建站平台或插件自动生成,人根本没参与,系统按订单设置自动输出了一份。二是承诺信息放在了商品页而不是首页,而结构化数据是全站模板级的,所以首页也带上了。 第一种解释更常见,它引出一个重要提醒:你的站可能已经在对机器做出承诺了,而你不知道。 如果平台的默认配置输出了一个免运费门槛,而你的实际活动规则早就变了,那么这条声明就是错的,且没有任何人会告诉你。值得花十分钟检查一遍:自己站上的结构化数据里,到底有没有配送和退货字段,值是多少。 ## 怎么十分钟查完 不用工具,三步。 想一次查完更多项,可索引性一键体检 (https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html)能把原因列清。 看不懂那段数据,把结构化数据调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)里有顺手的工具。 第一步,打开首页和一个商品页的源码,搜索标记类型的关键词,看有没有配送详情、退货政策这类节点。 第二步,如果有,把里面的数值抄出来:免运费门槛多少、退货多少天、处理时长几天、适用哪些国家。 第三步,拿这几个数去结算流程里实测一遍。凑单到门槛下面一块钱看看收不收运费,去帮助中心看看退货期写的是多少天。 三步对完,要么确认一致可以放心,要么发现不一致——而后者的价值更大,因为那是一条正在生效的错误声明。这个检查在多数团队里从来没人做过,恰恰因为它跨了市场部和技术两边。 ## 对机器说,和对人说,差别到底在哪? 上面那句“写进去要负责”值得展开,因为它是这一整篇的关键。 还有一层声明藏在响应头里,X-Robots、缓存与Vary的实战机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)。 机器可读这件事还有别的场景,接口和订阅源拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)。 ## 谁在核这份数据 写成机器可读之后,这份承诺会进入几条完全不同的链路。 购物结果的入口在变,图片搜索开始混入购物广告 (https://zhangwenbao.com/google-image-search-shopping-ads-organic-traffic.html)。 商品数据的入口不止广告,不投广告也能让商品免费上购物结果 (https://zhangwenbao.com/google-free-product-listings-merchant-center.html)。 搜索平台会用它做展示。购物结果里那些“免费配送”“30天退货”的标签,来源就是这类数据。而平台对展示出去的信息是有责任的,所以它会核。 比价与聚合服务会用它做筛选。用户按“支持免费退货”筛一遍,你在不在结果里,取决于这份数据。 生成式回答会用它组织答案。用户问“这家支持多少天退货”,模型从哪里取答案?从它能读到的地方,而不是从你首页的图片里。 三条链路的共同点是:它们都不看图片上的那行字。你把承诺做成一张精美的横幅,这三条链路一个字都读不到。 ## 核不上会怎样 平台核的方式很朴素:拿你声明的和实际能观察到的比。 被取消资格的另一种形态,站点声誉滥用与三方防御 (https://zhangwenbao.com/site-reputation-abuse-parasite-seo-2024-defense.html)。 评测类内容被整顿的那一轮,80个联盟站到底谁活下来了 (https://zhangwenbao.com/google-product-reviews-update-mechanism-affiliate-site-survival.html)。 如果你声明免运费门槛是75,而抽查发现结账时80块也要收运费,那么轻则这条信息不再展示,重则整个站的商品数据资格受影响。 这套机制的严格程度在电商侧一直在提高。商品数据这条线上的变更相当频繁,从类目属性到配送信息,平台一年要动好几次;连代理商能关联多少个账户这种细节也在持续调整 (https://www.seroundtable.com/google-merchant-center-for-agencies-1000-accounts-41870.html),说明这条链路上的规则还在快速演进。 所以真实的取舍是这样的:不写,你损失的是展示机会;写了但做不到,你损失的是资格。而多数团队选择了前者——不是算过账,是根本没意识到有这个选择。 ## 写了之后,改起来反而更麻烦 还有一个现实顾虑,做过的人才知道:写成机器可读之后,改动的成本变高了。 能自动化的就别靠人记,用cron把备份、站点地图与日志一条龙 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)。 改版时这类字段最容易掉,改版不掉SEO的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)。 页面上那行字,市场部自己就能改,改完立刻生效。而结构化数据里的值通常在模板或数据源里,改动要走技术流程,可能还要等发版。 于是就出现一种很典型的拖延:大促要临时调门槛,页面改了,结构化数据那份留到“下次一起改”,然后就一直没改。三个月后,页面写着50,机器读到的还是75。 这个问题的解法前面提过——统一数据源。但在那之前,有个更简单的临时办法:只把不会变的部分写成机器可读。退货天数一年不改一次,写;免运费门槛一年改四次,先不写,等改造完再补。 宁可少写几个字段,也别留一个会过期的值。因为一个错的声明比没有声明更糟——没有声明只是缺席,错的声明是在提供假信息。 ## 法定下限是另一条硬线 还有一层很多人没注意:承诺的下限不是你定的。 欧洲市场还有别的强制项,同意管理平台怎么选 (https://zhangwenbao.com/cmp-consent-management-platform-selection-cross-border.html)。 合规要求怎么落到架构上,同意横幅怎么配才不影响SEO数据 (https://zhangwenbao.com/seo-legal-compliance-gdpr-ccpa-consent-mode-cross-border-architecture.html)。 欧盟的消费者权利指令给远程购物设定了法定冷静期,这是硬性的,你写多少天都不能低于它。那份指令的正式文本 (https://eur-lex.europa.eu/eli/dir/2011/83/oj)里对期限起算点、退款时限、消费者告知义务都有明确规定。 这意味着做欧洲市场的站,退货天数这一栏其实没有太多自由度——你只能往上加,不能往下减。而如果页面上写的天数低于法定值,那不只是营销问题。 这也解释了为什么30天成了事实标准:它在所有主要市场都稳稳站在法定线之上,同时不至于让自己承担太久的责任。这是一个被法规和成本共同挤出来的数字。 ## 一个常被问到的顾虑:会不会被竞品抄 推动这件事时经常遇到一个反对意见:把配送和退货条件写成结构化数据,等于把自己的政策明码标价挂出去,竞品一抓就知道。 这个顾虑基本不成立,理由有三。 第一,这些信息本来就是公开的。它印在你首页最大的那条横幅上,任何人打开网站就能看到。写成机器可读只是换了个存放位置,没有增加任何暴露。 第二,竞品要抓早就抓了。真正在做竞品监控的团队,抓的是页面文本和结账流程,不会因为你没写结构化数据就抓不到。反倒是那些不做监控的对手,本来也不会来看。 第三,也是最实际的,配送和退货政策不是护城河。它是可以被立刻复制的东西——对方看到你写30天,明天就能改成30天。真正难复制的是履约能力,而那个东西写不进任何字段里。 所以这个顾虑的真实成分,可能是对暴露本身的不适感,而不是对竞争的担忧。而这种不适感,恰恰是前面说的“写进去要负责”的另一种表述。 ## 还有一个顾虑是怕被绑死 第二个常见反对意见更有道理一些:写成结构化数据之后,改起来要走技术流程,业务上少了灵活性。 这个顾虑是真的,前面也承认了。但解法不是不写,而是分清哪些是硬规则、哪些是可变策略。 硬规则是那些一年不动一次的:退货天数、退货费用由谁承担、适用国家。这些写死没有任何问题,因为它们本来就不该经常变。 可变策略是那些跟着活动走的:免运费门槛、限时的延长退货期。这些要么做成从配置读取,要么就不写。 把两类分开之后,会发现真正需要频繁改动的字段其实很少。多数人以为自己需要灵活性,实际上只是没把稳定的部分和易变的部分分开过。 ## 三条链路读到的东西差别有多大 把同一个页面在三种读法下呈现的信息量摆出来,落差会更直观。 框架选错会抓成空壳,渲染模式该怎么选 (https://zhangwenbao.com/react-nextjs-framework-seo-rendering.html)。 读不读得到还取决于渲染方式,三种渲染模式的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)。 读法 | 能读到首页横幅图片上的字吗 | 能读到正文文本吗 | 能读到结构化字段吗 | 人用眼睛看 | 能 | 能 | 看不见也不需要 | 搜索引擎抓取 | 不能 | 能 | 能,且优先采信 | 购物与比价服务 | 不能 | 基本不用 | 只用这一份 | 生成式回答 | 不能 | 能 | 能,且更省事 | 这张表里最刺眼的是第一列:除了人,没有任何一方能读到图片上的字。而恰恰是最重要的促销信息,最常被做成图片。 第二刺眼的是购物与比价那一行。这类服务几乎完全依赖结构化数据,因为它要做的是跨站比较,必须拿到同一格式的字段。你不提供,它就不是把你排后面,而是根本没法把你纳入比较。 ## 那生成式回答呢 这一条现在变数最大,也最值得提前布置。 连地址写法都会影响引用,四家模型对照的五条原则 (https://zhangwenbao.com/url-structures-ai-retrieval-llm-citation.html)。 它按块检索而不是按页,内容分块优化该怎么做 (https://zhangwenbao.com/chunk-optimization-ai-rag-retrieval-geo.html)。 当用户直接问“这家支持几天退货”时,回答的来源有三种可能:从结构化字段里取(最准)、从正文文本里读(次准)、或者干脆答不上来。 三种情况里,第二种最危险。因为正文里关于退货的表述往往不止一处——首页横幅一处、帮助中心一处、条款页一处,三处的措辞和天数可能都不一样。模型读到哪一处,取决于它抓到了哪一页。 结果就是同一个问题,不同时候可能得到不同答案,而这些答案全都“出自你的官网”。这是自填字段不一致最典型的代价:你没有说谎,但你说了三个版本。 研究显示模型在真正去检索之前,往往已经形成了倾向性,关于模型在检索前就已经有了推荐倾向这件事 (https://www.searchenginejournal.com/chatgpt-already-knows-who-itll-recommend-before-it-searches/585162/)有过专门的分析。这意味着你能影响的窗口比想象中窄,能做的就是把可读的那一份写清楚、写一致。 ## 换个思路:把承诺当成产品的一部分 讨论到这里,有个视角可以换一下。前面一直把承诺当成营销话术在分析,但对用户来说,承诺本身就是产品的一部分。 买一张床垫,你买的不只是那块海绵,还包括“睡不惯可以退”这个选项。这个选项有实实在在的价值——它把决策风险从买方转移到了卖方,而风险转移是有价格的。 这个视角一换,很多事情的算法就变了。试用期不是成本,是定价的一部分;免运费门槛不是补贴,是一个附加条件的产品包。 更实际的推论是:承诺应该像产品一样被设计、被测试、被迭代。可现实中,商品会做A/B测试,价格会做弹性测试,承诺条款几乎从来没人测过——定下来就一直用,改一次要惊动好几个部门。 值得试的最小实验是:拿两组流量,一组看到30天退货,一组看到60天,比转化率和退货率的净效果。这个实验成本不高,结论却能直接换算成钱。 ## 为什么很少有人测 三个障碍,都不是技术上的。 第一,改承诺要过法务。而法务的默认倾向是维持现状,因为改动带来的风险归他,收益归业务。 第二,退货成本的账在另一个部门。做转化的人看到转化率涨了就算赢,逆向物流的成本落在运营那边,两边的账没有并表。 第三,效果要等。转化率的变化几天就看得出来,退货率的变化要等一个完整的退货周期,也就是至少一个月。而多数实验没耐心等这么久,往往在只看到好消息的时候就下了结论。 这三条加起来,就是为什么这个杠杆一直没人拉。它需要跨部门的账、需要耐心、还需要有人愿意承担改动的风险。但也正因为没人做,它至今仍是一个真空地带。 ## 评价数据也是同一个形态吗? 是,而且落差更大。顺手量了一下这批站的评价体系,结果很能说明问题。 问答标记也是同一套逻辑,博客问答结构化数据的八步实战 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)。 评论这块的完整打法,评论结构化数据加GEO联动优化 (https://zhangwenbao.com/ecommerce-product-reviews-seo-guide.html)。 ## 42.6% 装了,1.5% 让机器读得到 136个站里,页面上能看到第三方评价系统痕迹的有 58个,占42.6%。这些系统会在商品页展示星级和用户评论,是电商站的标配。 聚合方式影响可读性,结构化数据怎么接入智能体网络 (https://zhangwenbao.com/yoast-schema-aggregation-agentic-web-seo.html)。 具体怎么接,给评论加上星级结构化数据 (https://zhangwenbao.com/shopify-ryviu-review-structured-data-guide.html)有一份逐步操作。 而把评分写进机器可读的结构化数据的,只有2个站,占1.5%。 两个数一比,差了28倍。 装了评价系统的站,手里是有评分数据的——4.8分、6700条评价,这些数字就显示在页面上。但让机器读得到的,只有两家。 ## 为什么装了却不写 这里的原因和承诺那一层略有不同,有技术因素也有责任因素。 平台侧的完整配置顺序,产品页、分类页与技术栈一次配齐 (https://zhangwenbao.com/woocommerce-seo-12-step-roadmap.html)。 评论系统怎么配才既真实又出星标,审核与防刷的完整运营 (https://zhangwenbao.com/woocommerce-product-reviews-verified-owner-moderation-spam-rating-schema-operations.html)。 技术因素是:评价内容通常由第三方系统异步加载。星级和评论在页面打开后才从评价服务商那里取回来,静态的页面源码里没有。要写进结构化数据,得让评价系统把数据同时输出一份到页面里,这需要额外配置。 责任因素是:自填评分曾经被大规模滥用。行业里有过一段时期,商家给自己的商品标一个漂亮的分数和一个虚构的评价数,只为在搜索结果里挂上星星。平台后来收紧了规则,对自我声明的评分展示做了限制。 两个因素叠加,导致一个荒诞的局面:真有评价数据的站不写,而当年愿意乱写的站已经被规则挡住了。最后是一片空白。 ## 顺带说说那两家写了的 那两个站的评分分别是4.9分6700条评价,和4.8分7404条评价。 编出来的数字和链接一样要防,幻觉引用怎么查 (https://zhangwenbao.com/ai-hallucinated-links-fake-citations-seo.html)。 自填评分被整治的力度有多大,刷一条挣1美元,罚上限53088美元 (https://zhangwenbao.com/fake-review-unit-payoff-and-denominator-gap.html)。 两个数都落在4.8到4.9这个区间,评价数都是四位数。这个区间是电商评分的典型分布——低于4.5会劝退,接近5.0反而显得可疑。 这也是自填评分难以取信的根本原因:当所有人都落在同一个窄区间里时,这个数字就不再有区分度了。它变成了一个入场券,而不是一个信号。 ## 评分区间的另一层含义 4.8到4.9这个区间还有一层值得说的东西:它其实是被筛选机制造出来的。 用户到底在问什么,十种电商查询模式 (https://zhangwenbao.com/geo-consumer-intent-10-pattern-coverage-guide.html)能查出盲区。 差评里藏着定位,从对手评论挖差异化卖点的完整框架 (https://zhangwenbao.com/competitor-review-gap-analysis-positioning.html)。 大多数电商的评价体系有两个天然偏差。一是沉默的多数——满意的用户不写评价,不满意的用户也常常直接退货了事,真正留下评分的是两头的少数人。二是邀请式采集——很多品牌只向已完成配送且没有售后工单的订单发送评价邀请,这本身就过滤掉了体验最差的一批。 两个偏差叠加,结果就是绝大多数品牌的公开评分都落在4.6到4.9之间。这不是因为产品都好,是因为采集口径都一样。 理解这一点之后,评分这个数字该怎么用就清楚了:看绝对值没意义,看评价数量和分布形态才有信息。一个4.7分带一万条评价的商品,比一个4.9分带三十条评价的商品可信得多。 ## 那评价数量能不能信 比评分可信一些,但也不是完全可信,因为它同样是自填的展示数字。 能被复算的数据才有价值,把数据做成持续吸外链的磁铁 (https://zhangwenbao.com/original-data-research-content-link-magnet.html)。 数字能不能追到出处,九条查得到出处八条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)。 常见的做法是把同一系列所有型号的评价合并计数,或者把跨平台的评价加总。这些做法本身不违规,但会让这个数字失去可比性——你不知道对方那一万条是不是也这么算的。 真正可核验的路径只有一条:指向一个你改不动的第三方评价页面。实测这批站里有42.6% 装了第三方评价系统,其中一部分的评价页面是可以独立访问的。能点开到第三方页面的评分,价值远高于页面上一个纯数字。 这个判据和前面讲身份声明时的结论是同一条:指向一个你控制不了的地方,比在自己地盘上多写十行都有用。 ## 那评价这一层该怎么做 既然自填评分基本走不通,这一层还有什么可做的?有三件事,按性价比排。 用户内容还能再利用,内容再利用地图怎么画 (https://zhangwenbao.com/content-repurposing-map-seo-llm-visibility.html)。 评论本身就是原料,把用户评论变成高转化的产品描述 (https://zhangwenbao.com/ai-transform-reviews-into-product-descriptions.html)。 第一,把评价系统的输出打通到页面源码里。多数主流评价服务商都支持同时输出一份可被机器读取的数据,只是默认不开或者需要在主题里加一段代码。开通之后,评分才会以正确的形式存在,而不是只在插件的界面里显示。 第二,让评价内容本身成为可读文本。用户写的评论是极好的原创内容——真实的使用场景、真实的问题、真实的措辞。如果这些内容只存在于异步加载的插件里,那对搜索和生成式回答来说等于不存在。把评论渲染成页面上的真实文本,这一步的收益比标记评分本身大得多。 第三,给出可点开的第三方页面。如果你用的评价服务商提供公开的品牌页面,在站上给一个链接过去。这是这一层唯一真正可核验的动作。 三件事的共同点是:都不涉及往上报一个数字,而是让已经存在的真实材料被读到。这恰恰是所有自填字段问题的通用解法。 ## 顺带说一句差评 还有个反直觉的点值得提。很多品牌想尽办法让页面上只显示好评,但从可信度的角度看,清一色好评反而是减分项。 站外的提及也要盯,监控、回收与图片署名 (https://zhangwenbao.com/brand-mention-monitoring-unlinked-reclamation-image-attribution.html)。 回复差评这件事有实打实的收益,评论关键词与商家资料活跃度的实战配方 (https://zhangwenbao.com/local-seo-ai-visibility-keyword-signals-review-response-gbp-playbook.html)。 一个4.9分、几千条评价、翻十页找不到一条批评的商品页,给人的感觉不是产品完美,是评价被筛过。而一个4.6分、里面有几条中肯的差评加上商家认真回复的商品页,说服力高得多。 这跟本文的主线是一致的:可信度不来自数字好看,来自这份数据看起来没被动过手脚。差评的存在本身就是一种证据——它证明这套评价系统不是你能随意编辑的。 ## 这类数字什么时候会被结果反推? 前面反复说这类数字“会被结果验证”,具体是怎么验的?大致三条路径,时间尺度差别很大。 本地场景的核验更直接,商家资料的实体识别五步排查 (https://zhangwenbao.com/local-seo-google-entity-business-category.html)。 后台管理正在被自动化接手,AI替你回评论读后台,可有一步千万省不得 (https://zhangwenbao.com/google-business-profile-gemini-app-tools.html)。 ## 路径一:用户当场兑现 最快也最直接。用户按你写的门槛凑单,结账时发现还要付运费;或者按你写的天数申请退货,被告知已经过期。 用户找不到答案就会问,搜索框怎么设计才不浪费这个入口 (https://zhangwenbao.com/site-search-bar-ux-design-conversion.html)。 结账环节的摩擦最伤,用户回头改一次收货地址前面填的全没了 (https://zhangwenbao.com/checkout-rework-path-vs-first-fill.html)。 这条路径的反馈时间以天计,反馈形式是客诉和差评。它的杀伤力被严重低估了,因为一条“说好免运费结果还收钱”的评价,比十条中肯的产品批评更伤转化。 ## 为什么第一条路径最该被重视 三条路径里,用户当场兑现这一条最容易被当成售后问题打发掉,其实它的信息价值最高。 口碑的正反两面都要经营,把忠实用户养成长期代言人 (https://zhangwenbao.com/dtc-brand-ambassador-program-advocacy-operations.html)。 工单要能归类才有价值,多语种客服的四层SLA与工单分流 (https://zhangwenbao.com/dtc-overseas-customer-service-multilingual-4-layer-sla-ticket-routing.html)。 因为它是唯一能精确定位到哪一句话出了问题的路径。平台抽查只告诉你数据不合格,财务数据只告诉你毛利掉了,而一条“说好满75免邮结果76块还收了运费”的客诉,直接指出了是哪一个数、哪一个场景、哪一步流程。 所以处理这类工单时,除了给用户一个交代,还该做一件事:把它记进一个专门的清单,按承诺类型归类。三个月下来,这份清单会清楚地告诉你哪几句承诺最容易出问题。 实践中最常上榜的通常是三类:门槛金额是含税还是不含税没说清、退货期从下单算还是从收货算没说清、免运费适不适用于特价商品没说清。三类都不是承诺本身错了,是条件没写全。 ## 条件写全比数字写大更重要 顺着上一条说。绝大多数承诺纠纷不是因为数字给得不够,是因为限定条件缺失。 落地页的文案原料从哪来,自动升级之后原料全在落地页上 (https://zhangwenbao.com/ad-landing-page-copy-source-robots-template.html)。 条款写得再细也要看拿哪把尺子量,外贸品质条款的四种约定方式 (https://zhangwenbao.com/export-contract-quality-clause-sample-specification-faq-gmq.html)。 “满75免邮”这四个字后面至少还有五个未说明的问题:含不含税、算不算折扣后的价格、退货后不足75要不要补运费、偏远地区适不适用、特价商品参不参与。 把这些写全,页面会变丑,转化可能掉一点点。不写全,省下的这点空间迟早以客诉的形式还回来。 折中做法是主承诺短,条件放一个可点开的说明里。横幅上写“满75免邮”,旁边一个小小的详情链接,点开是完整条件。这样既保住了传播效率,又把条件说清楚了,出问题时也有据可依。 ## 路径二:平台抽查比对 时间尺度以周到月计。平台拿你声明的数据去比对实际页面、实际结账流程,对不上就降级或撤下展示。 违规判定的边界也在动,返回按钮劫持新规的排查指南 (https://zhangwenbao.com/google-back-button-hijacking-spam-policy.html)。 自动检测也会误伤,执法指南里的例外被标成高风险 (https://zhangwenbao.com/ad-word-checker-exception-overlap-falsepositive-guide.html)。 这条路径只对写成机器可读的那部分生效——你不写,它就无从比对,这也是很多人不写的隐秘动机。但不写的代价是完全拿不到那个展示位。 ## 路径三:自己的财务数据 时间尺度以季度计,也是最迟钝的一条。 指标体系怎么搭才不骗自己,三平台三百站的实测数据对比 (https://zhangwenbao.com/seo-kpi-guide.html)。 跟财务对齐口径有清单,预算到归因到并购退出的七个动作 (https://zhangwenbao.com/finance-cfo-seo-collaboration-7-actions-budget-attribution-asset.html)。 免运费门槛定得太低,运费吃掉毛利;退货期限给得太长,退货率悄悄爬升;试用期承诺太宽松,逆向物流成本失控。这些都不会立刻显现,它们混在整体数字里,通常要到季度复盘时才被算出来。 更麻烦的是归因困难:毛利率下滑到底是因为运费补贴,还是因为促销力度,还是因为品类结构变了?如果没有事先按承诺条件拆分数据,事后基本算不清。 反推路径 | 时间尺度 | 信号形态 | 能不能提前防 | 用户当场兑现 | 天 | 客诉与差评 | 能,把条件写清楚 | 平台抽查比对 | 周到月 | 展示被撤或降级 | 能,声明与实际对齐 | 自己的财务数据 | 季度 | 毛利率下滑 | 能,但要事先埋点 | ## 要算清账,得提前埋三个东西 第三条路径最迟钝,但也最可控——前提是你事先埋好了能拆开算的数据。三样东西,成本都不高。 平台数据本身也会出错,修复之后怎么走长期自动跟踪 (https://zhangwenbao.com/gsc-impression-bug-inflated-data-fix.html)。 把多平台花费拉到一起,算统一回报的做法 (https://zhangwenbao.com/ga4-import-ad-cost-data-non-google-blended-roas.html)。 第一,在订单上打一个标记:这一单有没有触发免运费。这个字段多数电商系统本来就有,只是没被拉进分析。有了它,你才能算出免运费补贴了多少钱,以及触发免运费的订单客单价是不是真的更高。 第二,记录退货申请距离收货的天数。不是退货率,是时间分布。有了这个分布,前面说的“延长退货期会不会增加成本”就不用猜了,直接看曲线尾巴有多长。 第三,把承诺的历史版本存下来。免运费门槛什么时候从50改到75,退货期什么时候从14天改到30天,各改了几次。没有这份时间线,你永远没法把业绩变化归因到某次承诺调整上。 三样都埋好之后,季度复盘时能回答的问题会完全不同。从“毛利率为什么掉了”变成“免运费补贴涨了多少、由哪个门槛调整引起、多带来了多少订单”。 ## 一个容易被忽略的反向效应 还有件事值得提:承诺放宽有时候不增加成本,反而降低成本。 要验证就得设计好实验,30个A/B测试方案 (https://zhangwenbao.com/ab-testing-ctr-conversion-optimization.html)里有现成题目。 要验证这类效应得先算样本量,避免假胜利的三个公式 (https://zhangwenbao.com/dtc-ab-test-sample-size-3-formulas.html)。 退货期从14天延到30天,直觉上退货率会涨。但实际数据经常相反——期限宽松时,用户不着急,很多人拖着拖着就不退了;期限紧张时,用户会在截止前抢着申请,宁可退了再说。 这个效应在客单价高、决策慎重的品类里尤其明显。紧迫感会制造退货,从容感会消解退货。 所以决定这类数字时,别只算最坏情况。拿自己的历史数据跑一次对照,比任何行业经验都靠谱——而能不能跑这个对照,取决于前面那三个埋点做没做。 ## 那到底该不该把承诺写成机器可读? 讲了这么多风险,是不是干脆别写?不是。判据其实很清楚。 落到动作上,结构化数据怎么配合SEO落地 (https://zhangwenbao.com/seo-schema-guide.html)那份避坑清单可以对着改。 结构化数据到底有没有用,官方说法加实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)给过不含糊的答案。 ## 先问一个前置问题 在讨论写不写之前,有个更前置的问题得先答:你的承诺,实际执行的规则到底是什么? 排查顺序比手段重要,从症状分诊到动手修复的急救手册 (https://zhangwenbao.com/google-not-indexed-fix-playbook.html)。 把自查做成体系,企业网站SEO审计该查什么 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)有可裁剪的框架。 听起来像废话,但真去问,很多公司答不上来一个确定的数。首页写30天,客服培训手册写15天,售后系统里配的是20天,实际执行时看客户态度。四个答案,没有一个是错的,因为从来没人统一过。 遇到这种情况,先别急着写机器可读的那一份。先把四个答案收敛成一个。这一步做完之后,写不写反而变成小事了——有了确定规则,写进去毫无风险。 顺序不能反。在规则不确定的时候把某一个版本写成机器可读,等于随便挑一个答案对外承诺,而这个答案未必是运营真正在执行的那个。 ## 怎么收敛这几个答案 实操上有个简单办法:以实际执行的那个为准,往上取。 把口径写进合同也是一种收敛,达标定义与违约责任 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)。 推动跨部门对齐要会讲,一套让老板秒懂还拨预算的讲法 (https://zhangwenbao.com/explain-seo-geo-value-to-non-technical-leadership.html)。 把最近三个月的退货工单拉出来,看实际批准的最长天数是多少。如果实际上超过25天的申请也都批了,那对外就写30天,因为你本来就在这么做,写出来只是把既成事实说清楚。 反过来,如果实际执行严格卡在15天,那首页那个30天就是一句空话,早晚出事。这时候要么改流程支持30天,要么把首页改成15天。两个选择都行,唯独不能维持现状。 这个动作还有个副产品:它逼着市场和运营坐下来对一次数。而这次对数的价值,往往超过这一栏本身——因为暴露出来的通常不止一处不一致。 ## 该写的三种情况 第一,这个承诺已经是系统里的确定规则。免运费门槛写在结算系统里,退货天数写在售后流程里,这些本来就是硬规则,不会因人而异。这类承诺写成机器可读没有任何额外风险,因为它本来就在被执行。 平台侧怎么加,128种类型该怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)。 要补别的类型,结构化数据生成器的13种类型 (https://zhangwenbao.com/schema-generator-jsonld-13-types-guide.html)够覆盖多数页面。 第二,你所在的品类竞争激烈,展示位有实际价值。购物结果里能不能挂上配送和退货标签,在同质化品类里是真的会影响点击的。 第三,你的目标市场是搜索和生成式回答的重度使用地区。用户越倾向于直接问而不是点进来看,你的信息就越需要以机器能读的方式存在。 ## 不该写的两种情况 第一,这个承诺是活动性的、会变的。大促期间的免运费门槛跟平时不一样,写成结构化数据之后忘了改,那就是一条持续存在的错误声明。会变的东西要么做成动态生成,要么就别写。 投机做法为什么不灵,七大合作型优化策略 (https://zhangwenbao.com/geo-cooperative-optimization-vs-adversarial-attack.html)是反面。 错误信息被放大的风险,三条攻击路径与三层防御 (https://zhangwenbao.com/geo-ai-poisoning-315-deep-analysis.html)值得提前看。 第二,你的实际履约做不到承诺的水平。这条听着像废话,但现实里不少站的首页承诺和实际流程是脱节的——首页写着30天退货,售后系统里设的是15天。这种情况下写进机器可读的字段等于自己举报自己。 遇到第二种情况,正确的顺序是先把实际流程改到和承诺一致,或者把承诺改到和实际一致,然后再考虑要不要写。 ## 先改哪个字段最划算 如果决定要写,从哪个字段开始最划算?按投入产出排一下。 另一个低成本高收益的标记,面包屑的四种类型与实操 (https://zhangwenbao.com/seo-breadcrumbs-types-schema-implementation.html)。 同类取舍在问答标记上也有,富结果被砍之后FAQ标记怎么改 (https://zhangwenbao.com/faq-schema-optimizer-rich-result-ai-citation-guide.html)。 字段 | 实现难度 | 展示收益 | 出错风险 | 优先级 | 退货天数 | 低,一个固定数 | 中 | 低,规则稳定 | 最先做 | 退货费用由谁承担 | 低 | 中 | 低 | 最先做 | 免运费门槛 | 中,会随活动变 | 高 | 中,改了容易漏 | 次之,需动态生成 | 处理时长 | 中,要问仓库 | 中 | 中 | 次之 | 运输时长 | 高,按目的地不同 | 高 | 高,最容易做不到 | 最后做 | 适用国家 | 低 | 无直接收益 | 不写风险更高 | 只要多市场就必写 | 顺序背后的逻辑很简单:先写那些本来就固定、不会随活动变、你百分之百做得到的。这些字段写进去零风险,而且能立刻拿到一部分展示位。 运输时长排最后,是因为它取决于承运商和目的地,波动最大,也最容易出现声明和实际不符。宁可不写运输时长,也别写一个自己做不到的数。 ## 一个折中的做法 如果拿不准,有个折中:先写最保守的那一版。 保守版本也能拿到展示位,抢占精选摘要仍是被引用的近路 (https://zhangwenbao.com/featured-snippet-position-zero-capture-ai-overview.html)。 一个展示位说没就没,富结果被砍之后还该不该写 (https://zhangwenbao.com/google-drops-faq-rich-results.html)。 免运费门槛写平时的那个值,不写活动价;退货天数写系统里实际执行的那个数,不写首页横幅上的营销话术;配送时效写你九成订单能达到的那个区间,不写最快的那个。 保守版本的好处是它经得起比对,而比对通过之后带来的展示收益,和激进版本没有区别。这一层不是拼谁写得漂亮,是拼谁写的是真的。 ## 动态生成具体怎么做 前面说“会变的东西要么动态生成要么别写”,这一步在实现上比想象中简单,值得展开一下。 模板里塞参数会有副作用,给内链加参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)。 同一套数据源还能驱动别的标记,用结构化数据标注重要内链 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)。 核心原则是:页面上显示的那个值和结构化数据里的那个值,取自同一个数据源。 免运费门槛写在结算系统的配置里,页面横幅从那里读,结构化数据也从那里读。这样活动一改,两处同时变,不存在遗漏的可能。 做不到这一点的常见原因是横幅那行字是硬编码在模板里的,甚至是设计稿里的一张图。这时候要改的不是结构化数据,是先把那行字从图片里解放出来,变成从配置读取的文本。 这个改造顺序很重要:先统一数据源,再补机器可读的那一份。顺序反了,你会得到两处独立维护的值,比只有一处更糟。 ## 如果承诺按市场不同呢 做多市场的站还有一层复杂度:同一个承诺在不同国家不一样。美国站满75免邮,德国站满50欧免邮,日本站不免邮。 多市场的结构选择在前,国家域名、子目录还是子域名 (https://zhangwenbao.com/international-seo-domain-structure-cctld-subdirectory-subdomain.html)。 多市场架构怎么选,先算清这笔账 (https://zhangwenbao.com/shopify-markets-vs-plus-expansion-stores-international-seo-architecture.html)。 处理办法有两种。一种是每个市场版本各自输出自己的那份声明,这是最干净的做法,前提是各市场的页面本来就是分开的。另一种是在同一份声明里标出适用地区,用适用国家字段限定范围。 第二种更灵活但也更容易写错,因为一旦漏标了地区,这条声明就会被理解为全球通用。实测那11个写了的站里,只有3个用了适用地区字段——其余的要么只做一个市场,要么就是漏标了。 建议是:只要你有超过一个市场,适用地区这一栏就必须写。它是这一层里最容易被忽略、后果又最直接的字段。 ## 回到广告那边,怎么止住数字虚高? 网站这边讲完了,回头收拾广告后台那个转化价值。做法可以借用同一套思路。 顺带澄清一个老问题,投广告到底帮不帮自然排名 (https://zhangwenbao.com/does-google-ads-help-organic-ranking-myth.html)。 目标定多少才算能赚钱,四步把出价目标算清楚 (https://zhangwenbao.com/google-ads-target-roas-cpa-break-even.html)。 ## 三个自查 第一,把回传值和财务口径对一次。把上个月广告后台报的转化价值总和,和财务系统里同期通过这些渠道产生的实际收入对一下。两个数差多少,差在哪个环节,一次就能看出来。 自查要能批量跑,两千条配额下的监控管线 (https://zhangwenbao.com/gsc-url-inspection-api-bulk-index-monitoring.html)。 对数之前要先把数据打通,分析、数仓、广告与后台怎么关联 (https://zhangwenbao.com/ga4-bigquery-google-ads-search-console.html)。 第二,把非交易类转化的价值系数翻出来重定。那些当初拍脑袋定的数字,用实际的线索转化率和平均客单价重算一遍。多数账户重算之后会发现原来的系数偏高不少。 第三,把退货扣回去。退货率高的品类,回传的价值应该按净值计算。这一步技术上有点麻烦,需要在退货发生后回传一次调整,但它是最能改变优化方向的一步。 ## 先做哪一个自查 三个自查里,先做第一个——把回传值和财务口径对一次。理由有三。 不花钱也能查不少东西,真正好用的免费工具清单 (https://zhangwenbao.com/free-seo-tools-zero-budget-checklist.html)。 差额怎么讲给老板听,四板块模板加仪表板 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)。 它最快。两个数一比,半小时之内就知道有没有问题、问题有多大。另外两个自查都要动配置,工期以周计。 它决定要不要做另外两个。如果对下来两个数只差百分之几,那说明口径基本干净,另外两步的优先级可以往后排。如果差出百分之三十以上,那就是必须处理的事。 它是唯一能拿去说服人的东西。要推动跨部门的改造,你需要一个所有人都看得懂的差额。“广告后台报了120万,财务那边同期这些渠道只认82万”,这句话比任何技术解释都有力。 对的时候有两个细节要注意。时间窗口要对齐——广告平台按点击归因,转化可能记在下单前几天的那次点击上,跨月时会错位,所以对季度比对月更稳。口径要说清含不含税和运费,这是最常见的差异来源,先把这两项排除掉再看剩下的差额。 ## 口径一致比数值准确更重要 这是本节最想说的一句。 口径统一之后就能自动化,用工作流把四个场景闭环 (https://zhangwenbao.com/n8n-dtc-seo-pipeline-4-scenarios.html)。 内容侧也有同样的口径问题,从流量归因到单篇盈亏表 (https://zhangwenbao.com/content-roi-performance-measurement-attribution.html)。 很多人纠结于回传的数字准不准——含不含运费,算不算税,要不要扣成本。这些当然重要,但比准确性更重要的是口径的一致性。 因为自动出价系统学的是相对关系:哪个词带来的价值更高,哪个受众更值钱,哪个时段回报更好。只要所有转化都用同一套口径折算,哪怕整体偏高20%,系统学到的相对关系仍然是对的。 反过来,如果口径不一致——有的品类含运费有的不含,有的加了系数有的没加——那么整个相对关系就是乱的,系统会被系统性地带偏。 所以清理的优先级应该是:先统一口径,再校准数值。顺序反了,力气会白花。 ## 做完这三步之后会发生什么 提前说一下预期,免得做完之后被吓到。 大盘变化时怎么交代,流量暴跌之后的实战指南 (https://zhangwenbao.com/organic-search-disrupted-aeo-strategy.html)。 数字变难看时怎么解释,流量下降不等于失败的八个维度 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)。 口径清理完,后台的回报率数字大概率会变难看。原来报5倍的可能变成3.2倍,原来看着盈利的某个渠道可能变成持平。这不是变差了,是原来那个数就不对。 更要紧的是心理准备:这个数字要拿给老板看。一个突然从5掉到3.2的指标,如果没有事先解释,会被当成投放出了问题。 所以清理这件事最好配一句话一起交出去:数字变了是因为口径改了,改之前的数和改之后的数不可比,从这个月起用新口径重新建立基线。把这句话说在前面,比事后解释省事得多。 另一个可预期的变化是预算分配会自己调整。系统按新的价值分布重新学习,通常需要两到四周。这段时间里数据会有波动,别在这个窗口里再做别的大动作。 ## 值不值得做 有人会问,既然口径不准也能跑,为什么要折腾? 算不清账的时候,品牌影响力怎么衡量 (https://zhangwenbao.com/zero-click-search-brand-influence-measurement.html)能补一半答案。 付费数据的价值不止在广告里,6类付费数据怎么反哺SEO决策 (https://zhangwenbao.com/ppc-data-feedback-seo.html)。 答案是:口径不准的时候,你的所有优化决策都建立在错的相对关系上。你以为在加码高价值渠道,实际可能在加码高虚报渠道;你以为砍掉的是低效词,实际砍掉的可能是回传值偏保守但真赚钱的那批。 这个损失不会体现在任何报表里,因为报表用的就是那套错的口径。它只会体现在一个地方——你花的钱和你赚的钱之间那个说不清的差额。 所以这件事的价值不在于让数字变好看,而在于让后面所有的判断有一个可靠的基础。基础不对,后面做得越勤快,偏得越远。 ## 还有一层是数据能不能被信任 顺带说一个更大的背景。行业里对第三方数据平台的信任度,这两年一直在下滑。关于从业者想要数据却不信卖数据的平台这个矛盾 (https://www.searchenginejournal.com/the-geo-trust-gap-seos-want-the-data-but-not-the-platforms-selling-it/585161/)有过专门的讨论,核心争议就是口径不透明。 信任下滑是普遍现象,用的人越来越多信的人却越来越少 (https://zhangwenbao.com/ai-search-adoption-rises-trust-declines.html)。 第三方指标同样是自己算的,网站权威这个数谷歌到底认不认 (https://zhangwenbao.com/what-is-domain-authority.html)。 这跟本文讲的是同一件事的两面:你给平台的数字不可核验,平台给你的数字也不可核验。整条链路上,每一环都在采信上一环的自我声明。 在这种环境里,能被复算的东西价值会持续上升。不是因为它更准,是因为它可以被检查。 ## 技术上怎么把净值回传出去 把退货扣回去这一步,是三个自查里最难落地的,值得给个可行路径。 平台规则说变就变,整个大类被挡在门外 (https://zhangwenbao.com/apple-maps-ads-home-services-ban.html)是个例子。 回传链路怎么重建,归因失真怎么救的九招 (https://zhangwenbao.com/dtc-meta-ads-ios14-attribution-rebuild.html)。 思路是两段式回传:下单时先按订单金额回传一次,等退货窗口过了再回传一次调整值。多数广告平台都支持对已回传的转化做调整或撤销,只是这个能力用的人不多。 实现上要解决一个问题:你得能把退货单和当初那次转化对应起来。这需要在回传时带上一个唯一的订单标识,退货发生时用同一个标识去做调整。多数电商系统都能做到,只是默认配置没开。 如果技术上实在做不了两段式,还有个粗糙但有效的替代:按品类的历史退货率给回传值打折。退货率30% 的品类,回传时乘0.7。这个做法不精确,但它至少让不同品类之间的相对关系是对的——而前面说过,相对关系才是自动出价真正在学的东西。 ## 非交易类转化怎么定价值 另一个老大难。加购、注册、咨询这些非交易转化,价值系数最容易拍脑袋。 线索来源还能挖得更细,用正则挖AI搜索提示词的五步 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)。 要算清用户旅程得先把数据留下来,服务器端跟踪的八步部署 (https://zhangwenbao.com/dtc-ga4-bigquery-user-journey-stape-server-side.html)。 给个不那么拍脑袋的算法:用这个动作到最终成交的转化率,乘以平均成交价值。比如一百个咨询里最后成交八个,平均每单500,那一次咨询的价值就是40。 这个算法的关键不是精确,是它有一个可以定期重算的依据。业务变了,重算一次系数就跟着变了,不需要重新拍。 更要紧的是记得定期重算。保哥见过不少账户里的价值系数是三年前定的,期间客单价涨了、转化率变了,那个数字还纹丝不动。一个不会随业务变化的估值,用得越久偏得越远。 ## 三种自填字段,到这里凑齐了 本文是一组观察里的第三篇,到这里可以把三种情况并排放一次。 实体权威要靠跨岗协作,SEO与内容团队的四阶段框架 (https://zhangwenbao.com/entity-authority-ai-search-seo-content-collaboration.html)。 核验不了会带来什么,71家审计揭开平均84%的身份泄漏 (https://zhangwenbao.com/ai-search-verify-business-identity-leak.html)。 ## 按可核验程度排开 类型 | 典型字段 | 能不能核 | 什么时候暴露 | 正解 | 无从核验 | 这段内容谁写的 | 基本不能 | 可能永远不暴露 | 建立自己的过程留痕 | 可被内容核验 | 这一页是什么语言 | 能,读一遍 | 立刻 | 让内容本身撑得住 | 只能被结果反推 | 这一单值多少钱 | 当场不能 | 几天到几个季度 | 口径一致,说到做到 | 署名这一栏怎么做才被认,六个信号的实战 (https://zhangwenbao.com/author-byline-entity-eeat-ai-citation-content-mechanism.html)。 可验证的出处正在变成新的信任货币,内容溯源这条线 (https://zhangwenbao.com/content-provenance-c2pa-trust-currency-geo.html)值得提前看。 三格的药方互为毒药,这一点值得记住。 第一格的正解是不要指望标记,去积累旁证;如果你在第二格用这招,纯属浪费,因为对方本来就能自己看。 第二格的正解是去改内容本身;如果你在第三格用这招,方向完全错了,因为那个数字根本不在内容里。 第三格的正解是统一口径并保证履约;如果你在第一格用这招,无从下手,因为没有可执行的口径。 ## 为什么这三格值得记住 把这三格记牢的实际好处,是它能帮你在遇到一个新问题时快速判断力气该往哪儿使,而不必等踩坑之后才知道。 评估别人有现成范本,质量评估手册怎么读 (https://zhangwenbao.com/search-quality-rater-guidelines-qrg-seo-self-review-checklist.html)。 新指标出现时的通用应对,从页面碳足迹到爬虫抓取的同一套规范 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)。 举个例子。假设明天出现一个新的平台字段,要求你申报商品的碳排放数据。这属于哪一格? 先问:平台能不能从你交的材料里读出来?不能,碳排放不写在商品页上。再问:有没有独立来源?有——如果有认证机构出具的核算报告,那就是可核验的。最后问:多久会被检验?如果有抽查机制,那是中期;如果没有,那基本永远不会。 三问答完,做法就清楚了:有认证的把认证指过去,没认证的就别报一个自己编的数,因为一旦将来引入核查机制,之前报过的数就是把柄。 这套判断不依赖你了解这个新字段的任何细节,也不依赖平台的规则文档。它只依赖信息结构,而信息结构比规则稳定得多。 ## 三格各自的误判长什么样 比正解更有用的是误判,因为误判是大家真实会犯的错。三格各有一种典型错法。 最常见的误判之一,AI写的内容会不会被惩罚 (https://zhangwenbao.com/ai-generated-content-google-penalty-myth.html)官方从没这么说过。 加大声明力度通常没用,不做什么的清单比做什么的更可核查 (https://zhangwenbao.com/ai-usage-disclosure-negative-list.html)。 第一格的误判是加大声明力度。没人信我是原创的,那我就多写几遍、在页脚加个声明、做个证书图标。这些动作全都在同一个层面上打转,而问题恰恰是这个层面没有说服力。正解是换一个层面——拿出过程和一手材料。 第二格的误判是反复改标签。语言标记不对就改标记,改完还不行就再改一遍写法。而问题往往在内容本身——页面上写的根本不是那个语言,或者内容太少判不出来。正解是让内容对得上你写的那个值。 第三格的误判是把数字调大。回报率不好看,就把转化价值调高;转化不够多,就把更多动作算成转化。短期数字确实好看了,代价是把出价系统喂坏,它会按错误的价值分布去分配预算。正解是统一口径,宁可整体偏低也别偏得不一致。 三种误判有个共同点:它们都在自己能改的那一栏上使劲,而问题都不在那一栏。这大概是自填字段最典型的陷阱——因为那一栏是你唯一能动的,所以你会一直动它。 ## 怎么快速判断自己在哪一格 拿到一个具体问题,用一句话就能定位:如果我把这一栏的值改成任意一个数,对方会不会发现? 日志能验的东西比你想的多,每五次抓取就有一次IP不属于谷歌 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)。 当场能不能验,真假Googlebot该怎么验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)是最清楚的例子。 当场就发现,说明你在第二格,改内容去。永远不会发现,说明你在第一格,改声明没用,去建旁证。过一段时间才会发现,说明你在第三格,重点是保证说到做到、以及提前埋好能算清账的数据。 这一问不需要任何专业知识,也不受平台规则变化影响。因为它问的是信息结构,不是具体规则。 ## 一条通用的判断顺序 拿到任何一个要填的字段,按三步问: 做到位还不够的地方,AI搜索为什么还是不选你的18个盲区 (https://zhangwenbao.com/topical-authority-limits-ai-search-entity-evidence.html)。 别把它当成口号,E-E-A-T怎么落到可执行清单 (https://zhangwenbao.com/eeat-ranking-factor-myth-signal-checklist.html)。 第一步,对方能不能从它已经拿到的材料里读出这个答案?能,那你填什么都不太重要,力气该花在让材料本身正确。 第二步,如果读不出来,这个答案有没有别的独立来源?有,比如官方登记、第三方记录,那就把指针指过去,让人能顺着查。 第三步,如果既读不出来又没有独立来源,那它什么时候会被结果检验?时间越短,越要保证说到做到;时间越长,越要提前埋好能算清账的数据。 这三步不需要记具体规则,它适用于任何平台的任何表单。因为它问的不是规则怎么写,而是对方凭什么相信你。 ## 最后回到那56比7 整篇写下来,最让人回味的还是那个56比7。 有些问题不在这一层,流量暴跌的七大元凶 (https://zhangwenbao.com/seo-cant-fix-broken-brand.html)里能对号入座。 承诺信息最后往往落在页脚,页脚怎么设计才是信任的最后一关 (https://zhangwenbao.com/ecommerce-footer-design-trust-conversion.html)。 56个站愿意把承诺印在首页最显眼的位置,用最大的字号,配最亮的颜色。7个站愿意把同一句话写成一行机器能读的代码。 差别不在技术,不在成本,甚至不在认知——差别在于前者是说给会忘记的人听,后者是说给会记账的系统听。 而随着越来越多的决策由会记账的那一方做出,这两句话的分量正在互换。 ## 这套框架的边界在哪 最后说一下这套三分法不适用的地方,免得被当成万能钥匙。 官方叫停过的动作值得逐条看,AEO和GEO到底还是不是SEO (https://zhangwenbao.com/googles-ai-search-guide-aeo-geo-still-seo.html)。 指标之外还有别的目标,排名第一却没人记得你的时候该盯什么 (https://zhangwenbao.com/seo-goal-recognition-not-rankings.html)。 它不处理“对方能读出来但读错了”的情况。比如页面语言判断,机器有能力读,但短文本、混排、专业术语多的页面它可能判错。这时候你的声明反而是有价值的纠偏信号,不该因为“反正它能自己看”就不填。 它不处理法定强制申报的字段。有些信息不管能不能被核验,法规要求你必须公示——企业主体信息、税务标识、争议解决渠道。这类没有取舍空间,该写就得写。 它也不处理纯粹的展示优化。标题怎么写、描述怎么组织,这些既不是承诺也不是分类,属于另一套逻辑,不在本文讨论范围内。 把边界画清楚之后,这套框架真正管用的范围是:那些你有选择权、对方需要采信、且采信之后会影响资源分配的字段。这个范围不大,但里面每一个都很值钱。 ## 写在最后 回头看这三种情况,会发现它们描述的其实是同一件事在不同时间尺度上的样子。 谁先说的这件事怎么判,原创内容的判定与镜像防御 (https://zhangwenbao.com/how-google-identifies-original-content-scraper-defense.html)。 原始出处一直在被悄悄奖励,原创报道到底指什么 (https://zhangwenbao.com/original-reporting-google-elevation-signal.html)梳理过这条线。 可被内容核验的字段,检验发生在当场;只能被结果反推的字段,检验发生在未来某个时点;无从核验的字段,检验可能永远不发生。 而人的行为几乎完全由检验的时点决定:当场会被检验的,大家填得又全又准;很久以后才检验的,大家开始放松;永远不检验的,就成了各说各话。136个站的三组数据,讲的都是这一件事。 所以如果只能记住一句话,那就是:看一个数字什么时候会被检验,就知道它现在有多可信。这句话既可以用来审视自己的页面,也可以用来判断别人给你的任何一份数据。 ## 三篇合起来,其实只回答了一个问题 这组观察从内容来源开始,经过语言与地区,到这里的承诺数值,看着是三个完全不相干的话题——一个属于内容合规,一个属于国际化,一个属于电商运营。 但它们回答的是同一个问题:当对方需要给你分类、而分类所依据的那个字段由你自己填时,会发生什么。 答案也高度一致。能被验证的,大家填得又准又全;不能被验证的,覆盖率立刻塌掉。136个站的三组数据,三次得出同一个结论: 身份声明里,纯自述的名称94% 的站填了,能去官方登记处比对的税号只有1.2%。语言标记里,能被内容核验的语言属性97.8% 填对了,不能被核验的地区对应关系一半的站没做、做了的又有七成掺水。承诺数值里,说给人听的46.3%,说给机器听的8.1%。 三组数字的形态完全一样:只要一个字段的填写会带来可被追究的责任,它的覆盖率就会掉一个数量级。 ## 这对做事的人意味着什么 两层意思,一层防守一层进攻。 防守层面:别把力气花在改自填字段上。如果对方能自己看出来,你改标签没用;如果对方看不出来,你改标签也没人信。真正该改的永远是那个字段所描述的事实本身。 进攻层面:可核验的那一层几乎是空的。136个站里,能被外部独立查证的身份字段填写率只有1.2%,把承诺写成机器可读的只有8.1%,把评分写进结构化数据的只有1.5%。这三个位置上,你几乎没有竞争对手。 而这三个位置的共同点是:做起来不难,只是要承担说出去的后果。在一个越来越依赖机器判断的环境里,愿意承担这个后果的人,会拿到一个别人主动让出来的位置。 ## 常见问题解答 ## 把配送和退货政策写进结构化数据,有什么实际收益? 主要是展示收益。购物结果和商品卡片里那些配送时间、退货天数的标签,数据来源就是这类字段,写了才有机会展示。此外比价筛选和生成式回答也只读机器可读的那份,你首页横幅上的图片文字这三条链路一个字都读不到。实测136个站里只有11个写了,这是一个竞争很少的位置。 ## 写进去之后如果做不到会怎样? 平台会拿你声明的和实际能观察到的比对,比如声明免运费门槛是75,抽查发现结账时80也收运费。对不上轻则这条信息不再展示,重则影响整个站的商品数据资格。所以正确顺序是先让实际流程和承诺一致,再考虑写。做不到就先别写,不写只损失展示机会,写了做不到损失的是资格。 ## 免运费门槛应该定多少? 实测69个门槛值的中位数是99,高频取值是75、100、50、99、150、200。整数明显比99结尾的更常见,跟商品定价的习惯正好相反,因为免运费门槛的作用是让用户算得清还差多少,整数更好心算。具体定多少要看你的客单价分布和毛利结构,通常设在平均客单价的1.2到1.5倍之间,才有拉高客单的作用。 ## 退货天数写多少合适? 实测10个明确天数里30天出现7次,是事实标准。这个数字的形成有法规背景:欧盟消费者权利指令给远程购物的法定冷静期是14天,写30天在所有主要市场都稳稳高于法定线,同时不至于承担太久责任。做欧洲市场要注意这一栏只能往上加不能往下减,写得低于法定值不只是营销问题。 ## 为什么装了评价系统的站不把评分写进结构化数据? 两个原因。技术上,评价内容通常由第三方系统异步加载,静态页面源码里没有,要写进去需要额外配置让评价服务商同时输出一份。责任上,自填评分曾被大规模滥用,平台后来对自我声明的评分展示做了限制。实测42.6% 的站装了评价系统,只有1.5% 写进了结构化数据,差28倍。 ## 广告后台的转化价值回传,最该先修哪一步? 先统一口径,再校准数值。自动出价系统学的是相对关系——哪个词更值钱、哪个受众回报更高,只要所有转化用同一套口径折算,哪怕整体偏高两成,相对关系仍然是对的。反过来如果有的品类含运费有的不含、有的加了系数有的没加,整个相对关系就乱了,系统会被系统性带偏。顺序反了力气会白花。 ## 怎么判断一个字段该不该认真填? 按三步问。第一步,对方能不能从已经拿到的材料里读出答案,能的话力气该花在让材料本身正确。第二步,读不出来的话有没有独立来源,有就把指针指过去让人能顺着查。第三步,既读不出来又没有独立来源的,看它什么时候会被结果检验,时间越短越要说到做到,时间越长越要提前埋好能算清账的数据。 ## 权威参考资料 ## Vary响应头实测:说变的3个,真变的17个 - URL:https://zhangwenbao.com/vary-header-declared-vs-actual-response-variation.html - 分类:技术SEO - 发布:2026-08-15 | 更新:2026-08-15 - 摘要:同一个网址,换个语言偏好再请求一次,拿回来的东西可能完全不同。这件事没有任何文档记着,你的缓存也不一定知道。 - 关键词:技术SEO,HTTP响应头,独立站运营,缓存策略 > **TLDR**:摘要:给139个品牌站的首页各发4次请求,地址一个字不改,只换请求头。结果是128个站发了Vary头声明自己随什么变,其中写明随语言变的只有3个;而实测真的随语言变的有17个,差5.7倍。压缩那一层同样:17个站的编码随请求变,Vary里也没写。这些行为没有任何一份文档记着,只能靠发两次不同的请求把它试出来。 > 摘要:给139个品牌站的首页各发4次请求,地址一个字不改,只换请求头。结果是128个站发了Vary头声明自己随什么变,其中写明随语言变的只有3个;而实测真的随语言变的有17个,差5.7倍。压缩那一层同样:17个站的编码随请求变,Vary里也没写。这些行为没有任何一份文档记着,只能靠发两次不同的请求把它试出来。 先描述一个很容易被忽略的场景。 你的站上线了,首页地址只有一个。你在浏览器里打开它,看到的是英文版,价格是美元。同一时刻,另一个人在别的地方打开同一个地址,看到的是德语版,价格是欧元。 中间没有跳转,地址栏里的字符完全一样。是服务器根据请求里附带的信息,当场决定给哪一版。 这件事本身没问题,多语言站几乎都这么做。问题在于:你的服务器在按什么条件变,没有任何一份文档写着。它不在代码注释里,不在部署文档里,也不在你交给同事的那份说明里。它只存在于服务器的实际行为中,要知道答案只有一个办法——发两次不同的请求,看看拿回来的东西一不一样。 更麻烦的是中间还隔着缓存。缓存要决定一份副本能不能给下一个人用,靠的不是观察行为,而是读一个叫Vary的响应头。这个头是站点自己声明的:我随哪几个请求头变。声明写对了,缓存分得清;写漏了,缓存会把德语版发给要英文的人。 所以这里有一对可以直接比对的东西:一边是站点声明自己随什么变,一边是它实际随什么变。这次把211个海外品牌站的首页各请求四次做了这个比对,能正常返回正文的139个站,下面全是从这139份响应里数出来的。 ## 同一个地址,为什么会给出不一样的东西? 先把机制讲清楚,不然后面的数字没法读。 这几个头字段各管什么,X-Robots、缓存与Vary的分工 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)有一份逐项拆解。 ## 请求里带着的那几行字 浏览器请求一个地址时,除了地址本身,还会附上一批说明自己情况的头字段。常用的有这么几个:Accept-Encoding 说自己能解哪几种压缩,Accept-Language 说自己偏好哪种语言,User-Agent 说自己是什么客户端,Cookie 带着之前存下的状态。 这些字段在日志里就是识别依据,八类UA的识别与流量归因 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)可以直接照抄。 服务端读这些字段做判断很常见,五种识别爬虫的写法 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)就是拿其中一个字段做的。 服务器可以读这些字段,然后决定返回什么。返回压缩过的还是没压缩的、返回英文版还是德语版、返回桌面版还是移动版、返回登录态还是游客态——都是同一个地址下的不同答案。 这套机制叫内容协商 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Content_negotiation),它是HTTP从一开始就有的设计。它的好处是地址干净,坏处是同一个地址不再对应唯一的内容。 ## 缓存必须知道这件事 缓存的工作是把响应存下来,下次有人请求同一个地址就直接给。如果同一个地址会给出不同答案,缓存就必须知道该按什么把这些答案区分开。 参数也会让同一个页面变成多个地址,给内链加追踪参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)是同一类问题。 缓存头这一套怎么配才不出事,让回头客秒开又不犯改了不更新的配置 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)讲得比较全。 这就是 Vary 的用途,它的取值会直接参与缓存键的计算 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Vary)。服务器在响应里写一句 Vary: Accept-Encoding,意思是这份内容随压缩偏好变,请按这个字段分开缓存。写 Vary: Accept-Encoding, Accept-Language,就是按两个字段的组合分开存。 写漏了会怎样?缓存会以为这个地址只有一个版本,把第一个人拿到的那份存下来,发给后面所有人。第一个访客碰巧是德国来的,后面所有人都会拿到德语页。这类事故在业内有个专门的说法,叫缓存投毒。 ## 缓存投毒是怎么发生的 把这个后果讲具体一点,因为它是本文所有讨论的现实动机。 发错语言版本的代价不只是体验,五个翻译陷阱与人审六步 (https://zhangwenbao.com/overseas-indie-keyword-localization-translation-traps-native-review.html)说的是本地化的分量。 边缘缓存的规则怎么设计,回源率优化的八维决策树 (https://zhangwenbao.com/cloudflare-cache-real-world-optimization-decision-tree.html)给了可照抄的判断路径。 假设你的站按语言返回不同内容,但没有声明。边缘缓存收到第一个请求,来自德国,返回德语页,缓存把它按地址存下来。此后一小时内,所有请求这个地址的人——不管来自哪里、带什么语言偏好——拿到的都是那份德语页。 这个故障有三个特别难查的特征。第一,它是概率性的,取决于缓存过期后第一个请求碰巧来自哪里;第二,它对你自己不可见,你在办公室刷新看到的多半是对的,因为你的请求可能命中另一个边缘节点;第三,它不产生任何错误日志,服务器认为自己正确响应了每一个请求。 用户那边的表现是“网站有时候是德语的”,这句话传到技术这边通常会被当成用户搞错了。等到能稳定复现的时候,往往已经过了很久。 把这个故事记住,后面那些覆盖率数字读起来会不一样:2.2% 这个数不是一个体检指标,它对应的是一类查起来极其费劲的线上故障。 ## 为什么这条声明特别容易漏 因为它和产生变化的那段代码通常不在一起。 本地开发看不见的问题最难防,信息词流量过大的六大危害 (https://zhangwenbao.com/informational-keywords-traffic-dtc-ecommerce-seo-strategy.html)也是上线后才显形。 改动与后果隔得远时要靠记录补上,把变更做成日志的十三类信号 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)是这么做的。 决定返回哪种语言的逻辑,可能写在应用层的中间件里,也可能写在边缘节点的脚本里。而 Vary 这个头,多数情况下是服务器或者CDN自动加的——加的是它自己知道的那部分。 比如压缩这件事是服务器自己做的,所以它会自动补上 Vary: Accept-Encoding。而按语言分发是你的业务代码做的,服务器不知道,也就不会替你补。会自动补的那部分不用你操心,需要你操心的那部分没有任何提示。这就是接下来所有数字的成因。 ## 协商和跳转是两条不同的路 顺便把两种做法的区别说清楚,因为后面会反复用到。 选定之后还要配套一条生产线,从翻译外包到原生再创作的工程体系 (https://zhangwenbao.com/multilingual-content-localization-production-pipeline-vs-translation.html)是那条线怎么搭。 多语言站选哪条路影响很大,多语言站的避坑清单 (https://zhangwenbao.com/international-seo-hreflang-complete-guide.html)把两种做法的代价列清楚了。 一种是内容协商:地址不变,服务器根据请求头当场决定返回哪一版。地址栏里始终是那一个地址,用户看不出发生过选择。 另一种是跳转:服务器看一眼请求头,直接回一个跳转,把人送到 /zh-cn/ 这样的独立地址上。用户能从地址栏看出来自己被送到了哪个版本。 从缓存的角度看,这两条路的性质完全不同。跳转把一个变化的地址拆成了几个固定的地址,每个地址内容唯一,缓存不用分版本;协商把变化留在了同一个地址里,缓存必须靠 Vary 才分得清。 从搜索的角度看,差别更大:独立地址可以被分别收录、分别排名、分别做外链;协商出来的多个版本共用一个地址,搜索引擎只会收录它拿到的那一版。 ## 为什么内容协商用的人越来越少 这套机制写进标准很早,但真正大规模用的场景其实只剩压缩这一项。原因就在上一段:地址唯一在搜索这件事上是负资产,多语言站基本都改用独立地址了。 跨市场的问题正在换形态,为什么hreflang挡不住跨市场知识污染 (https://zhangwenbao.com/international-seo-global-knowledge-integrity-cross-market-ai.html)是新出现的那一类。 判断搬到边缘之后玩法就变了,在CDN边缘改SEO的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)是这一层的入门。 不过它并没有消失,而是换了个位置继续存在——现在做协商的常常不是源站,是边缘节点。边缘按访客所在地区决定给哪一版,这在技术上仍然是内容协商,只是判断依据从请求头换成了来源地址。 这个变化带来一个新问题:来源地址不是一个请求头,你没法用 Vary 声明它。各家CDN因此定义了自己的字段,比如把访客国家写成一个自定义头再放进 Vary。本文样本里有1个站这么做了,是全样本唯一一个把地区分发正确声明出来的。 ## 说了随什么变的有几个,真的在变的有几个? 直接看结果。 服务器这一层要核对的项不止这一个,二十项服务器配置清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以对照着过。 ## 声明侧:92.1% 的站发了Vary,但内容高度集中 139个站里有128个在首页响应里发了 Vary,覆盖率92.1%。乍看很健康。 体验信号也是一组被平台定义的默认,六项体验信号怎么优化与排序 (https://zhangwenbao.com/seo-page-experience.html)是那边的清单。 覆盖率高不等于做对了,资深团队的技术SEO为什么会失灵 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)说的是同一类错觉。 但拆开看令牌就不是那么回事了。 Vary里包含的字段 | 站数 | 占比 | Accept-Encoding | 120 | 86.3% | Cookie | 4 | 2.9% | Accept-Language | 3 | 2.2% | User-Agent | 3 | 2.2% | Origin | 2 | 1.4% | 压缩那一项独占鳌头,其余全是零头。这和上一节说的机制完全对得上:Accept-Encoding是服务器自动补的,其余得靠人写,而人几乎不写。 另外还有一批值得一提的令牌:6个站写了 RSC、Next-Router-State-Tree、Next-Router-Prefetch 这类框架自定义字段,那是前端框架自己加的;1个站写了 CloudFront-Viewer-Country,说明它按访客国家分发并且正确声明了——这是全样本里做得最规范的一个。 ## 写多了会怎样 前面一直在说漏写的危害,写多了也有代价,只是方向相反。 切分维度多了就会稀释,交叉分类的五种优化方法 (https://zhangwenbao.com/shopify-product-cross-classification-seo.html)是控制切分的做法。 切得太碎直接反映在首字节时间上,多层缓存怎么同时影响体验与抓取 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)能看到这条链路。 Vary 里每多一个字段,缓存就要按这个字段的取值再切一层。写 Vary: User-Agent 是最经典的反面例子——用户代理字符串的取值几乎是无限的,每一个细微的版本号差异都会被当成一个新版本,结果是缓存里存了成千上万份几乎一样的副本,命中率趋近于零。 样本里写了这一项的有3个站。它们可能确实按设备返回不同内容,但即使如此,更好的做法也是把用户代理归一化成几档,或者干脆换成客户端提示那一套字段。 Vary: Cookie 同理,4个站在用。Cookie里通常带着会话标识,那是每人一份的,按它切缓存等于给每个访客单独存一份,和不缓存没有区别。 所以这一项的判断标准是:这个字段的取值空间有多大。取值只有几种(比如压缩算法、语言)的可以放心写;取值近乎无限的(用户代理、Cookie)要么归一化,要么别走缓存。 ## 实测侧:17个站确实随语言变 接着看行为。测法是拿同一个地址发三次请求,第一次带英语偏好,第二次带中文偏好,第三次干脆不带这个字段,然后比对三次拿回来的内容。 语言之外货币也会跟着变,把跨市场价格排得像本地店 (https://zhangwenbao.com/currency-formatter-cross-border-price-localization-schema-guide.html)是配套的处理。 同语言多地区最容易出这种事,同一种英语卖到几个市场怎么不打架 (https://zhangwenbao.com/international-seo-same-language-multi-region-en-us-gb-au-duplicate-content-hreflang.html)是配套的处理。 按严格判据统计——只有跳转到了不同地址、页面语言标记不同、标题不同,或者正文体积差超过0.5%,才算真的变了——139个站里有17个(12.2%)确实随语言变,而它们的Vary里都没写Accept-Language。 把两个数放一起:声明随语言变的3个,实际随语言变的17个。而这17个和那3个还不是包含关系——那3个声明了的站里,有的在这次测试中没有表现出差异。 ## 变化的具体形态 17个站里,变化分三类。 换一种语言用户搜的词也变了,跨文化语义与查询语言切换 (https://zhangwenbao.com/multilingual-keyword-research-cross-cultural-localization-query-language.html)是这条线的完整流程。 地址结构变了影响的不只一处,目录层级的六招优化 (https://zhangwenbao.com/impact-of-hierarchical-urls-on-seo.html)可以一起考虑。 跳转规则要和标注对得上,return tags对称与x-default实操 (https://zhangwenbao.com/hreflang-implementation-return-tags-x-default-canonical-mistakes.html)是核对的依据。 第一类是跳到不同地址,有8个:aloyoga.com在带中文偏好时落到 /zh-hans-cn,不带偏好时落到根路径;suitsupply.com从 /en-cn/ 变成 /zh-cn/;rapha.cc从 /us/en 变成 /gb/en;ouraring.com反过来,从根路径跳去 /zh-CN。fiskars.com最有意思,不带语言偏好时它落到了 /fi-fi,也就是芬兰语版——那是这家公司总部所在地,是它内部的默认值。 第二类是地址没变但页面语言标记变了,有4个:canyon.com的 lang 从 en-cn 变成 zh-cn;casetify.com从 en 变成 zh-Hans-cn;mackweldon.com从 en-CN 变成 en-US。 第三类是地址和标记都没变,正文体积明显不同。delonghi.com差了59.36%,aliexpress.com差了51.96%,peakperformance.com差了8.31%。体积差一半以上,基本可以断定返回的是完全不同的一套内容。 ## fiskars那个芬兰语版说明了什么 单独说一下fiskars.com这个例子,因为它把缺省这件事演示得特别完整。 兜底语言这件事在异常页上更明显,撞上404那一刻本地化就管不到了 (https://zhangwenbao.com/minor-language-error-page-fallback-language.html)是同一个机制。 默认值来自组织内部这件事很常见,本地化数据看着有的多半是借的 (https://zhangwenbao.com/minor-language-locale-data-inheritance.html)是另一个形态。 带英语偏好请求时,它落在 /en-en;把语言偏好这个字段整个去掉之后,它落到了 /fi-fi,芬兰语版。 这家公司总部在芬兰。也就是说,当请求没有表达任何偏好时,系统给出的是组织内部的那个默认值,而不是覆盖面最广的英语版。 这个设计从公司内部视角看完全合理——不知道你是谁的时候,先按自己家的来。但从访客视角看,一个不带语言偏好的请求最可能来自脚本、爬虫或者简易客户端,而它们拿到的是芬兰语版。 类似的还有aloyoga.com、glossier.com、liquiddeath.com这三个:带中文偏好时落在带地区后缀的路径上,不带偏好时落到根路径。去掉一个字段就换一个版本,而这件事在任何一份对外文档里都查不到。 ## 那3个声明了随语言变的站 公平起见也看看做对的那边。样本里有3个站在 Vary 里写了 Accept-Language,另有1个站用自定义字段声明了按访客国家分发。 跨语言对齐做对的站都是修出来的,实操对不上的五大根因 (https://zhangwenbao.com/multilingual-entity-seo-cross-lingual-reconciliation.html)是那些坑的清单。 做对的通常是修过的,五百个站实测排出来的优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)也是从事故里排出来的。 有意思的是,这3个站在本次测试中并没有表现出语言相关的差异——它们声明了会变,实测没变。 这不算错,反而是更保守的做法:声明的范围比实际变化的范围大,缓存会切得碎一点、命中率低一点,但绝不会串版本。宁可多声明也不要少声明,这个方向上的偏差代价是性能,另一个方向上的偏差代价是给错人。 把这四个站放在一起还能看出一件事:真正把这件事想明白的站,通常是那些做了多市场业务、并且在缓存上吃过亏的。正确的配置往往不是设计出来的,是修出来的。 ## 从64收到17,中间那47个是怎么回事? 这一节讲测量本身,因为第一版尺子给出的数字是64,是最终数字的3.8倍。 口径没定死结论就会飘,从指标体系到异常诊断 (https://zhangwenbao.com/seo-data-analysis-guide.html)是先把口径立住的做法。 ## 第一版判据错在哪 最初的判法很直觉:把两次响应的正文做个指纹,指纹不同就算变了。为了避开页面里的随机串,先用正则把长十六进制串、纯数字时间戳、nonce 属性都替换掉再算。 页面内容是否稳定影响一切测量,四种渲染模式下能读到多少 (https://zhangwenbao.com/ai-search-skips-spa-rendering-passage-level.html)是前置问题。 换台设备结果就变的问题同理,排名监测对不上的六大原因 (https://zhangwenbao.com/rank-tracking-methodology-traps-share-of-voice.html)也是测量方法本身出的错。 结果是64个站(46%)指纹不同。这个数字当时看着很爽——将近一半的站在静默变体。 然后翻明细,发现一大批长这样:assos.com 正文不同(558833 -> 558833)。指纹不同,字节数一个不差。 字节数完全相同而内容不同,唯一合理的解释是页面里有等长的随机值——某个会话标识、某个请求追踪号、某个防重放令牌,长度固定,每次生成都不一样。那一版正则只清掉了几种常见形态,剩下的没清干净。 ## 换成什么判据 改成只认四类硬证据:跳转后的最终地址不同、html 标签上的 lang 属性不同、页面标题不同,或者正文体积差超过0.5%。 标题这类字段稳定又有语义,H1与页面标题的关系 (https://zhangwenbao.com/h1-page-title-relationship-multiple-h1-seo-design.html)说明了它为什么可靠。 指标要有唯一来源才不会各说各话,一套靠得住的五大指标 (https://zhangwenbao.com/seo-metrics-layer-single-source-of-truth-data-governance.html)给了治理框架。 这四类都有一个共同点:它们不可能由随机串造成。随机串不会改地址,不会改语言标记,不会改标题,也不会让体积差出半个百分点以上。 换判据之后数字从64掉到17。收缩得很厉害,但17这个数是站得住的——每一个都能点开具体差异看到实证。 ## 为什么第一版数字看着更像真的 补一句当时的心理过程,因为它比技术细节更值得留意。 想验证一个因果就得设计实验,哪条外链真撬动排名的六步实验设计 (https://zhangwenbao.com/backlink-attribution-experiment-design-rank-uplift.html)是可迁移的方法。 符合预期的数字最不该轻信,核心指标解析的四个常见错误 (https://zhangwenbao.com/google-analytics-metrics-misuse-guide.html)都是这么来的。 46% 这个数出来的时候,保哥第一反应是“果然有这么多”。它和事前的预期完全吻合——大家都不写Vary,所以静默变体应该很普遍。一个符合预期的数字,是最不容易被检查的数字。 促使去翻明细的其实是另一件事:本来想在文里举几个具体例子,需要点名几个站。一翻就看到了那批字节数完全相同的记录。 也就是说,发现错误靠的不是审慎,是恰好需要举例子。如果这篇文章只打算给一个百分比,那个错误数字会原封不动地留下来。 这件事之后加了一条习惯:任何一个要写进结论的比例,都必须能点出三个具体样本,并说清楚它们各自为什么被算进去。举例子这个动作本身就是校验。 ## 这件事本身的教训 这已经是做这类实测时第二次栽在尺子上了。上一次是特征匹配串写得太短造成误判,这一次是噪声没清干净造成虚高。 对账这件事要有固定动作,埋点归因看板的七个动作点 (https://zhangwenbao.com/data-analyst-seo-reconciliation-7-actions.html)是一份可执行的清单。 该退的指标不退就会继续误导,九个该淘汰的SEO指标 (https://zhangwenbao.com/retire-outdated-seo-metrics-2026-strategy.html)是同一种清理。 共同点是:两次都是尺子偏向于报告更多的问题,而更多的问题看起来更像成果。如果不去翻明细,64这个数会被直接写进结论,而且没人会质疑——毕竟它符合大家对这类问题的预期。 所以做完任何一轮自动统计,都要抽样翻原始记录。判断标准很简单:随便抽三条,能不能一条条讲清楚它为什么被算进来。讲不清楚的,说明尺子有问题,不是样本有问题。 顺带说一句,宽判据那64个也不是全无价值。它说明将近一半的站每次返回的字节都不完全一样,也就是这些页面在响应层面不具备可重复性——这对想做逐字节比对的监控是个前提条件,得先把噪声字段排除掉。 ## 虚高的数字为什么总是往同一个方向偏 再深挖一层:为什么两次栽跟头,尺子都是偏向报告更多问题,而不是更少? 口径切错方向结论就反了,品牌词与非品牌词为什么要分开算 (https://zhangwenbao.com/branded-vs-non-branded-keyword-strategy.html)是同一类切分问题。 报表被污染也是单向偏的,机器流量怎么揪出来再拦掉 (https://zhangwenbao.com/spam-traffic-ga4-detect-filter-prevent.html)是把噪声先剔掉的做法。 原因在于这类检测的构造方式。你写的是一个“找不同”的程序,它的默认输出是“有差异”,只有当两边完全一致时才输出“无差异”。任何一个没考虑到的干扰因素,都会让结果落在“有差异”那一边。误差不是随机的,它有方向。 反过来,如果程序写成“找相同”,比如只在满足某几个具体条件时才判定有问题,那漏报会多、误报会少。两种写法各有代价,关键是知道自己用的是哪一种,误差往哪边偏。 更麻烦的是心理层面。报告更多问题的结果看起来更像成果,而看起来像成果的东西,人是不会主动去质疑的。这一点比技术上的疏忽更值得警惕,因为它会让你在有机会发现错误时选择不去看。 可用的对策只有一个,而且很土:每轮统计跑完,从结果里随机抽三条,逐条讲清楚它为什么被算进来。讲不清楚就是尺子的问题。这一步花不了十分钟,本文两次纠错都是靠它。 ## 压缩这一层的默认协商 语言那条线讲完,看另一条更基础的:压缩。 体积直接决定加载表现,页面速度到底怎么影响排名 (https://zhangwenbao.com/page-speed-seo.html)给了优先级排序。 ## 带上压缩偏好时给什么 正常浏览器请求都会带 Accept-Encoding,声明自己能解gzip、br之类。这次的第一个变体就是这么发的,结果是: 体积只是性能的一环,六层架构把加载时间压下来的实操 (https://zhangwenbao.com/woocommerce-performance-6-layer-lcp-core-web-vitals-real-path.html)是完整路径。 压缩这件事还能在应用层再做一层,免插件压缩与压缩算法叠加 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)是具体写法。 返回的编码 | 站数 | 占比 | br | 97 | 69.8% | gzip | 40 | 28.8% | 不压缩 | 2 | 1.4% | br是主流,接近七成。这个比例比几年前高很多,主要是各家CDN把它做成了默认。又一个不用你操心的缺省,而且是往好的方向缺省的。 ## 不带压缩偏好时给什么 第二个变体把这个头去掉了。结果非常整齐:137个站全部返回不压缩的内容,没有一个例外。 移动端对体积最敏感,十大致命错误与修复 (https://zhangwenbao.com/mobile-seo-mistakes-2026.html)里有几条正是这个。 弱网下体积的影响会被放大,低端机与弱网的移动端性能优化 (https://zhangwenbao.com/overseas-weak-network-low-end-phone-mobile-performance-optimization.html)讲的就是这类场景。 这是标准要求的行为——客户端没声明能解压缩,服务器就不该压。整齐到没有例外,说明这一层的实现是各家服务器软件自带的,没人动过。 有意思的是体积。不压缩与压缩的体积比,中位数是6.44倍。也就是说一个压缩后200 KB的首页,原始体积在1.3 MB上下。 这个倍数值得记一下,因为它是判断某些异常的参照。如果你在日志里看到某个客户端拉走的字节数是常规的六七倍,多半不是它在攻击你,而是它没带压缩偏好——一些老旧的抓取脚本和简易的监控探针就是这样。 ## 17个站的编码变了却没声明 把两个变体的 Content-Encoding 一比,有17个站的编码确实随请求变,而它们的Vary里没有Accept-Encoding。名单里有aboutyou.com、temu.com、swarovski.com、philips.com、onepeloton.com这样量级不小的站。 多层处理是这类丢失的温床,六层缓存与边缘路由的实战配置 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)能看清各层职责。 这类问题要从网络层往下查,从DNS、线路到CDN的排障顺序 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)是可用的路径。 这一类的风险比语言那一类更直接:如果中间有一层缓存把不压缩的版本存了下来,后面所有带压缩偏好的请求都会拿到未压缩的内容,体积直接涨六倍多。页面看着一切正常,只是慢了,而且慢得没有道理。 为什么这17个站会漏?边缘配置改错一处就足以让实际交付和预期对不上 (https://www.seroundtable.com/misconfigure-cloudflare-seo-41865.html),大概率是响应经过了不止一层:源站发出时带了Vary,某一层代理或者边缘脚本重写了响应头,把它丢了。这种丢失在任何一层单独看都是正常的,只有把首尾两端接起来看才发现少了东西。 ## 一次真实的排查:慢,但慢得没道理 这类问题在实际项目里长什么样,举个保哥经手过的例子。 查这类问题日志要留得住,日志轮转与检索不爆盘的配置 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)是前置工作。 这类问题通常卡在前端与运维之间,前端工程师的七个协作动作点 (https://zhangwenbao.com/frontend-engineer-seo-collaboration-7-actions-semantic-cwv-render.html)能减少扯皮。 一个做家电配件的独立站找过来,说欧洲用户反馈页面加载慢,但监控里的各项指标都正常。第一轮查下来确实找不到毛病:服务器响应时间没问题,图片也压过,边缘节点覆盖也够。 后来是在浏览器的网络面板里注意到,主文档的传输体积和资源体积几乎一样大——也就是没压缩。而同一个页面在办公室打开是压缩过的。 顺着这条线查到边缘层:他们前段时间加了一段脚本给响应补安全头,那段脚本用的是整体替换响应头而不是追加,把源站发的 Vary 冲掉了。缓存于是不再区分压缩版本,某个节点存了一份未压缩的副本,此后就一直发这一份。 改动很小,把替换改成追加,加上一行把原来的 Vary 保留下来。但从用户反馈到定位原因中间隔了三周,因为所有常规监控指标都是正常的——服务器确实很快,只是发出去的东西大了六倍。 ## 一个都没有出现的编码 这次请求里声明了能解br、gzip、deflate,没有声明zstd。而实际返回里zstd一个都没有出现,全是br和gzip。 规则不合就静默降级,八大类规则一键扫出不合规的地方 (https://zhangwenbao.com/amp-validator-mobile-amp-html-compliance-guide.html)是另一处同样的静默。 能力申报决定拿到什么,抓取和渲染分几步走 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)里也有同样的机制。 这个结果本身在意料之中——服务器只会从你声明能解的那几种里挑。但它顺带演示了内容协商最基本的一条规则:你没说自己能接受的,服务器就不会给。能力是客户端主动申报的,服务器不会去猜。 这条规则的另一面是,如果你的客户端申报能力时漏了什么,你就永远拿不到那种形式的响应,而且不会有任何提示。这在写抓取脚本时是个常见的坑:默认不带压缩声明,然后被自己拉走的流量吓一跳。 ## 压缩比这个数还能用来做什么 6.44倍这个中位数值得多说一句,因为它比想象中有用。 字节数最后要折成资源账,页面碳足迹与爬虫抓取的同一套规范 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)换了个角度算同一笔。 体积在抓取那边也有硬上限,抓取正文只读前两兆 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)是必须知道的一条。 首先它能反推页面里冗余的量。文本压缩靠的是重复模式,压缩比越高说明重复越多。一个能压到六分之一的页面,意味着它的HTML里有大量重复结构——重复的类名、重复的内联样式、重复的属性。 其次它是判断某些性能问题的快速参照。如果一个页面的压缩比明显低于这个区间,比如只有两三倍,那多半是页面里塞了大量内联的图片数据或者已经压过一遍的内容,这类东西再压也压不动。 最后它能帮你估算流量账。把日志里的字节数除以六,才是这些请求真正对应的内容量;反过来,如果发现某类请求的字节数没除以六还偏高,那就是没走压缩的那一批。 ## 不写Cache-Control的那30个站,缓存怎么办? 顺着缓存这条线再往下一层。 应用层的缓存同样要显式配置,对象缓存的原理与运维 (https://zhangwenbao.com/redis-object-cache-wordpress-persistent-cache-hit-rate-operations.html)是另一层的同类工作。 ## 21.6% 的站没有这个头 139个站里,30个(21.6%)的首页响应完全没有 Cache-Control。 先把该测的测起来,三类工具与追踪习惯 (https://zhangwenbao.com/seo-data-concept.html)是入门的顺序。 不配置就走默认这件事到处都是,字节码缓存怎么调才真的快 (https://zhangwenbao.com/php-opcache-bytecode-cache-tuning-preload-jit-hit-rate.html)是又一个例子。 没有这个头,缓存不会因此就不缓存,它会走启发式规则:按修改时间与当前时间的差值取一个比例当作可缓存时长 (https://www.rfc-editor.org/rfc/rfc9111.html),常见取10%。一个上周改过的页面,就可能被缓存好几个小时。 而这次的样本里,带 Last-Modified 的只有17个站(12.2%)。既没有 Cache-Control 又没有 Last-Modified 的情况下,各家缓存的处理并不一致,有的不缓存,有的给一个很短的默认值。 这是本文里最纯粹的一个缺省分支:你什么都没说,于是每一层缓存各自决定了一个值,而这些值你既不知道也不一致。 ## 写了的那109个站写了什么 剩下109个站的取值分布很说明问题。 首页承担的转化任务决定了它的策略,双轴八模块九十天实战 (https://zhangwenbao.com/high-conversion-ecommerce-cro-seo-90day-playbook.html)能看到取舍来自哪里。 不缓存的代价最终体现在体验指标上,行业基准与投入产出测算 (https://zhangwenbao.com/core-web-vitals-ai-search-industry-benchmark.html)可以拿来算这笔账。 Cache-Control取值 | 站数 | private, no-store | 36 | no-cache, no-store, must-revalidate | 9 | public, max-age=0, must-revalidate | 12 | no-store, no-cache, must-revalidate, max-age=0 | 4 | no-cache, no-store, max-age=0, must-revalidate | 3 | 把这几行读一遍会发现一个共同点:绝大多数都是各种写法的“别缓存”。首页作为一个高流量入口,被明确要求每次都回源。 原因不难理解:首页上有购物车数量、有会员状态、有个性化推荐,缓存一份发给所有人是要出事的。所以大家选了最安全的做法——干脆不缓存。 但这个选择的代价是每一次首页访问都要打到源站。如果Vary这套机制被正确使用,本来是可以做到既缓存又分版本的,只是那需要把随什么变这件事想清楚并且写下来,比统一no-store麻烦得多。 ## ETag有一半的站在发,它派什么用场 样本里 ETag 的覆盖率是51.8%,比 Last-Modified 的12.2% 高出一大截。 修改时间这类字段在别处也要写对,两千四百个站踩过的sitemap坑 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)里有相关的一条。 验证机制是否真的生效要看实测,三平台三百站的收录实测 (https://zhangwenbao.com/seo-kpi-guide.html)是同一种验证思路。 这两个字段解决的是同一件事:让客户端下次请求时能问一句“我手上这份还能用吗”,服务器如果说能用,就回一个很短的响应,正文一个字节都不用传。 ETag 覆盖率高的原因和前面那条规律一致——它是服务器根据响应内容自动算出来的,不需要人参与;而 Last-Modified 需要知道内容的修改时间,动态页面没有这个概念。 不过要注意一个坑:如果一个站有多台服务器,各自算出的 ETag 可能不一样,那么同一份内容在不同服务器上会被当成不同版本,验证永远失败,这个机制就白装了。多机部署时要么统一算法,要么干脆关掉它,别留着一个永远命中不了的验证器。 ## 缓存命中率的实际情况 响应里还能读到缓存层的命中状态。这次能读到的分布是:DYNAMIC 77个、HIT 18个、MISS 19个、BYPASS 2个,另外 Age 头出现在32个站(23%)。 回源多了抓取那边也会受影响,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)是关联的一头。 命中率低通常是配置没打通,索引器、缓存与反向代理调优 (https://zhangwenbao.com/magento-2-performance-tuning-indexer-cache-redis-varnish-production-mode.html)是排查的顺序。 DYNAMIC 的意思是这个响应压根不进缓存,边缘层直接转给了源站。77个站,超过一半。这和上面 no-store 占多数是同一件事的两面。 ## 首页不缓存,不等于整站都不该缓存 这里有个容易被顺手带过去的问题:很多站把首页设成 no-store 之后,同一套策略被应用到了全站。 把个性化那块单独拆出来是关键,首屏内容怎么影响SEO (https://zhangwenbao.com/above-the-fold-content-seo-page-layout-mechanism.html)讲的是同一块区域。 首页的特殊性不止在缓存上,首页首屏怎么设计才留住人 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)是另一头的讲究。 但首页和内页的性质完全不同。首页有购物车数量、有个性化推荐,确实因人而异;而一个商品详情页、一篇博客文章、一个帮助文档,绝大多数内容对所有人是一样的,个性化部分往往只是页头的那一小块。 把整站按首页的标准设成不缓存,等于为了页头那一块状态放弃了整页的缓存收益。更合理的做法是把因人而异的那一小块拆出来单独请求,页面主体正常缓存。 判断方法很直接:把一个内页用两个不同的会话打开,逐段比对哪里不一样。如果只有页头几个数字不同,那这页是可以缓存的。这个比对花不了十分钟,而它决定的是这个站有没有边缘缓存这件事。 ## Age头能告诉你什么 顺带说说 Age 这个字段,样本里23% 的站发了它。 看懂一个指标要先知道它怎么算出来的,从建项目到看懂核心指标 (https://zhangwenbao.com/ahrefs-beginner-guide.html)是同一种读法。 想看某个时点的页面长什么样,缓存退役后历史快照还能怎么查 (https://zhangwenbao.com/webpage-cache-snapshot-viewing-tools-guide.html)列了几个工具。 它的含义是这份响应在缓存里已经待了多少秒。数值大说明这份副本很旧、缓存命中率高;一直是0或者根本没有这个头,说明每次都是新取的。 它的实际用途是当作缓存策略的验证器:你设了一小时的缓存时长,那么反复请求同一个地址,Age 应该在0到3600之间爬升,然后归零。如果它始终是0,说明缓存没生效,得回去查是不是被某个头挡住了。 这一项和前面讲的 Vary 是一对:Vary 决定缓存怎么分版本,Age 告诉你分完之后有没有真的命中。只看配置不看 Age,你不知道自己的缓存策略是不是纸上谈兵。 ## 首次请求就写下的778条Cookie,是谁写的? 换一个维度看缺省。这一次不是响应内容,是响应带来的副作用。 要管住这些东西得先有个管控平台,四家主流同意管理工具横评 (https://zhangwenbao.com/cmp-consent-management-platform-selection-cross-border.html)是选型的起点。 ## 85.6% 的站在第一次请求就发Cookie 这次的请求是干净的:没有历史Cookie,没有登录态,没有任何交互,就是一次首页GET。 前端这类提示的默认状态也该管,评论Cookies提示的汉化与默认勾选 (https://zhangwenbao.com/save-my-name-email-and-website-in-this-browser-for-the-next-time-i-comment.html)是个小而具体的例子。 同意横幅和数据采集怎么共存,同意模式下的出海合规架构 (https://zhangwenbao.com/seo-legal-compliance-gdpr-ccpa-consent-mode-cross-border-architecture.html)给了完整方案。 结果139个站里有119个(85.6%)在这次响应里就写下了Cookie,条数中位是7条,最多的一个站写了39条,全样本合计778条。 写得最多的几个:weber.com 39条、theordinary.com 24条、suitsupply.com 19条、cybex-online.com与joolz.com各18条。 ## 这些Cookie是干什么的 把名字汇总去重排个频次,前几位非常整齐。 每装一个工具就多一批痕迹,两种安装方式的取舍 (https://zhangwenbao.com/shopify-microsoft-clarity.html)里能看到它带进来什么。 装的应用越多留下的东西越多,应用栈精简与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)是清理的做法。 Cookie名 | 出现站数 | 用途 | _shopify_essential | 96 | 店铺平台必需会话 | localization | 53 | 记住地区选择 | cart_currency | 52 | 记住货币 | _shopify_y / _shopify_s | 各46 | 访客与会话标识 | _shopify_analytics / _marketing | 各45 | 分析与营销归因 | __cf_bm | 26 | 边缘层机器人识别 | 这份名单里几乎没有站主自己写的东西。它们全部来自建站平台和边缘服务商,是开店和接入CDN时自带的。 顺带说一个数字上的意外:_shopify_essential 出现在96个站,而前一轮从robots.txt文件特征识别出的同平台站点只有65个。两个探针给出的平台占比差了将近一半。原因是有些站改写了robots.txt,指纹认不出来,但Cookie骗不了人。这也算一个小的方法论提醒:判断技术栈别只用一个探针。 ## 为什么这份名单里几乎没有自己写的东西 值得停下来想一下:为什么778条Cookie里,站主自己写的凤毛麟角? 平台替你决定的东西还有很多,集合页没有产品时的三种场景 (https://zhangwenbao.com/seo-empty-shopify-collections.html)是另一个例子。 平台替你做了很多决定,在这套系统上同时做好搜索与AI优化 (https://zhangwenbao.com/shopify-seo-ai-optimization-playbook.html)是接受这个前提之后的打法。 不是因为大家不需要存状态,而是因为需要存的那些状态,平台已经替你存好了。购物车、货币、地区、会话——这些是电商的通用需求,平台把它们做成了默认能力。 这本身是好事,它意味着你不用重复造轮子。但它带来两个后果。一是你对这些状态的控制力其实很弱,改名、改有效期、改作用域都得看平台支不支持;二是当出问题时,你需要先搞清楚这条Cookie是谁的,而这件事没有现成的对照表。 所以做一次盘点是值得的:把首次响应的Cookie名字列出来,逐条查它属于哪个系统。查的方法很土,搜名字就行——这些名字在各家文档和社区里都能找到。 盘完之后你会得到一份自己站上的状态地图。它的价值不在盘的那一天,而在半年后某次排查会话丢失问题时,你能立刻知道该看哪一条。 ## Domain属性没写的有537条 778条Cookie里,537条没有写 Domain 属性。 身份打不通归因就会错,多触点归因模型怎么选 (https://zhangwenbao.com/dtc-multi-touch-attribution-model-selection.html)是这条链路的下一步。 跨子域的身份打不通会毁掉分析,服务器端跟踪还原完整链路的八步 (https://zhangwenbao.com/dtc-ga4-bigquery-user-journey-stape-server-side.html)是修复方向。 不写会怎样?缺省是只作用于发出它的那个主机名,不包含子域 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie)。写了 Domain=.example.com,才会在所有子域之间共享。 这个缺省方向是安全的——不写等于范围更小。但它也意味着如果你的站有多个子域,不写这一项的Cookie在子域之间是不通的。购物车在 shop.example.com 上,博客在 blog.example.com 上,两边的会话标识各是各的,跨子域的行为分析会看到两个不相干的访客。 安全属性方面:778条里带 Secure 的488条,带 HttpOnly 的313条。SameSite 的取值分布是 Lax 323条、None 246条、Strict 只有1条。Lax 排第一,正是因为它是现代浏览器不写这一项时的缺省值——写与不写结果一样,所以大家更愿意显式写出来。这算是本文唯一一个大家把缺省显式化做得不错的地方。 ## 安全属性的覆盖率说明了什么 778条里带 Secure 的488条、带 HttpOnly 的313条,占比分别是62.7% 和40.2%。 比例数字要结合意图读,合规边界与决策红线 (https://zhangwenbao.com/black-hat-white-hat-gray-hat-seo-comparison-risk-decision-line.html)也是靠意图划线的。 安全项要看具体用途再判断,八类内网地址绕过的修补 (https://zhangwenbao.com/http-php-file-wp_http_validate_url-function-in-wordpress-to-verify-improper-loopholes-in-input-ip.html)也是一条条看出来的。 这两项的差距有它的道理。Secure 限制这条Cookie只在加密连接上发送,几乎没有副作用,平台默认打开的多;HttpOnly 禁止页面脚本读取它,而很多Cookie恰恰就是给前端脚本用的,比如记住地区选择、控制弹窗显示,加上这个属性就用不了了。 所以40.2% 这个数不是“有六成没做好”,而是“有六成本来就要给脚本读”。这类比例数字必须结合用途来读,否则很容易得出一个听着吓人但没意义的结论。 真正该关心的是那些明显属于会话或者身份的Cookie有没有这两项。这份判断没法靠统计得出,得逐条看名字——而这正好又绕回前面那件事:先有一份自己站上的Cookie清单,后面所有判断才有依据。 ## 第三方域的Cookie只有4个站 按域归类之后,含第三方域Cookie的站只有4个,其余115个全是第一方。 第三方追踪失效之后要重建链路,九招重建接口与投放回报 (https://zhangwenbao.com/dtc-meta-ads-ios14-attribution-rebuild.html)是那条路的做法。 第三方脚本留下的痕迹不止Cookie,第三方统计图标的现代处理与合规 (https://zhangwenbao.com/hidden-third-party-website-statistics-icons.html)是另一处。 这个结果比预期干净,原因是首次请求还没触发那些延迟加载的第三方脚本。要看真实的第三方Cookie数量,得在浏览器里跑完整个页面生命周期,而不是一次纯请求。这也是这份数据的口径边界,得说清楚。 ## 七条Cookie意味着每个请求多带多少字节 Cookie有一个常被忽略的成本:它们会被带在此后每一个同域请求的请求头里,包括图片、脚本、样式表。 首屏的每一点开销都要算,搜索框从入口到结果的四层拆解 (https://zhangwenbao.com/site-search-bar-ux-design-conversion.html)是另一个高价值入口。 第三方脚本对性能的拖累是叠加的,五个场景的弃用接口治理 (https://zhangwenbao.com/psi-deprecated-api-third-party-tracker-pagehide-fix.html)是逐个拆的过程。 按这次的中位数7条算,一条平均几十字节,加起来一个请求要多带几百字节。一个页面加载过程中如果有一百个同域请求,光Cookie就是几十KB的上行流量。上行带宽通常比下行小得多,这部分开销对移动端首屏的影响比多数人以为的大。 写了39条的那个站,情况会明显一些。这类问题的解法通常是把静态资源放到一个独立域名下——不同域,Cookie就不会被带过去。这是Cookie那个 Domain 缺省行为的一个正面用法:默认不跨域,正好帮你隔离。 ## 同意条弹出之前就已经写好了 还有一层要说清楚:这778条Cookie是在第一次请求的响应里就下发的,也就是用户还没看到页面、更没点过任何同意按钮的时候,它们已经在浏览器里了。 弹窗时机与合规是同一件事,时机、字段与移动端合规实战 (https://zhangwenbao.com/email-popup-lead-capture-opt-in-conversion-guide.html)给了具体做法。 这类问题最终要法务来定边界,隐私合规与应答的七个动作点 (https://zhangwenbao.com/legal-counsel-seo-collaboration-7-actions-privacy-trademark-incident.html)是配套的分工。 这在合规上不是自动出问题,因为各地规则通常对严格必要的那一类留了口子——会话标识、购物车、安全防护都属于必要范围。样本里排在前面的几条大多能归到这一类。 但排在后面的那些就未必了。名单里明确带分析和营销字样的字段出现在四十多个站上,这一类通常不在必要范围内。它们出现在同意之前,多半不是有意为之,而是平台默认打开、没人去关。 该做的事很简单:把首次响应的Cookie清单导出来,逐条标注它属于哪一类,不属于必要类的挪到同意之后再写。这件事的难点从来不是技术,是没人知道首次响应里已经写了这么多条。 ## 一次响应里36个头字段,你认识几个? 把镜头再拉远一点,看看一次普通的首页响应到底带回来多少东西。 技术审查要多看几层,从AI爬虫到无障碍的五个新层面 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)是重新划分之后的清单。 ## 中位36条,最多235条 139次响应里,头字段条数的中位是36,最少的一个站只有10条,最多的一个站有235条。 响应里还有一大块是结构化数据,一百二十八种类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)是那边的取舍。 层数一多就得靠自动化守住,把配置纳入持续集成的做法 (https://zhangwenbao.com/seo-automation-engineering-ci-maintenance-architecture.html)是治本的那一档。 全样本出现过的不同字段名有272种。其中标准定义的只是一小部分,剩下大量是各家平台、CDN、安全产品、前端框架自己加的。 ## 覆盖率最高的那一批 响应头 | 覆盖率 | 谁加的 | Content-Encoding | 98.6% | 服务器自动 | Server | 92.8% | 服务器自动 | Vary | 92.1% | 服务器自动为主 | Strict-Transport-Security | 90.6% | 平台或人工 | Set-Cookie | 85.6% | 平台自动 | X-Content-Type-Options | 80.6% | 平台或人工 | Cache-Control | 78.4% | 需要人工 | Content-Security-Policy | 67.6% | 需要人工 | ETag | 51.8% | 服务器自动 | Last-Modified | 12.2% | 需要人工或静态文件 | 从主机到插件的默认值一样要过一遍,从主机、插件到体验指标 (https://zhangwenbao.com/wordpress-seo-guide.html)是那套系统的清单。 开发期就该定下来的那些项,十大优化要点清单 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)列得比较全。 这张表按覆盖率排下来,正好呈现出一条规律:自动加的都在九成以上,需要人写的掉到七成以下,需要人写且没有默认模板的掉到一成多。 这条规律和上一轮在robots.txt上看到的完全一致——平台默认写得挺全,自定义的那部分才是缺口所在。 ## 头字段数量的两端分别是什么站 中位36条,最少10条,最多235条。这个跨度本身有信息量。 架构简单与功能丰富之间要选一头,九个维度的选型对比 (https://zhangwenbao.com/responsive-web-design-seo.html)把代价摆出来了。 架构选型直接决定要自己搭多少,基建得自己重搭的那几样 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是选之前该知道的。 只有10条的那一端,通常是把静态文件直接放在对象存储或者简单静态托管上的站。没有应用层、没有安全模块、没有会话,响应头就是最基本的那几个。这类站的行为最可预测,因为几乎没有东西在中间做决定。 235条的那一端则是经过了多层处理的:源站加一批、应用框架加一批、安全产品加一批、边缘节点再加一批诊断字段。层数越多,前面说的“某一层重写时丢了东西”的概率就越高。 这两端之间存在一个真实的取舍:功能越多、层次越多,能力越强,但行为的可预测性越差、需要实测的维度越多。没有哪一端天然更好,但至少要知道自己在哪一端,以及这意味着要做多少验证工作。 一个快速自查:数一下自己首页响应的头字段条数。明显超过样本中位数的话,说明你的响应经过的处理层比多数同行都多,那么本文讲的这套实测对你的价值也更大。 ## 边缘层是谁 顺手记一下这批站的边缘归属:Server 头里cloudflare占62.6%(87个站),netlify 6个,cloudfront 5个,vercel 5个,tengine 4个。按CDN特有的指纹头统计,Cloudflare 90个、CloudFront 13个、Fastly 8个、Vercel 8个、Akamai 1个。 不同入口拿到的东西也不一样,隐私搜索引擎要不要单独做 (https://zhangwenbao.com/privacy-search-engines-seo-duckduckgo-brave-ecosia.html)是另一个分岔。 托管选型也是这一层的一部分,国内主机还是国外主机的取舍 (https://zhangwenbao.com/china-vs-overseas-hosting-for-cross-border-independent-site.html)有具体判断。 HTTP版本上,133个站走HTTP/2,只有6个还在HTTP/1.1。Content-Type 里带 charset 的115个(82.7%),没带的24个——不带的话浏览器要靠猜,虽然现代浏览器猜得挺准,但这仍然是一个把决定权交出去的缺省。 ## 64% 的站宣告了下一代协议,这次一次都没用上 这里有个特别能说明问题的对照。 两端约定不一致就会退回默认,三类跳转方案对比 (https://zhangwenbao.com/mobile-terminal-access-pc-website-automatically-jump-to-mobile-website.html)里也有同样的协商过程。 两端能力不一致导致结果不同,移动端与桌面端排名差异的六大因素 (https://zhangwenbao.com/mobile-desktop-ranking-differences.html)是同一种成因。 响应头里有个字段叫 Alt-Svc,作用是告诉客户端“我还支持另一种更快的连接方式,下次可以试试”。样本里89个站(64%)发了这个字段,宣告支持HTTP/3。 而实际连接统计是:133个走HTTP/2,6个走HTTP/1.1,HTTP/3一个都没有。 原因不是这些站在说谎,是这次用的客户端默认不启用那个协议。服务器宣告了能力,客户端没接这个话,于是双方退回到都支持的那一档。 这个例子和前面的zstd是同一件事的两面:一边的能力宣告,加另一边的能力申报,交集才是实际发生的行为。只看任何一边都会得出错误结论——只看服务器会以为大家都在用新协议,只看客户端会以为服务器不支持。 ## 272种字段名里,有多少是给人看的 272这个数字里,标准定义的字段大概占几十个,剩下两百多个全是各家自定义的。 该关掉的能力就关掉,五种环境禁掉目录执行权限的写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是同一种收敛。 暴露版本信息是要处理的,版本隐藏与访问控制实战 (https://zhangwenbao.com/apache-server-security-hardening-version-hide-directory-access-control-waf.html)给了具体做法。 它们大致分三类。一类是诊断信息,比如请求追踪号、处理它的节点编号、耗时统计——这些是给服务商自己排障用的。一类是安全产品加的标记。还有一类是前端框架为了自己的路由机制加的,样本里那6个写了 Next-Router-State-Tree 的站就属于这一类。 对站主来说,这些字段绝大多数不需要关心。但有两件事值得做一次:一是检查有没有暴露内部信息的字段,比如具体的框架版本号、内网主机名、后端服务名;二是估一下这些头字段的总字节数,中位36条,最多那个站235条,后者的响应头体积已经能和一个小图标相提并论了,而且每个请求都要发一遍。 ## 安全头那一组的覆盖率为什么高 顺带看一眼安全相关的几项:Strict-Transport-Security 90.6%、X-Content-Type-Options 80.6%、Content-Security-Policy 67.6%、X-Frame-Options 62.6%。 容易做的先做完再看别的,九个被低估的技巧 (https://zhangwenbao.com/underrated-google-seo-tips.html)里有几条也是低成本高回报。 有一键方案的项覆盖率总是高,落地页体验的及格线 (https://zhangwenbao.com/baidu-landing-page-experience-search-quality-whitepaper-guide.html)也是被平台规则推着做起来的。 这几个数明显高于 Cache-Control 的78.4% 之外的其他人工项,原因很简单:它们在主流平台和CDN的控制台里是一个开关,点一下就全站生效。 反过来看 Last-Modified 只有12.2%,因为它没法一键开——它需要服务器知道这份内容什么时候改的,而动态生成的页面根本没有这个概念。 所以覆盖率高低基本等于“有没有人做成一键开关”,和这项配置本身重不重要关系不大。这条规律在评估任何一份行业统计时都用得上:先问这一项是不是有默认或者一键方案,再看数字。 ## 这些不成文的缺省,到底是谁定的? 把前面几节的结果并到一起看,会发现这些行为的来源相当集中。 平台层的坑跨系统是相通的,建站第一年最容易失分的十二项 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验。 ## 三个来源,各管一段 第一个来源是建站平台。它决定了Cookie写几条、叫什么名字、有没有 Secure;也决定了首页默认的缓存策略是不是 no-store。这一层的特点是全平台统一,你和用同一套系统的几万家店拿到的是同一份行为。 换一层底座要有回滚预案,十二步迁移与回滚演练 (https://zhangwenbao.com/woocommerce-hpos-migration-rollback-sop-12-step.html)是这类变更的标准做法。 第三层的活要拉后端一起做,工程侧七个动作点的分工 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)能省掉来回。 第二个来源是边缘服务商。它决定了用br还是gzip、要不要自动补 Vary: Accept-Encoding、机器人识别标记怎么下发、缓存命中状态怎么标。样本里62.6% 的站在同一家CDN后面,这意味着这批站的这一层行为高度一致。 第三个来源才是你自己的代码。按语言分发、按地区换货币、按登录态改页面——这些是业务逻辑,只有这一层的变化是你亲手写的。 而这三层里,只有第三层的变化需要你手动声明,也只有第三层会漏。前两层的行为虽然不是你定的,但它们自带了配套的声明;你自己写的那部分反而没有任何东西提醒你去补。 ## 三层各自的可预测性 来源 | 典型行为 | 可预测性 | 会不会自己变 | 建站平台 | Cookie、默认缓存策略 | 同平台一致,可查同行 | 会,随平台版本更新 | 边缘服务商 | 压缩、Vary自动补、缓存标记 | 同服务商一致 | 会,随产品策略调整 | 自己的代码 | 语言、货币、个性化 | 只有你自己知道 | 只在你改的时候变 | 不可预测的部分最终会体现在预算上,预算到归因到退出的七个动作 (https://zhangwenbao.com/finance-cfo-seo-collaboration-7-actions-budget-attribution-asset.html)是那本账。 把这类工作当产品来排期,产品化指标体系与迭代节奏 (https://zhangwenbao.com/seo-as-product-roadmap-metric-system-iteration-discipline.html)是可用的方法论。 这张表里最值得留意的是最后一列。前两层会在你完全没动过任何东西的时候自己变化,而且不会有人单独通知你。换句话说,就算你今天把所有行为都测清楚了,这份基线也有保质期。 ## 为什么第三层最容易漏 前面说只有第三层会漏,这句话值得再拆一层,因为它解释的不只是Vary这一件事。 断点在人不在技术,四画像三阶段的团队路线图 (https://zhangwenbao.com/seo-team-ai-engineer-fde-localization-playbook.html)是补人这一环的思路。 反馈链条断掉是协作问题,流量到转化的边界与交点 (https://zhangwenbao.com/seo-cro-boundary-handoff-collaboration.html)说的是另一处断点。 平台和边缘服务商在设计自己的功能时,是把“这个功能需要配套什么”当成一个完整包交付的。他们做压缩,就顺手补上压缩的声明;他们下发Cookie,就顺手带上安全属性。因为对他们来说,配套没做全会变成成千上万客户的工单。 而你写业务代码时,没有这个压力。按语言返回不同内容,写完测一下,浏览器里显示正确,功能就算完成了。“这个变化要不要告诉缓存”这个问题,不会在任何一个测试环节里被问到——本地开发没有缓存,测试环境的缓存通常也关着。 等到上了生产、走了边缘缓存,问题才有条件出现,而那时距离写代码已经过去很久,没人会把两件事联系起来。 所以这不是能力问题,是反馈链条断了:做决定的时刻和暴露后果的时刻,中间隔着一层只在生产环境才存在的东西。凡是有这个结构的地方,都值得单独加一道检查。 ## 怎么判断一个行为是哪一层来的 有个简单的分辨法:去找几个同平台或同CDN的站测一遍同样的东西。如果结果一致,那是平台层的;如果只有你这样,那是你自己代码里的。 同平台的站长得很像,比一比就知道,结构化数据的八步实战 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)就是这么摸出来的。 托管方悄悄改了策略这类事,监控没报警但引用归零 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)是最近一个例子。 这个方法在本文里用过一次,效果不错。_shopify_essential 这个Cookie出现在96个站上,几乎所有用这套系统的站都有,一眼就能判定是平台行为,不用去翻自己的代码。 反过来,delonghi.com那个体积差59% 的表现只有它一家,那必然是它自己的业务代码在做语言分发。分辨清楚来源,才知道该去改谁、该找谁问、以及这个行为哪天可能自己变掉。 ## 平台层的行为会变,而且不通知你 前两层会自己变这件事,值得单独强调,因为它决定了这套测试必须定期跑而不是做一次。 规则说变就变,返回按钮劫持新规的合规排查 (https://zhangwenbao.com/google-back-button-hijacking-spam-policy.html)是一次具体的应对。 外部变化要靠追踪才看得见,各家波动追踪工具与解读流派 (https://zhangwenbao.com/google-algorithm-volatility-tracking-tools-interpretation-frameworks.html)是这套监测的参照。 可能发生的变化有这么几类:平台改了Cookie的名字或者数量、CDN把默认压缩算法从一种换成另一种、边缘产品调整了自动补 Vary 的策略、安全模块开始给某类请求加新的标记。 这些变更通常会出现在服务商的更新日志里,今年那次边缘层默认设置变更就是先发了公告再引发一批抓取异常 (https://www.searchenginejournal.com/report-that-cloudflare-ai-bot-blocking-prevents-googlebot-from-indexing-sites/584673/);但那份日志的读者是运维,不是做站的人;而且它面向所有客户,不会告诉你“这条对你的站意味着什么”。公告发出来了不等于送达了,送达了不等于被翻译成了你这边的行动项。 所以真正可靠的做法不是订阅公告,是定期对自己的站做一次同样的测试,用差分捕捉变化。公告是通用的,差分是你自己的;前者你可能漏读,后者一定和你相关。 这一点也是本文这套方法最实际的价值所在——它测的不是别人的站,是你自己那一份行为清单会不会在你没注意的时候被人改掉。 ## 这些缺省该怎么测出来? 讲完数据,说做法。这一节是全文最能直接用的部分。 另一条实测路径是读日志,五千个站的爬虫伪造与抓取预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)是那条路的样板。 ## 测试矩阵怎么搭 核心思路只有一句:把请求的每一个变量单独变一次,其余保持不动,看响应变不变。 把一个问题拆成多个维度是通用手法,一个主题挖五十个长尾问题的五种方法 (https://zhangwenbao.com/how-do-you-generate-long-tail-question-keywords-from-a-topic.html)是另一处应用。 变量多的时候要设计抽样,跨设备位置怎么省钱的采样设计 (https://zhangwenbao.com/rank-tracking-sampling-design-frequency-device-sample-cost.html)是同一种思路。 需要变的变量,按重要性排是这几个。 变量 | 怎么变 | 看响应的什么 | Accept-Encoding | 带br、只带gzip、完全不带 | Content-Encoding、体积 | Accept-Language | 英语、目标市场语言、不带 | 最终地址、html lang、标题、体积 | User-Agent | 桌面、移动、搜索爬虫 | 最终地址、体积、结构化数据 | Cookie | 无、带地区选择、带登录态 | 价格、货币、库存显示 | 来源地址 | 不同地区的出口 | 最终地址、货币 | 每一行测完,得到的是一个是非题的答案:这个变量会不会改变响应。把答案汇总起来,就是你这个站真实的变化维度清单。 ## 比对什么才算数 这一步是前面吃过亏的地方,直接给结论。按可靠性从高到低排:最终地址 > 页面语言标记 > 页面标题 > 正文体积 > 正文指纹。 抽取稳定字段来比对更省事,一次扒清五种格式的字段缺漏 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)就是这么做的。 要比对就得先有稳定的快照,把搜索结果页变成可对账的时间资产 (https://zhangwenbao.com/serp-history-snapshot-tracking-system-volatility-archive-engineering.html)讲的是存证工程。 前四项都不可能被页面里的随机串影响,可以直接采信。最后一项要用就必须先把随机字段清理干净,而清理干净这件事比想象中难——本文的第一版尺子就是在这里虚报了3.8倍。 更省事的做法是不做全文指纹,改成只提取几个关键位置:html 标签的属性、title、meta description、页面上第一个价格数字、货币符号。这几个东西稳定、有语义、也正好是你真正关心会不会变的东西。 ## 然后和Vary对一遍 拿到变化维度清单之后,去读一遍自己的 Vary 头,逐项核对。 声明之间还会互相打架,两个标记的九种场景判断 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)把边界划清了。 声明与实际对不上是通病,八种跨页场景与冲突诊断 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)是另一个字段上的同款问题。 结果无非三种。清单里有而 Vary 里没有,是漏声明,缓存会串版本,必须补。Vary 里有而清单里没有,是过度声明,缓存被切得太碎、命中率变低,可以删。两边一致,这一项就算过了。 这个核对的价值在于它给出的是行动项,不是分数。每一条差异都对应一个明确的改动,不存在模棱两可的中间状态。 ## 把它做成一次可重复的检查 手工测一次能发现当下的问题,但缺省是会被改的——换一次CDN、加一层边缘脚本、升一次框架版本,行为都可能变。 定时任务这类活要考虑失败重试,实时推送与异步队列怎么搭 (https://zhangwenbao.com/wordpress-baidu-active-push.html)有可参考的结构。 定时跑加存档靠计划任务就够,用cron把独立站运维自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)给了脚本骨架。 所以这套矩阵值得写成脚本,跑在部署流程里或者定时任务里,输出存档,和上一次的结果做差分。发现响应行为变了但没人提过这次改动,就是最值得追查的那一类信号。 ## 用什么工具 不需要专门的软件,命令行的HTTP客户端就够,关键是把几个选项用对。 数据落地之后还要能关联起来,逐项打通几个后台的操作 (https://zhangwenbao.com/ga4-bigquery-google-ads-search-console.html)是下一步。 把结果做成自己的报表也不难,用命令行工具做自定义SEO报表 (https://zhangwenbao.com/claude-code-gsc-custom-seo-reports.html)是一条可行路径。 要点有四个。第一,把响应头单独存到文件里,别只看正文——本文一半以上的结论来自响应头。第二,跟随跳转,同时把最终地址记下来,因为跳转本身就是一种变化。第三,需要显式控制请求头时,把不需要的那个字段设成空值而不是不设,两者在多数客户端里含义不同。第四,把状态码、体积、耗时这几个数值一次性格式化输出,方便直接落成表格。 并发上要克制。同一个站点连续快速请求几次很容易被边缘防护判成异常,本文这次是每个站点内部串行、站点之间并发三路,中间留了间隔,全程没有被限流。测自己的站可以放开,测别人的站必须慢。 ## 什么时候跑 时间点比想象中重要,有三个时机值得固定下来。 迁移这类大动作前后都要测,六维度保稳的完整路线图 (https://zhangwenbao.com/site-migration-seo-no-traffic-loss-complete-guide.html)列了时点。 改版之后必须整体复测,改版不掉流量的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)列了要复查的项。 第一个是每次部署之后。这时候要验的是自己的改动有没有意外改变响应行为,尤其是碰过中间件、路由或者边缘脚本的时候。 第二个是换了任何一层基础设施之后。换CDN、换主机、加一层防护,这些动作会整批地替换掉前面说的第二个来源的行为。这类变更最容易在事后很久才发现问题,因为当时页面看起来一切正常。 第三个是定期的无事巡检,频率不用高,一个月一次足够。它抓的是前两个来源在你没动手的时候自己发生的变化。 ## 结果怎么读才不误判 有两类假信号要先排掉,不然每次差分都会报一堆问题。 异常曲线要能和正常波动分开,增长速度异常的识别与防护 (https://zhangwenbao.com/link-velocity-anomaly-detection-organic-growth-pattern-protection.html)是同一个判别难题。 灰度和实验会互相干扰,三十个A/B测试方案 (https://zhangwenbao.com/ab-testing-ctr-conversion-optimization.html)里有分流设计的讲究。 一类是页面里的随机值,前面讲过了,靠只提取稳定位置来避开。另一类是灰度发布——很多站在同一时间会有多个版本在跑,两次请求可能落到不同版本上,看起来像是随请求变,实际上只是随机分配。 区分这两者的办法是重复:同一个变体连发三次,如果三次之间也不一致,那就不是协商造成的差异,是随机分配。只有同一变体内部稳定、变体之间不同,才能判定为真正的按请求变化。 这一步会让测试次数翻三倍,但它是把结论从“看着像”变成“确实是”的唯一办法。本文的数据没有做这一步,所以严判据里那几个只靠体积差判定的站,严格说仍有灰度发布的可能——这一点必须说明,不能拿一个自己都没排除干净的数当结论。 ## 一份可以照着跑的实测清单 把上面的东西压缩成能直接执行的步骤。 清单跑完要排先后,三类站点的高回报修复顺序 (https://zhangwenbao.com/technical-seo-priorities-guide.html)是可用的排法。 ## 五分钟版 只做三次请求,对同一个首页地址。 轻量选择也会影响看到的数据,两种资源类型的六场景选型 (https://zhangwenbao.com/domain-property-vs-url-prefix-property-in-gsc-which-is-better.html)是选之前该知道的。 轻量检查一样能查出大问题,死链批量检测、分类到提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)也是几条命令的事。 第一次用正常的浏览器请求头。第二次把 Accept-Language 换成你主要市场的语言。第三次把 Accept-Encoding 整个去掉。 三次都把响应头存下来,看三件事:三次的最终地址一样吗,三次的 Content-Encoding 一样吗,响应里的 Vary 写了什么。 只要出现地址不同或编码不同,而 Vary 里没有对应字段,就是一个待修项。这三次请求能覆盖掉本文里说的绝大部分问题。 ## 五分钟版能查出什么,查不出什么 把预期说清楚,免得跑完觉得没发现问题就以为没事。 筛子和体检报告要分开看,五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)是更完整的那一份。 这三次请求能查出的是:语言维度和压缩维度上的漏声明,以及缓存策略是显式设定还是默认捡来的。按本文的数据,这两个维度覆盖了实测中发现的绝大部分静默变体,投入产出比最高。 查不出的有三类。一是按来源地区分发的行为,那需要从不同地区的出口发请求;二是按登录态变化的内容,那需要带真实会话;三是灰度发布造成的差异,那需要同一变体重复多次才能区分。 另外它只测了首页。首页往往是全站最特殊的一个页面——最容易被设成不缓存,也最容易有个性化内容。首页的结论不能直接推广到商品页和内容页,那是半天版要做的事。 所以五分钟版的正确用法是当筛子而不是当体检报告:发现问题说明确实有问题,没发现问题只说明这两个维度是干净的。 ## 半天版 在五分钟版的基础上加四件事。 内页里最复杂的是筛选那一类,筛选URL不爆炸的系统方案 (https://zhangwenbao.com/faceted-navigation-filter-url-seo-crawl-trap.html)要单独处理。 内页的规则和首页常常不同,分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)是内页那边要单独看的。 一是把地址从首页扩到几个代表性页面:一个商品详情页、一个类目页、一个内容页。不同页面走的代码路径不同,行为未必一致。 二是加上 User-Agent 这个维度,尤其要测搜索爬虫的令牌。如果响应对爬虫和对浏览器不同,而 Vary 里没有 User-Agent,那是个更严重的问题。 三是把 Cache-Control 和 Last-Modified 一并记下来,确认自己知道每个页面的缓存策略是显式设定的还是默认捡来的。 四是把首次请求写下的Cookie列出来,逐条问一句这是谁写的、干什么用的。问不出来的那几条,通常来自某个已经不用了的第三方脚本。 ## 顺手能查出来的另外三件事 同一批请求已经发出去了,多看几个字段几乎不额外花时间,顺手把这三件事一起查了。 跳转与错误页要一起看,404修复与软404排查 (https://zhangwenbao.com/google-search-console-404-error-fix-guide.html)是配套的操作。 跳转链一起看能省一轮,301、302、404与410各自的含义 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)是判断依据。 第一件是跳转链的长度。请求最终落在哪个地址、中间跳了几次,客户端都会告诉你。超过两跳就值得看一眼,每一跳都是一次完整的往返,对移动端首屏的影响很直接。 第二件是响应头里有没有暴露内部信息。具体的框架版本号、后端服务名、内网主机名,这些在272种字段里偶尔会冒出来,删掉不影响任何功能。 第三件是 Content-Type 有没有带字符集。样本里有24个站没带,虽然现代浏览器猜得挺准,但这是个一行就能补上的东西,没有不补的理由。 这三件事的共同点是:它们都不需要新的测试,只需要在已有的响应里多看两眼。做一次实测就把能顺出来的都顺出来,比分三次做省事得多。 ## 做完之后写在哪 结果不要只存在某个人的终端历史里。落到一份文档里,内容就三列:变量、是否影响响应、Vary里有没有声明。 零散的东西要有归拢的结构,主题集群和支柱页照着搭为什么没效果 (https://zhangwenbao.com/topic-cluster-pillar-page-topical-authority-architecture.html)讲的是结构的要害。 把零散知识收成可查的一处,把孤岛词条织成主题权威 (https://zhangwenbao.com/glossary-definition-hub-topical-authority-ai-citation.html)是同一种整理动作。 这份文档的作用不是给别人看,是给下一次改动时的自己看。当有人问“加一层地区判断会不会有事”,你能立刻回答“会,而且要同步改Vary”,而不是重新测一遍。 ## 这份清单该由谁维护 实际操作中,这件事经常卡在归属上:它算前端的、后端的、运维的,还是做站的? 归属要落到配比上,三类分工与团队配比的决策 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)是配套的组织答案。 归属不清就等于没人管,团队怎么搭才出活 (https://zhangwenbao.com/seo-team-structure-and-output-based-performance.html)说的是这件事的组织解法。 从产生变化的位置看,语言分发多半在后端或者边缘脚本里,缓存策略在运维或者CDN控制台里,Cookie来自平台和第三方脚本。没有任何一个角色能独立说清全部,这正是它长期没人管的根本原因。 可行的安排是:让做站或者技术负责人持有这份清单,各个角色在自己动手时负责更新对应的行。清单本身放在版本库里,和代码一起走评审流程。 更重要的是把它挂进现有流程:在改动清单涉及的那几层时,评审模板里加一句“本次改动是否改变了响应随请求变化的维度”。一句话的成本,换的是这件事从此有人过问。 这个安排听起来很轻,但它是前面所有测试真正落地的前提。测出来的结论如果没有归属,下一次基础设施变更之后它就作废了,而作废的时候没有任何人会知道。 ## 测出来之后,该改哪一层? 最后一节讲修复的落点,因为同一个问题在不同层修,代价差很多。 服务器这一层能做的事不少,六层重写与缓存的综合治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)是可照抄的分层。 ## 能在源站改就别在边缘改 Vary 这个头最好由产生变化的那段代码同时发出。谁决定了返回哪个版本,谁就负责声明这件事,两段逻辑放在一起,改的时候不会漏。 跳转放哪一层也是同一个选择,双向跳转的完整配置 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)能看出层次差异。 反代那一层改响应头要当心,末尾斜杠、重写与全场景配置 (https://zhangwenbao.com/nginx-proxy.html)有具体写法。 放到边缘层去补也能生效,但那意味着两处逻辑要靠人记住保持同步。本文里那17个编码变了却没声明的站,成因大概率就是响应头在某一层被重写时丢了东西。每多一层重写,就多一处需要同步的地方。 ## 如果非要在边缘改 那就把规则写成追加而不是替换。Vary 是个可以有多个值的字段,追加一个令牌不会影响已有的,替换整行就会。 边缘规则常被用来兜底,三类筛选URL的分流处理策略 (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)是更靠前的解法。 边缘层能做的远不止改头,用内容协商给智能体发Markdown (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是另一个方向的用法。 另外要注意执行顺序:边缘脚本改响应头的时机,可能在缓存写入之前也可能在之后,这一点各家产品不一样,直接决定了你的改动有没有作用于缓存键。这也属于文档不写、只能实测的那一类,改完必须验一次。 ## 修复的优先级怎么排 如果一次测出来好几处差异,别按发现顺序改,按影响面排。 影响面大的先修,索引膨胀的诊断与处置矩阵 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)给了同样的排序逻辑。 排完得讲清楚为什么这么排,四板块汇报模板 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)能把这件事说明白。 最优先的是会给错人的那一类:语言、货币、价格、库存。这几样发错版本会直接影响下单,而且用户不会来告诉你,他只会走掉。 第二优先的是会让所有人变慢的那一类:压缩声明漏了,缓存里存了未压缩副本。它不影响正确性,但影响每一个访客。 第三优先的是只影响缓存命中率的那一类:声明写多了,缓存切得太碎。这一类不会出错,只是回源多了一些,可以放到有空的时候再优化。 最后才是那些字段整理类的:删掉暴露内部信息的头、补上字符集声明、清理已经不用的Cookie。这些做起来最轻松,也最容易被优先做掉——但它们的收益也确实是最小的。排期时留意别本末倒置。 ## 把语言分发从内容协商换成显式地址 还有一条更彻底的路:不要按 Accept-Language 变内容,改成每种语言一个独立地址,用跳转把人送过去。 独立地址多了标注就得自动生成,从爬虫结果自动生成多语言sitemap (https://zhangwenbao.com/ai-script-hreflang-xml-sitemap-multilingual.html)是省人力的做法。 独立地址也不是写了就一定被收,那些语言版本只被当成规范页的别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)是要提前知道的。 这样做的好处是同一个地址永远对应同一份内容,缓存不用分版本,搜索引擎也能把每个语言版本单独收录。代价是首页会有一次跳转,而且跳转规则本身又成了一个需要维护的东西。 本文样本里那8个按语言跳到不同地址的站走的就是这条路,从缓存正确性的角度看,它们其实是做对的那一批——虽然它们的跳转规则同样没有出现在任何一份文档里。 ## 改完怎么验证 改 Vary 有个麻烦:改完之后,缓存里还躺着按旧规则存下来的副本。 改完对方认不认是另一回事,规范网址的九大决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)说明了判断权在谁那里。 改动生效要等多久是另一回事,加了noindex之后多久才消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)给了实测区间。 所以验证必须分两步。第一步是确认新响应确实带上了正确的头,这一步绕开缓存直接问源站,或者带一个随机查询参数让它必然回源。第二步是清掉边缘缓存,然后按新的变量组合各请求一遍,确认拿到的是各自对应的版本。 第二步经常被跳过,后果是改动看起来生效了、实际用户还在拿旧副本。判断方法是看 Age:如果它是个不小的数,说明你拿到的是清缓存之前的东西。 还有一个容易忽略的点:Vary 只对遵守它的缓存有效。浏览器本地缓存、企业内网的代理、运营商的透明缓存,各自的实现程度不一样。所以对于绝对不能串版本的内容,比价格和库存,最稳妥的做法仍然是根本不缓存,而不是靠声明。 ## 一个不改代码的过渡方案 如果排期紧、暂时改不了应用层,有个成本很低的过渡做法:把首页从内容协商改成固定返回一个版本,然后用页面上的语言切换器让用户自己选。 自动判断猜错的代价很具体,台港用语本地化与那个会转错的词 (https://zhangwenbao.com/chinese-converter-simplified-traditional-localization-guide.html)是个鲜活例子。 自动判断这条路的坑不少,假桌面、客户端提示与最佳实践 (https://zhangwenbao.com/js-judges-mobile-automatically-jumps-to-mobile.html)把几种判法都试过了。 这样做牺牲了一点体验——来自其他市场的访客第一眼看到的不是母语版——但换来的是行为完全可预测:一个地址一份内容,缓存不会串,搜索引擎收的也是确定的那一版。 在“自动猜对但可能串版本”和“不猜但绝不出错”之间,多数站选前者是因为默认就是前者,而不是因为比较过。真正比较一次会发现,自动判断带来的体验提升,往往抵不过它带来的缓存复杂度。 这也是本文一直在说的那件事的另一种表现:不是这个选择错了,是这个选择根本没被当成一个选择。 ## 搜索引擎拿到的是哪一版 还有一个角度前面没展开:如果同一个地址有多个版本,搜索引擎收录的是哪一版? 地区变体在检索里会被合并,地区差别写在标注里到了问答只剩一个词 (https://zhangwenbao.com/spanish-regional-variants-ai-answer-source-divergence.html)是同一个现象。 多语言版本在检索里本来就吃亏,翻译内容为什么在AI检索里吃亏 (https://zhangwenbao.com/multilingual-ai-visibility-geo-optimization.html)是另一层原因。 答案是它自己那次请求拿到的那一版。搜索爬虫请求时带的语言偏好通常是英语,来源地址多半在美国,所以它拿到的大概率是英语版或者美国版。 这带来两个实际后果。一是你的其他语言版本可能根本没被收录,因为它们没有独立地址,爬虫没有触发它们的条件;二是页面上声明的多语言关系可能对不上——你在页面里声明了有德语版,但那个地址点开对爬虫仍然返回英语版。 本文样本里那4个页面语言标记会变的站尤其要注意这一点:lang 属性从 en 变成 zh-Hans-cn,说明同一个地址下确实有中文版,但这个中文版没有自己的地址,也就没有被单独收录的机会。 要让每个语言版本都能被收录,前提是每个版本有自己的地址。这又绕回了前面那个结论:跳转虽然多一次往返,但它在搜索这件事上是明显更优的选择。 ## 回到那条一般规律 把这一整篇收一下。robots.txt那一层的缺省是成文的,标准文档里写着,查得到只是没人查。而这一层的缺省是不成文的——没有任何一份文档告诉你“这个站随语言变”,它只存在于行为里。 显式写清楚比让对方猜更稳,正文越本地化结构化数据越要写回国际格式 (https://zhangwenbao.com/minor-language-structured-data-inlanguage-locale-schema.html)是同一条原则。 把每类页面的取值写死是个好习惯,五类页面的差异化配置 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)是一份现成的表。 不成文的缺省只有一种办法能拿到,就是把它测出来。测的成本不高,本文全部结论用的是每个站四次请求;难的是想到该去测,以及测完把结果写下来变成团队的共同知识。 成文的缺省要显式化,不成文的缺省要基线化。前者花的是查文档的时间,后者花的是搭一套小测试的时间。两件事都不难,难在没人会提醒你这里有个东西需要你做决定。 ## 把这套东西交给别人时该说什么 最后补一段交接的话,因为这类知识最容易死在人员变动上。 该写下来的东西不止技术这一摊,三地区架构与合规开户对照 (https://zhangwenbao.com/dtc-overseas-incorporation-us-llc-uk-ltd-hk-ltd-3-region-comparison.html)也是要留档的那类。 交接和交付都要有明确定义,达标定义与验收条款怎么写 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)是把它写进合同的做法。 交接时要传的不是那份测试脚本,脚本谁都能重写。要传的是三件事:这个站在哪几个维度上会随请求变化、这些变化分别由哪一层产生、以及上一次核对是什么时候。 第一件决定了接手的人改动时要小心什么。第二件决定了出问题时该找谁。第三件决定了这份信息还能不能信——超过半年没核对过的清单,应该当成过期处理,重新跑一遍再用。 这三句话写下来不超过一页纸,但它把一个只存在于服务器行为里的事实,变成了团队里可以传递的东西。缺省分支之所以难对付,不是因为它复杂,是因为它不留痕迹;而写下来就是留痕迹最便宜的方式。 顺带一句,这份文档最好和代码放在一起,不要放在文档系统里。放在代码库里的东西,改代码的人有机会看见;放在别处的东西,只有想起来找的人才看得见。 ## 常见问题解答 ## Vary头到底该写什么? 写你的响应确实会随之变化的那些请求头,一个不多一个不少。少写会导致缓存把一个版本发给所有人,多写会把缓存切得太碎、命中率下降。最常见的必写项是 Accept-Encoding,这一项多数服务器会自动补。如果你的站按语言、按设备、按地区返回不同内容,就必须显式加上对应的字段。这次实测的139个站里,写了 Accept-Encoding 的有120个,而写了 Accept-Language 的只有3个,实际随语言变的却有17个。 ## 怎么快速测出自己的站随什么变? 对同一个地址发三次请求:第一次用正常浏览器头,第二次把 Accept-Language 换成目标市场语言,第三次把 Accept-Encoding 整个去掉。比对三次的最终地址、Content-Encoding、页面 lang 属性和正文体积。只要有任何一项不同,而响应里的 Vary 没有对应字段,就是漏声明。三次请求不到五分钟,能覆盖大部分问题。 ## 比对两次响应时,用整页哈希可靠吗? 不可靠,除非你先把页面里的随机字段清干净。本文第一版就是用整页指纹判定的,得出64个站有差异,翻明细才发现一大批是字节数完全相同、只有内部随机串不同的假阳性,收紧判据后真实数字是17个,虚高了3.8倍。更稳妥的做法是只提取几个稳定位置做比对:最终地址、html 标签的 lang、页面标题、正文体积,这几项不会被随机串影响。 ## 首页不写Cache-Control会怎么样? 缓存不会因此不缓存,而是走启发式规则:用 Last-Modified 与当前时间的差值取一个比例当作可缓存时长,各家实现不完全一致。这次样本里有21.6% 的站首页没有这个头,而带 Last-Modified 的只有12.2%,两样都没有的情况下行为最不可预测。首页这类含个性化内容的页面,建议显式写明策略,不要让每一层缓存各自猜一个值。 ## 为什么很多站的首页干脆写no-store? 因为首页上通常有购物车数量、会员状态、个性化推荐这类因人而异的内容,缓存一份发给所有人会出事。样本里 private, no-store 是最常见的取值,36个站在用。这是最安全但也最贵的选择——每次访问都要回源。如果把 Vary 用对,理论上可以做到既缓存又分版本,只是需要先把随什么变这件事想清楚并写下来。 ## 首次请求就被写入七八条Cookie正常吗? 在电商站上属于常态。这次139个站里有119个在第一次首页请求就写了Cookie,条数中位7条,最多的一个写了39条。名单里绝大多数来自建站平台和边缘服务商,比如店铺平台的会话标识、地区与货币记忆、边缘层的机器人识别标记,站主自己写的很少。值得做的是把这份清单列出来逐条确认用途,问不出来的那几条通常来自已经不用了的第三方脚本。 ## Cookie不写Domain属性有什么影响? 缺省是只作用于发出它的那个主机名,不包含子域。这个方向是安全的,但如果你有多个子域,比如商城和博客分开部署,那么不写这一项的会话标识在两边是不通的,跨子域的行为分析会把同一个人看成两个访客。这次778条Cookie里有537条没写这一项。要跨子域共享就得显式写 Domain,同时注意这会扩大Cookie的发送范围。 ## 不压缩的响应比压缩的大多少? 这次实测的中位数是6.44倍。也就是压缩后200 KB的首页,原始体积在1.3 MB上下。这个倍数可以当参照用:如果日志里某个客户端拉走的字节数是常规的六七倍,多半不是它在攻击你,而是它请求时没带 Accept-Encoding——一些老旧的抓取脚本和简易监控探针就是这样。 ## 权威参考资料 ## canonical你说了不算:132个首页有23%自相矛盾 - URL:https://zhangwenbao.com/canonical-self-declaration-conflict-google-selected.html - 分类:技术SEO - 发布:2026-08-15 | 更新:2026-08-15 - 摘要:新客户的博客还没被收录,搜索平台里那栏谷歌选定的规范网址已经指向一个陌生域名。这类字段的措辞是选定,不是你声明的,两栏并排放着本身就是在告诉你它们可以不一样。 - 关键词:技术SEO,多语言SEO,独立站运维,规范网址 > **TLDR**:摘要:把132个独立站首页对自己地址的所有声明抠出来,逐对比较。严格按字符串比,全部声明完全一致的只有29.4%;只放宽一条规则,忽略末尾那个斜杠,立刻跳到74.6%;再忽略www、再忽略协议、再忽略参数和大小写,最高只到77.0%就不动了。也就是说,这些页面自相矛盾的地方里,四分之三只是一个斜杠,剩下的23%是真分歧,怎么放宽规则都消不掉。分歧最集中的一对是hreflang的默认版本和结构化数据里的地址,41个可比对的页面里有13个对不上。 > 摘要:把132个独立站首页对自己地址的所有声明抠出来,逐对比较。严格按字符串比,全部声明完全一致的只有29.4%;只放宽一条规则,忽略末尾那个斜杠,立刻跳到74.6%;再忽略www、再忽略协议、再忽略参数和大小写,最高只到77.0%就不动了。也就是说,这些页面自相矛盾的地方里,四分之三只是一个斜杠,剩下的23%是真分歧,怎么放宽规则都消不掉。分歧最集中的一对是hreflang的默认版本和结构化数据里的地址,41个可比对的页面里有13个对不上。 先说一个让人心里一沉的场景。你接手一个新客户的站,博客刚上线还没被收录,你打开搜索平台的网址检查工具想看看进度,结果那一栏写着“谷歌选定的规范网址”,后面跟着一个你从来没见过的域名,看着还挺像垃圾站。 这不是假设,2026年8月13日有位从业者在社交平台上晒过这么一张截图,完整经过见Search Engine Roundtable关于选定的规范网址指向垃圾站的报道 (https://www.seroundtable.com/spammy-google-selected-canonical-41863.html)。谷歌那边的回应是:有时候几个域名共用过同一个停放页或者过渡页,就容易出现这种情况,建议过几周再看看会不会变。 新站迟迟不被收录还有别的成因,页面不被Google收录的急救手册 (https://zhangwenbao.com/google-not-indexed-fix-playbook.html)按症状分诊列过一遍。 这句回应里藏着本文要讲的全部内容。注意那个动词——选定。不是“你声明的规范网址”,是“它选定的”。这两个字段在同一个界面上并排放着,一个写你说的,一个写它选的,而它们经常不一样。 这就是第三种病。前两篇讲过另外两种:一种是东西根本不在你交出去的字节里,另一种是东西在但对方那次请求没拿到。这一种最麻烦:对方拿到了,读懂了,然后用了自己的判断。 它到底按什么选,Google选择Canonical URL的9大决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)拆过完整判据。 上一篇换了7种身份各要一次,robots.txt说允许GPTBot仍有10个站进不去 (https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html)。 那一篇量的是同一批站的正文可读字符,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html)。 三种病的药方互为毒药。缺失型你去补内容,送达型你去查通路,采信型呢?绝大多数人的第一反应是把声明写得更用力一点——再写一遍、写得更绝对、多加几个地方声明同一件事。这个动作在采信型面前不但无效,还经常帮倒忙,因为对方不采信的原因通常不是没看见,而是它同时看见了好几份互相矛盾的证据,只好自己挑一份。 所以这篇文章不讲规范网址标签怎么写,那种教程遍地都是。它想量一件几乎没人量过的事:一个真实的网站首页,到底对自己的地址做了几次声明,这些声明互相打架的比例有多高。 样本还是那132个国际化独立站首页,跟前两篇同一批,这样三层结论可以互相印证。 基础写法不在本文范围内,Canonical URL是什么 (https://zhangwenbao.com/canonical-url-seo-guide.html)有完整的设置指南。 提前说一句结论,免得读到一半失去耐心:这些页面在地址这件事上自相矛盾的地方,四分之三只是一个末尾斜杠,无伤大雅;但剩下那四分之一是真的在说两件事,而且它们的所有者八成不知道。 还有一件事得先讲清楚,不然后面容易读偏。本文不讨论规范网址标签该怎么写,也不讨论多语言标签的语法。这篇文章只关心一件事:同一份HTML里,那几处各自独立生成的地址,彼此对不对得上。语法全对、每一处单看都没毛病,合在一起仍然可以是矛盾的——这正是这类问题难被发现的原因。 ## 同一个首页,会对自己的地址做几次声明? 先把要量的东西数清楚。 这两个指令能不能一起用,noindex和Canonical能同时用吗 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)分了9种场景。 ## 一个页面能声明自己地址的六个位置 很多人以为地址声明只有规范网址标签一处,实际上一个现代电商首页通常同时用了三到四处,而且它们分属不同的系统、由不同的模块生成。这几处大多写在link元素上,MDN关于link元素与rel属性的条目 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/link)把canonical、alternate、hreflang这几种关系的写法列在了同一页。 来源 | 写在哪 | 谁生成的 | 它想告诉谁 | rel=canonical | 头部link标签 | SEO模块或主题模板 | 搜索引擎:这一页的正式地址 | og:url | 头部meta标签 | 社交分享模块 | 社交平台:分享出去用哪个地址 | hreflang的默认版本 | 头部link标签 | 多语言模块 | 搜索引擎:语言匹配不上时去哪 | 结构化数据里的url | 脚本块里的JSON | 结构化数据插件 | 搜索引擎与AI:这个实体的官网 | base href | 头部base标签 | 前端框架 | 浏览器:相对路径从哪算起 | 服务器实际服务的地址 | 跳转之后的最终地址 | 服务器与边缘规则 | 所有人:你实际站在哪 | 结构化数据这一层怎么落地,结构化数据Schema怎么配合SEO落地 (https://zhangwenbao.com/seo-schema-guide.html)附了常见避坑。 最后那一行是这篇文章的锚。前面五个都是声明,是页面在说话;最后一个是事实,是服务器在做事。做对齐审计的时候,永远拿事实那一行当基准,别拿任何一个声明当基准。 ## 各个来源的覆盖率 132个首页里,各来源出现的比例是这样的: 事实这一行由状态码决定,HTTP状态码怎么影响SEO (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)讲了301、302、404和410的选择。 来源 | 出现的站数 | 覆盖率 | rel=canonical | 121 | 91.7% | og:url | 94 | 71.2% | 结构化数据里的url | 86 | 65.2% | hreflang的默认版本 | 64 | 48.5% | base href | 0 | 0.0% | 规范网址标签的覆盖率最高,91.7%,符合预期,它是这行的标配。base href则是干净的零——132个站没有一个用它,这个标签在现代前端里基本退休了。 更有信息量的是每页同时存在几个来源:6个站一个都没有,9个站只有1个,29个站有2个,54个站有3个,34个站有4个。 哪些标签还值得用,网页语义化HTML改造 (https://zhangwenbao.com/semantic-html-tags-seo.html)按8类标签评过。 不同页面类型的配法不一样,各类页面的meta robots和canonical配置 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)按5类拆过。 也就是说,88个站在同一个页面里对自己的地址说了三遍以上。说三遍本身不是问题,问题是这三遍由三个互不通气的模块生成,而且没有任何一处校验它们说的是不是同一件事。 ## 这几处声明分别被谁读 要理解它们为什么会打架,得先知道它们各自是给谁看的。这一点比语法重要得多。 地址结构本身也有讲究,电商网站为什么爱用扁平URL (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)有10000个站的实测。 规范网址标签的读者主要是搜索引擎的索引系统。它在做的事情是把内容相同的一批地址归成一组,然后挑一个当代表,只有这个代表会出现在搜索结果里,其余的把权重让给它。 og:url的读者是社交平台的抓取器。你把链接贴进社交平台或者即时通讯工具,对方会去抓这个页面,用这个字段决定卡片上显示哪个地址、点击跳到哪里。它跟收录基本无关,但跟分享后的实际落点强相关。 归不到一起就成了索引膨胀,索引膨胀的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)给了决策矩阵。 分享出去之后的可见性是另一套打法,Search Everywhere全渠道实战 (https://zhangwenbao.com/influencer-content-search-everywhere-optimization.html)讲了怎么铺。 hreflang那一组的读者也是搜索引擎,但走的是另一条链路:语言与地区匹配。它回答的是同一份内容有哪些语言版本、匹配不上时去哪一版。 结构化数据里的地址,读者这两年变多了。除了搜索引擎的富媒体展示,各类AI答案系统在整理实体信息时也会读它。当一个AI答案里出现某个品牌的官网链接,那个链接有不小的概率就是从这个字段取的。 这一组标签的完整写法,国际化SEO和hreflang怎么做 (https://zhangwenbao.com/international-seo-hreflang-complete-guide.html)有避坑清单。 它对AI搜索到底有没有用,结构化数据对AI搜索的实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)给了官方说法与数据。 最后,服务器实际服务的地址,读者是所有人——包括那些根本不解析HTML的系统,比如链接检查器、广告平台的落地页审核、以及各种把地址当字符串存起来的地方。 ## 读者不同,所以没人负责让它们一致 把上面这一段连起来看,问题的根就露出来了。 落地页审核读的是另一份东西,广告文案原料全在落地页上 (https://zhangwenbao.com/ad-landing-page-copy-source-robots-template.html)讲了它的取料方式。 这五处声明服务于五拨不同的读者,因此在组织里通常也分属不同的人:做搜索的管第一处,做社媒的管第二处,做多市场运营的管第三处,做数据与富媒体的管第四处,做运维的管第五处。 每个人都在自己那一处写下了正确的答案,而没有任何一个人的职责是让这五个答案彼此相等。 跨语言的实体对不上是同一类协作问题,国际化SEO最难的不是hreflang (https://zhangwenbao.com/multilingual-entity-seo-cross-lingual-reconciliation.html)列了五大根因。 这也解释了为什么这类问题在小站上反而少见——小站上这五处很可能是同一个人配的,或者干脆由同一个主题模板一次输出。规模越大、分工越细,打架的概率越高。本文数据里那些声明来源最多的站,恰恰也是分歧最集中的那一批。 ## og:url这个字段,多数人只用对了一半 五处声明里,og:url是最容易被当成配置项随手填掉的一个,值得单独说两句。 大站的审计要成体系,企业网站SEO审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)给了检查表。 它的覆盖率71.2%,仅次于规范网址。但它的作用跟收录基本无关,它决定的是社交分享出去之后的落点:卡片上显示哪个地址、点开跳到哪里、以及那些统计分享数的系统按哪个地址计数。 最后那一点是很多人没想到的:如果同一个页面在不同时期用不同的地址被分享出去,那些分享计数是分开算的,不会合并。对做社媒投放的独立站来说,这意味着你的分享数据被拆成了几份。 参数怎么打才不乱,UTM链接构建器规范 (https://zhangwenbao.com/utm-builder-utm-tracking-link-campaign-url-guide.html)附了SEO避坑清单。 另一个常见错法是把它填成站点首页而不是当前页面。有些主题的默认设置就是这样,结果每一篇文章分享出去,卡片上的地址都是首页。这个错误在页面上完全看不出来,只有在分享的那一刻才暴露。 所以自查的时候,别只看它有没有填,要看它填的是不是当前这一页。把一篇文章分享到任意一个即时通讯工具里,看看弹出来的卡片指向哪,三秒钟就能验完。 主题默认值的坑不少,WordPress文章和页面怎么选 (https://zhangwenbao.com/wordpress-pages-vs-posts-seo.html)讲了收录与权重的差别。 ## 先把测量口径钉死 这类比较最容易在口径上出事,所以把规则先摆出来。 取值方式:规范网址标签取link元素的href属性原文;og:url取meta的content;hreflang取值为x-default那一条的href;结构化数据取顶层实体的url字段;最终地址取跟随全部跳转之后的那个地址。全部保留原样,不做任何清洗。 比较范围:只比较那些同时存在两个以上来源的页面,一共126个。只有一个声明的页面没什么好比的。 比较方法:把一个页面上所有存在的来源两两比,全部相同才算这一页一致。这是个很严格的判据,一处不一致整页就算不一致。后面会看到,正是这个严格性让分层放宽变得有意义。 ## base href为什么是干净的零 132个站零覆盖,这个结果值得单独说一句,因为它是这份数据里唯一一个百分之百确定的结论。 这个标签的作用是给页面里所有相对路径指定一个起点。它在早年很常用,因为那时候页面结构简单,用它能省掉一堆重复前缀。现在它基本消失了,原因有三个。 一是它的作用域太粗。它会影响页面里所有的相对地址,包括脚本动态插入的那些,一旦设错就是全页崩,而排查起来极难,因为出问题的地方和设置的地方隔得很远。 二是现代框架都有自己的路由和资源地址管理,不需要靠这个标签兜底。三是绝大多数站现在直接输出绝对路径,问题从根上就不存在了。MDN关于base元素的说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/base)里也写着,一个文档里最多只能有一个这样的标签,而且它必须出现在任何相对地址被使用之前。 链接形态本身也影响权重传递,按钮链接和JS链接会稀释权重吗 (https://zhangwenbao.com/will-button-links-and-js-links-dilute-the-authority.html)对比了4种形态。 这条结论对做审计有个用处:如果你在一个现代站上看到了这个标签,那它大概率是历史遗留或者某个老插件塞的,值得单独查一下它有没有在悄悄改写别的地址。 ## 那6个一个声明都没有的站 另一头也得看。132个站里有6个首页一个地址声明都没有,既没有规范网址,也没有社交标签、多语言声明和结构化数据。 页面被悄悄改写的事真发生过,浏览器自动翻译把yes改成forks (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是一个实例。 这6个站不是简陋的小站,它们的首页HTML都在几万字节以上,视觉上做得相当讲究。它们只是把所有精力放在了给人看的那一层。 这种状态的实际后果,是这个页面的身份完全由接收方推断。推断的依据只剩下跳转终点、内部链接和外部链接。对一个只有一个首页地址、没有多余参数的站来说,这样其实也能工作;但只要出现第二个可达地址,风险就立刻实体化。 给机器看的那一层怎么量,语义化HTML到底影响AI抓取吗 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)拿样本页跑过。 值得一提的是,这6个站里有几个是本文后面会提到的多语言大站。多语言站没有任何地址声明,是这批数据里我认为风险最高的一种组合。 ## 这次测量的边界在哪里,哪些结论不能外推? 把局限性摆在前面说,后面的数字才好用。这一节不好看但必须有。 这些语言版本的实际待遇,hreflang写的语言版本只被当成规范页的别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)有实测。 ## 只测了首页 首页在地址声明这件事上是最特殊的一页。它的地址最短、被链接得最多、被人工检查过的次数也最多。所以这批一致率应该被理解成上限,不是平均值。 真正容易出问题的是商品页和分类页,它们数量大、由模板批量生成、经常带参数。一个模板上的地址拼接错误,在首页上可能看不出来,在十万个商品页上就是十万处不一致。 首页的特殊性还体现在别处,首页首屏从导航到分类区怎么设计 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)讲了它的职责。 模板批量生成地址最怕失控,电商筛选器URL不爆炸的方案 (https://zhangwenbao.com/faceted-navigation-filter-url-seo-crawl-trap.html)是一套8步流程。 这也是我建议做抽查而不是只测首页的原因。首页测出来是好的,不能推出全站是好的;首页测出来有问题,那全站一定有问题。 ## 只采了一次,而且只从一个出口 所有请求在同一个时间窗内、从同一台位于中国的服务器发出。这个条件对做了地理分流的站影响很大。 上一篇量到过好几个站按请求方来源分发到不同的国家站。那意味着同一个页面的地址一致性,从不同出口测会得到不同的结果。这批数据只代表其中一个出口看到的样子。 还有一个时间维度的问题:地址声明会随发版变化。今天一致的站,下周上一个新插件就可能不一致。单次采样看不出这种波动。 分流出问题时怎么排,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)给了顺序。 变更要有记录才查得动,SEO变更日志的企业站治理 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)列了13类信号。 ## 不比较语义,只比较字符串 这是最重要的一条边界。本文所有的一致与不一致,判断依据都是字符串比较加上分层归一化,不涉及任何语义判断。 所以有几类情况会被误判成不一致,而它们其实是合理的。比如多语言站的默认版本本来就不必等于规范网址,前面已经说过;比如某些站的结构化数据写的是品牌实体的官网而不是当前页面的地址,这在规范上也说得通。 我的处理办法是把这类情况留在数据里,但在解读的时候单独指出来。把合理的差异也算进去,会让分歧率偏高;但如果凭主观判断剔掉一部分,这份数据就没法被别人复现了。两害相权,我选了可复现。 ## 这份数据能支撑的那一句话 把上面三条摆清楚之后,这批数字能支撑的结论其实只有一句:在只看首页、只从一个出口、只做字符串比较的条件下,一个页面内部的地址声明有23%存在无法用格式差异解释的分歧。 数据可复现有多重要,10条最佳实践清单里8条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)是个反例。 这一句已经够用了。它不需要外推到全站,也不需要精确到小数点,它要说明的只是一件事:这个问题的规模比行业里默认的大得多。 ## 为什么用这批样本,而不是随机抽 还有一个问法值得回答:为什么不随机抽一批站,那样不是更有代表性吗? 因为代表性要看代表谁。随机抽的样本代表的是整个网站群体的平均水平,而那个平均水平里包含大量个人博客、企业官网、几页纸的小站,它们的地址结构简单到不会有这个问题。把它们混进来,分歧率会被稀释得看不出问题,而稀释出来的那个数字对任何一个真实的独立站都没有参考价值。 这批132个站是按有独立品牌、有多语言版本、体量中大以上三个条件筛出来的。它们代表的是行业里做得比较认真的那一批,也就是很多人拿来当参照对象的那一批。 地址结构本身的9个细节,URL结构与slug优化 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)讲了它怎么影响抓取。 所以读这些数字的时候要记住一件事:这不是平均水平,这是被当成标杆的那一批的水平。23%的真分歧出现在这样一批站上,含义比它出现在随机样本里重得多。 ## 三次测量用的是同一批站,这件事本身有用 三篇文章、三个完全不同的问题,用的是同一个样本池,这不是省事,是有意为之。 好处是结论可以叠加。同一个站在三份数据里的表现能对上:那些首页正文几乎为空的站,往往也是没有地址声明的那一批;那些防护配置极严的站,往往也是地址结构最复杂的那一批。三层数据落在同一批对象上,才能看出这些问题不是孤立的,它们经常长在同一个站上。 更实际的一层好处是:它把三个抽象的判据变成了一套可以连起来跑的体检。抓一次首页,就能同时回答三个问题——字节里有没有内容、换个身份还拿不拿得到、页面对自己是谁说了几句话。 渲染模式决定字节里有什么,AI爬虫抓不到JS渲染的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)做过对比。 这三件事在多数团队里是三个人分别在管,甚至根本没人在管。而它们其实共用同一个动作:把首页抓下来,认真看一遍它到底交出了什么。 ## 把宽容度一层层放开,一致率涨到77%就再也不动了 这一节是全篇的尺子,也是我认为这次实验里最值得复用的方法。 体积这一头也要量,46个电商站的页面体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)发现4个站的商品链接没被读到。 ## 一层一层松开规则 直接问“这些声明一致吗”是问不出东西的,因为答案取决于你有多宽容。所以我把宽容度做成了阶梯,每一层只放宽一条规则,并且写明放宽的是哪一条。 层级 | 放宽了什么 | 全部声明一致的页面 | 比例 | 第0层 | 什么都不放宽,严格按字符串比 | 37 | 29.4% | 第1层 | 忽略末尾的斜杠 | 94 | 74.6% | 第2层 | 再忽略www前缀 | 96 | 76.2% | 第3层 | 再忽略http与https的差别 | 97 | 77.0% | 第4层 | 再忽略查询参数与片段 | 97 | 77.0% | 第5层 | 再忽略大小写 | 97 | 77.0% | 口径变了数字就没法比,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)讲的是同一类问题。 这张表要横着读,读的是每一层比上一层多救回了几个站。 第0层到第1层,从37跳到94,一条规则救回57个站。这些页面自相矛盾的地方里,超过四分之三只是一个末尾斜杠。 第1层到第3层,一共只多救回3个。www救回2个,协议救回1个。 地址形式的选择会放大这类差异,网站URL用扁平还是层级 (https://zhangwenbao.com/flat-urls-vs-hierarchical-urls-for-ecommerce-sites.html)含301改版实战。 第3层之后,再怎么放宽都是零。参数不救人,大小写也不救人。剩下那23%是真分歧,它们不是格式差异,是这些声明确实指向了不同的页面。 ## 这把尺子为什么值得抄走 分层归一化这个做法,可以用在任何一个“到底一致不一致”的问题上,它比单个百分比有用得多,原因有三条。 第一,它把结论和口径绑在一起。29.4%和77.0%都是对的,区别只在你认不认末尾那个斜杠。一个不写明归一化规则的一致率,是没法被别人复现的。 第二,它能自动分出问题的性质。跳变发生在哪一层,问题的性质就在那一层:跳在斜杠层就是模板拼接问题,跳在www层就是域名规范化问题,跳在协议层就是历史迁移的残留。 判据写明白才有用,一个词值不值得单开一页 (https://zhangwenbao.com/keyword-own-page-duplicate-wordset-audit.html)用87个站的站点地图给了答案。 协议迁移的跳转怎么配,HTTPS 301跳转的双向实战 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)有可直接抄的配置。 第三,也是最要紧的一条:它能告诉你放宽到什么程度就没用了。那条曲线一旦走平,说明剩下的都是真问题,再优化你的比较逻辑也是浪费时间。这个平台期的位置,比曲线本身更有价值。 ## 末尾那个斜杠到底要不要紧 既然它一个人就贡献了57个站的差异,得单独说两句。 对搜索引擎来说,根域名后面那个斜杠通常不构成两个不同的地址,主流搜索引擎会把它们当同一个。所以这57个站的差异,绝大多数不会造成实际的收录问题。 但它会造成另外两个麻烦。一是对比困难:你自己做审计的时候,工具报出一堆不一致,你得逐个确认是不是斜杠问题,很浪费时间。二是它是一个信号:同一个页面上的两个模块,连末尾斜杠这种事都没对齐,说明它们之间确实没有任何共享的地址生成逻辑。今天差一个斜杠,明天上多语言的时候就会差一个语言前缀。 归并结果在报表里怎么显示,Google索引覆盖的8种状态 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)讲了每种的含义。 层级前缀的影响,目录层级URL对SEO有何影响 (https://zhangwenbao.com/impact-of-hierarchical-urls-on-seo.html)给了6招优化。 所以我的建议是:斜杠层面的不一致不用当故障处理,但值得当成技术债记下来。修它的成本很低,通常就是在一个地方统一生成地址,然后所有模块引用它。 ## 第0层那37个站,做对了什么 严格比字符串就完全一致的有37个站。翻了一遍它们的共同点,答案很朴素。 第一个共同点是地址简单。这37个里的绝大多数,首页地址就是带www的域名加一个末尾斜杠,没有语言前缀、没有地区路径、没有参数。地址越简单,能写错的地方越少。 第二个共同点是声明来源少。它们里有不少只有两三个来源,而不是四个。来源少不代表做得好,但确实降低了打架的概率——两个人吵架的可能性总比四个人低。 架构决定地址复杂度,独立站网站架构怎么搭 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)讲了抓取深度。 第三个共同点才是真本事:那些既有四个来源、又严格一致的站,几乎都是把地址集中在一处生成的。你能从字节里看出来,四处写的字符串一模一样,连大小写和斜杠都分毫不差,这种整齐不可能是四个模块各写各的凑出来的。 这也就给出了唯一有效的解法:把当前页面的规范地址做成一个函数,所有需要输出地址的地方都调用它。这个改动在多数系统里是半天的活,但它一劳永逸。 重写规则也该集中管,.htaccess的六层综合治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)给了可版本化的写法。 ## 这把尺子还能量什么 分层归一化不只能用在地址上。凡是遇到“两边到底一不一致”的问题,都可以照着搭一遍。 比如比对商品标题在站内和在渠道上的一致性:第0层严格比,第1层忽略空格差异,第2层忽略标点,第3层忽略品牌前缀。跳变发生在哪一层,就知道问题出在录入、模板还是渠道映射。 再比如比对价格:第0层严格比,第1层忽略货币符号写法,第2层忽略千分位,第3层允许一分钱的误差。如果第3层还是对不上,那就是真的不一样,不是格式问题。 商品在渠道上的身份还有另一套标识,跨境电商GTIN怎么申请 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)讲了它的作用。 定价本身怎么定,从成本加成到价值定价的决策框架 (https://zhangwenbao.com/dtc-pricing-strategy-cost-plus-value-based-framework.html)是另一篇。 关键在于每一层只放宽一条规则,并且写清楚放宽的是什么。一次放宽三条,你就永远不知道是哪一条救回了那些样本。这是我从这次实验里拿到的最通用的一条方法。 ## 29.4%这个数字,对外该怎么说 做审计报告的人会遇到一个现实问题:这一堆数字里,该把哪一个写进结论。 只写29.4%是不诚实的,因为它把一大堆无害的斜杠差异算成了问题,听起来像天塌了。只写77.0%也不够,因为它把真问题的规模说小了,而且掩盖了那57个站的技术债。 我的写法是三句话:严格比只有29.4%一致;其中绝大多数差异只是末尾斜杠,放宽这一条之后升到74.6%;再怎么放宽最高只到77.0%,剩下的23%是真分歧。三句话缺一不可,缺了第一句显得问题小,缺了第三句显得问题大,缺了中间那句就没人知道该先修什么。 这个写法还有一个附带好处:它自带优先级。斜杠层的问题批量修、成本低、优先级低;真分歧层的问题要一个一个查、成本高、优先级高。一个数字给不出优先级,一条曲线可以。 怎么把技术结论讲给非技术的人听,老板听不懂SEO错其实在我们 (https://zhangwenbao.com/explain-seo-geo-value-to-non-technical-leadership.html)给了讲法。 ## 归一化也会归过头 分层归一化好用,但它有一个方向上的风险,得说清楚。 放宽规则的每一步,都是在假定某个差异无关紧要。这个假定在多数情况下成立,但不是永远成立。忽略末尾斜杠对根域名成立,对某些服务器上的路径就不一定;忽略大小写对域名部分成立,对路径部分不成立,因为路径在很多服务器上是区分大小写的。 所以我在做第5层的时候特意只对域名部分忽略大小写,路径保持原样。如果连路径大小写也忽略,一致率会更好看,但那个好看的数字里就混进了真实存在的问题。 参数带来的地址变体也是同一类,URL中srsltid参数的SEO影响 (https://zhangwenbao.com/google-srsltid-parameter-seo.html)给了4种处置。 更通用的说法是:归一化每放宽一条,都要能说出这条为什么在这个上下文里无害。说不出来的那一条就别放宽。这是分层法唯一需要小心的地方,也是它最容易被用坏的地方——为了让数字好看,一路放宽到什么都一致,然后得出一切正常的结论。 这个风险跟上一篇提过的那次尺子失效是同一类:判据本身没错,错在被用在了不该用的地方。一把尺子的诚实程度,取决于它有没有拒绝测量的能力。 ## 剩下那23%的真分歧,都长什么样? 接下来看具体是哪几对在打架。 样本边界画错的后果,调研数据里没有一个非会员 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)是个典型。 ## 配对分歧率排行 把所有能配对的来源两两统计,在第1层的口径下,分歧率是这样的: 这一对 | 可比对的页面 | 对不上的 | 分歧率 | hreflang默认版本 与 结构化数据 | 41 | 13 | 31.7% | 规范网址 与hreflang默认版本 | 64 | 18 | 28.1% | hreflang默认版本 与 实际服务地址 | 64 | 15 | 23.4% | og:url与hreflang默认版本 | 48 | 10 | 20.8% | 规范网址 与 结构化数据 | 85 | 11 | 12.9% | 结构化数据 与 实际服务地址 | 86 | 11 | 12.8% | og:url与 结构化数据 | 67 | 8 | 11.9% | 规范网址 与 实际服务地址 | 121 | 9 | 7.4% | og:url与 实际服务地址 | 94 | 6 | 6.4% | 规范网址 与og:url | 90 | 2 | 2.2% | 这张表从上到下读,是一条很清楚的线索。 ## 为什么最后一行只有2.2% 先看最底下那一行。规范网址和og:url,90个页面里只有2个对不上,分歧率2.2%,是全表最低。 原因不难猜:这两个字段在绝大多数系统里是同一段代码生成的,或者一个直接引用了另一个。它们不是达成了共识,它们是同一句话说了两遍。 这条给审计带来一个实用提示:如果你的站这两个字段不一致,那问题一定不小,因为连最容易一致的一对都出事了。值得优先查。 同一套模板里的分页也共用这套逻辑,Shopify集合页分页SEO实操 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)讲了canonical怎么设。 报表里怎么看出这类问题,GSC的数字为什么人人都读错 (https://zhangwenbao.com/google-search-console-complete-guide-diagnosis.html)逐项拆过。 ## 为什么排在最前面的都跟hreflang有关 再看最上面四行,全部涉及hreflang的默认版本。这个字段跟谁比都容易打架,跟结构化数据比31.7%,跟规范网址比28.1%,跟实际地址比23.4%,跟og:url比20.8%。 根源在于这个字段的语义跟其他几个不一样。规范网址回答的是“这一页的正式地址是哪个”,而hreflang的默认版本回答的是“语言都匹配不上的时候把人送到哪一版”。前者是身份,后者是兜底策略,它们本来就不必是同一个地址。 问题在于这个“本来不必”在实践中被滥用了。多语言模块通常由另一个团队或者另一个插件负责,它按自己的逻辑挑一个兜底版本,而完全不知道页面上还有别的地方在声明身份。 身份和意图是两回事,搜索意图到底有几种 (https://zhangwenbao.com/search-intent-seo-guide.html)讲了5种类型。 插件各管一段最容易出事,Shopify博客标签页SEO优化 (https://zhangwenbao.com/shopify-blog-tag-seo.html)讲的是权重稀释。 更要命的是,兜底版本经常被设成某个具体国家的版本。后面会看到实例,有的站默认版本指向芬兰站,有的指向英国站,有的指向欧盟站,而同一个页面的结构化数据写的是裸域名。两句话都合语法,但拼在一起就是在说这个网站有两个主页。 ## 分歧率要和覆盖率一起读 这张表有个陷阱,不说清楚容易读反。 看最上面那一行:hreflang默认版本与结构化数据,41个页面里13个对不上,31.7%。这个比例很高,但分母只有41——因为只有41个页面同时具备这两个来源。 再看倒数第三行:规范网址与实际服务地址,121个页面里9个对不上,7.4%。比例低得多,但分母是121,覆盖了绝大多数站。 多语言内容在AI检索里的处境,多语言AI可见性怎么做 (https://zhangwenbao.com/multilingual-ai-visibility-geo-optimization.html)讲了翻译内容为什么吃亏。 比例高说明这一对容易打架,绝对数大说明这个问题影响面广,两个视角要分开用。做优先级排序的时候看绝对数,做根因分析的时候看比例。 还有一个更实用的读法:把分歧率高的那几对当成一份预警清单。你的站如果同时具备hreflang默认版本和结构化数据这两处声明,那就有将近三分之一的先验概率对不上,值得主动去查一遍,而不是等出事。 指标怎么排优先级,网站收录速度实操指南 (https://zhangwenbao.com/seo-kpi-guide.html)用三平台数据做过对比。 ## 和实际服务地址比,才是真正的体检 表里有三行是拿声明去和服务器实际服务的地址比,这三行的含义跟其他行不一样,值得单独拎出来。 声明与声明之间打架,说明的是内部不一致,问题在协作。声明与事实打架,说明的是这个页面在撒谎——不是故意的,但效果一样。 三行的数字是:规范网址与实际地址7.4%、结构化数据与实际地址12.8%、多语言默认版本与实际地址23.4%。规范网址那一行最低,说明它是被维护得最认真的一个字段,这符合预期。 收录、排名、流量卡在哪一层,这三件事要分开查 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)给了分层方法。 og:url与实际地址的分歧是6.4%,只有6个页面,是全表倒数第二低。这个数字有点出乎意料——一个跟收录无关的字段,反而比结构化数据更贴近事实。 原因大概是它通常和规范网址同源生成,跟着后者一起对齐了。这也从侧面说明,只要地址是在一处生成的,跟着它输出的字段就都是对的;一处生成解决的是一批问题,不是一个。 结构化数据还能表达链接关系,用SignificantLink和RelatedLink提升内链效果 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)是另一种用法。 ## 为什么没有一对是零 整张表里最低的一对是2.2%,没有任何一对做到零。这件事本身就说明了点什么。 2.2%对应的是2个页面,而这两个页面的规范网址与og:url不一致,几乎可以断定是两处分别硬编码的结果——有人在模板里手写了一个,在插件设置里又填了一个。 这类硬编码是所有地址不一致里最难发现的一种,因为它不遵循任何规律,不会在同一批页面上同时出现,只在某一页上错。批量审计能抓到它,逐页人工检查反而抓不到,因为没人会去检查一个看起来一切正常的页面。 ## 声明来源越多,越容易打架吗 这是个很自然的疑问,数据也支持它,但支持的方式有点意外。 按来源数量分组之后:只有2个来源的29个站,一致率明显更高;有4个来源的34个站,一致率最低。这符合直觉——参与的人越多越难对齐。 但更值得注意的是分歧的性质变了。来源少的站,出问题多半是格式差异,放宽一层就救回来了;来源多的站,出问题往往是真分歧,怎么放宽都救不回来。 原因也不难理解。当一个页面同时有四处声明的时候,说明这个站做了多语言、做了社交、做了结构化数据,也就意味着它是个有多个市场、多个版本的复杂站。而复杂站的地址本来就有多个合理的候选,选哪个是个真问题,不是拼错了斜杠那么简单。 所以这条规律的实用含义是:如果你的站声明来源多,别指望靠一次格式清洗解决问题,那些分歧多半需要一个一个去做业务判断。反过来,如果你的站只有两三处声明却仍然不一致,那大概率是个便宜的修复。 ## canonical自指率92.6%,那9个不自指的站分别错在哪? 这一节全是实例,每一条都回到原始字节核对过,零推测。 ## 先看自指率 规范网址标签最常见的用法是自指,也就是首页的规范网址就写首页自己。121个有这个标签的站里,严格按字符串比,自指的有96个,79.3%;忽略末尾斜杠之后是112个,92.6%。 另外有一个数字值得单独说:指向另一个域名的规范网址,一个都没有。跨域规范网址在技术上是允许的,但它风险极高,等于把自己这一页的权重让给别人。这批中大型品牌站里零出现,说明这条底线大家守得还不错。 标签页的地址最容易忘了自指,Shopify博客tag标签URL优化 (https://zhangwenbao.com/shopify-tag-url.html)含301重定向实战。 把权重让给别人这件事,Google出站链接会损害SEO吗 (https://zhangwenbao.com/outbound-links-negative-signals-link-graph.html)从链接图谱算过。 还有一个小发现:有一个站的首页写了两条规范网址标签,值相同。这在规范里属于未定义行为,搜索引擎通常会忽略全部或者取第一条。值相同所以没造成实际伤害,但它说明这个页面上有两个模块都在写这个标签,而它们互相不知道对方存在。 ## 九个不自指的站,四种毛病 站点类型 | 规范网址写的是 | 服务器实际服务的是 | 毛病 | 刀具品牌 | countryselector.canonical | 首页 | 模板变量没渲染 | 健身器材品牌 | 某个八月促销变体页 | 首页 | 把首页声明成了A/B变体 | 小家电品牌 | https:///www域名(三个斜杠) | 首页 | 字符串拼接多了一个斜杠 | 时尚电商 | 根路径 | 一个二级路径 | 声明与服务不同页 | 自行车品牌 | 带国家语言前缀的路径 | 根路径 | 多了一层地区前缀 | 户外品牌 | 以home.html结尾的路径 | 目录形式的路径 | 文件名与目录形式并存 | 家具品牌 | 不带www | 带www | 域名规范化没做全 | 家具与美妆品牌各一 | 不带端口号 | 地址里带着443端口 | 跳转时把默认端口写死了 | 插件互相覆盖是常态,WordPress标签相关文章实战 (https://zhangwenbao.com/wordpress-adds-related-article.html)记过一次反模式拆解。 逐条说几个最有意思的。 第一个是刀具品牌那条,原始字节是一个相对路径,文件名就叫“countryselector.canonical”。这明显是模板里的变量名没被替换掉,把变量名本身当成路径输出了。浏览器会把它解析成一个不存在的地址,而这个错误在页面上完全看不出来,因为规范网址标签本来就不显示。 第二个是健身器材那条。它的首页规范网址指向一个叫“八月促销变体”的地址。这大概率是A/B测试工具留下的:测试期间把首页换成了变体版本,收工时忘了把标签改回来。这个错误的性质比看上去严重,因为它等于在告诉搜索引擎:我的首页不是首页,那个促销页才是。 模板标签调用写错的形态类似,模板标签怎么调用 (https://zhangwenbao.com/aspcms-labels-calling-instructions.html)有速查表。 实验期的数据也会骗人,A/B测试赢了上线却掉了 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)问题出在那26天。 第三个是那个三个斜杠的。协议后面本该是两个斜杠,它写了三个。这种错误一眼就能看出是字符串拼接的时候,一边的变量自带了斜杠,另一边又硬加了一个。 ## 那两个带443端口的,我特意去核对了 数据里有两个站的最终地址带着443端口。第一反应是我自己的抓取工具加的,那样的话这条数据就得作废。 这类脚本问题怎么自动化兜住,独立站服务器怎么用cron把运维自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)给了做法。 所以我把这两个站的跳转链原样打了出来。结果是:一个站返回301,响应头里的目标地址原文就写着带443端口的地址;另一个站先返回308跳到裸域名,再返回301,目标地址同样带着443端口。两个都是它们自己写死在跳转响应里的,不是抓取工具的产物。 443是加密连接的默认端口,写不写在语义上没有区别,RFC 3986定义的统一资源标识符通用语法 (https://www.rfc-editor.org/rfc/rfc3986.html)里就把省略默认端口列为标准的归一化步骤之一。但作为字符串它就是不一样了,而搜索引擎处理地址的时候,很多环节是按字符串来的。一个多余的端口号,足以让同一个页面在某些系统里变成两个地址。 同一批站的响应头还量过别的,304状态码能省抓取预算 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)测了142个站。 响应头这一层还有别的机关,HTTP响应头的X-Robots与Vary机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)逐个讲过。 这件事也顺便说明了核对原始字节的必要性。如果我没去看那条跳转链,就会把自己工具的嫌疑当成事实写进结论里,这份数据就废了一角。凡是看着像自己工具造成的异常,一定要单独核一遍,因为它有一半概率不是。 ## 模板变量没渲染这类错,怎么防 那个把变量名当路径输出的案例,看着离奇,其实是最常见的一类模板事故。 工具打架时该信谁,收录数据到底信site命令还是GSC (https://zhangwenbao.com/site-search-operator-vs-gsc-coverage-accuracy-decision.html)给了三源校准法。 它的成因通常是变量名拼错、或者模板引擎的语法用错了一个符号、或者那个变量在这个页面的上下文里根本不存在。这三种情况下,多数模板引擎的默认行为是输出空字符串或者原样输出,都不报错。 危险就在这个不报错上。页面能正常打开,视觉上毫无异样,只有藏在头部的那一行字是错的。而头部这些标签恰恰是最没人看的地方。 标题标签也常踩这个坑,自定义title标签的5场景实战 (https://zhangwenbao.com/typecho-custom-title-header.html)有代码。 防它的办法有三个,从便宜到贵。最便宜的是上线前跑一次头部体检,把几个关键标签的值打印出来人工扫一眼,三分钟。中等的是写一条断言:规范网址必须以协议开头且能解析成合法地址,不满足就构建失败。最贵也最彻底的是前面说的那个统一函数,从源头上不给手写留机会。 ## A/B测试留下的残骸 那个把首页规范网址指向促销变体页的案例,属于另一类事故:临时状态被永久化。 服务器层还有20项值得查,服务器配置对SEO的影响清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)列全了。 A/B测试工具改页面的方式有两种。一种是客户端改写,脚本在浏览器里把内容换掉,这种通常不影响头部标签。另一种是服务端分流,直接给不同的人返回不同的页面,这种就会把整个页面连同头部标签一起换掉。 第二种更快也更利于收录,但它有个后遗症:测试结束之后,如果分流规则没有干净地撤掉,某些请求方还会一直拿到变体版本。而爬虫恰恰是那种最容易被规则遗漏的请求方。 做法上有一条硬规矩值得立:任何服务端分流的实验,实验期内变体页的规范网址必须指回原页,而不是指向自己。这样即使规则忘了撤,收录层面也不会出事。 顺便一提,这个案例里的变体页名字带着月份。也就是说这个测试至少是那个月做的,而标签一直挂到现在。促销早就结束了,它的名字还留在这个站对自己身份的声明里。 实验前先把测量框架定清楚,埋点之前先设计测量框架 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)是同一个顺序问题。 ## 首页到底要不要写自指的规范网址 既然92.6%的站都写了,这个问题好像不用问。但它值得问,因为理由不是随大流。 自指标签的价值不在于告诉对方这一页在哪,那件事跳转和链接已经说清楚了。它的价值在于把一堆你没预料到的变体地址收拢回来。 想想一个首页可能有多少个能打开的形式:带与不带www、带与不带末尾斜杠、带广告追踪参数的、带社交来源标记的、被人手工加了大写字母的、带一个无意义空参数的。这些形式里的每一个,只要能返回200,就是一个独立的候选地址。 而它们全都会输出同一份HTML,也就都会带上那个自指标签,指回同一个正版地址。一行标签,把无穷多个变体一次性收拢。这就是它真正的作用。 过滤器产生的地址最多,电商过滤器SEO实战 (https://zhangwenbao.com/ecommerce-category-page-filters-seo-tips.html)对比了5类参数处理。 用robots去挡参数是另一条错路,robots.txt能禁止UTM追踪参数吗 (https://zhangwenbao.com/robots-txt-disallow-utm.html)讲了危害。 反过来说,如果你的站严格保证只有一个可达形式,其余全部301过来,那这个标签的边际价值确实不高。但真做到这一点的站极少——本文数据里81.8%的首页最终服务的地址跟输入的都不是同一个,这已经说明地址形式的膨胀是常态。 所以结论很简单:写,而且写绝对地址。成本是一行,收益是把一类你永远数不清的问题一次性关掉。 ## 三十秒自查自指 不需要工具,一条命令加一次肉眼比对就够。 先取事实:对首页发一次跟随跳转的请求,把最终地址记下来。再取声明:把页面源码里那一行规范网址标签抠出来。两个字符串并排放着看。 比的时候按三层看:完全一样,很好;只差一个末尾斜杠,记成技术债;差别不止斜杠,那就是本文说的那9个站里的一员,需要单独查。 这个动作最值得做的时机有三个:接手一个新客户的站时、自己的站换过模板之后、以及每次改完跳转规则之后。三十秒,能挡住的是那种能挂几个月没人发现的问题。 顺带一提,本文那9个不自指的站,全都是行业里有名有姓的品牌。这个检查之所以没人做,不是因为它难,是因为它太简单了,简单到不像是一件需要专门去做的事。 ## 为什么hreflang的默认版本和结构化数据最容易打架? 上一节留了个尾巴,这一节把这12条分歧全部摊开。 同一批站的另一项体检,211个站有152个拿不出图标 (https://zhangwenbao.com/favicon-site-name-platform-picks-one.html)也是这种简单到没人做的检查。 ## 12条分歧,形态高度一致 这12条我逐个回到原始字节核对,全部为真,没有一条是解析错误。而且它们的形态整齐得惊人: 行业 | hreflang默认版本指向 | 结构化数据写的是 | 骑行服饰 | 根路径 | 中文站路径 | 快时尚 | 欧盟子域名 | www主域名 | 母婴用品 | 美国英文版路径 | 裸域名 | 香氛品牌 | 欧盟英文版路径 | 裸域名 | 厨房小家电 | 英文版路径 | 中文版路径 | 清洁电器 | 全球子域名 | www主域名 | 储能设备 | 美国站路径(带双斜杠) | 中国站路径 | 园艺工具 | 芬兰语版路径 | 裸域名 | 数码配件 | 裸域名 | 中文站路径 | 骑行装备 | 英国英文版路径 | 裸域名 | 水晶饰品 | 英文版路径 | 中文版路径 | 充电配件 | 阿联酋英文版路径 | 裸域名 | 同类核对方法也能用在竞品研究上,产品评测只做SEO就够了吗 (https://zhangwenbao.com/competitor-research-seo-aeo-advanced-method.html)讲了深度研究法。 形态只有两种。一种是默认版本指向某个具体的国家或语言版本,而结构化数据写裸域名或者www主域名;另一种更麻烦,两边各指一个不同的语言版本,一个说英文站是主的,另一个说中文站是主的。 顺带说一个细节:储能设备那个站的默认版本地址里带着一个双斜杠的路径。这又是一处字符串拼接问题,和前面那个三斜杠是同一类毛病,只不过换了个位置。这类拼接错误在多语言站上出现的频率明显更高,因为地址是由好几段变量拼起来的,每一段的斜杠归属都要有人拍板。 多版本内容的组织逻辑,AI搜索时代内容优化的底层逻辑 (https://zhangwenbao.com/context-first-seo-ai-search-strategy.html)给了5步框架。 换域名时的拼接问题更集中,换域名后台跳转登不上 (https://zhangwenbao.com/wordpress-change-domain-access-management-login-jump-solution.html)记了三种改法。 ## 两个团队,两套主页的定义 这12条分歧的成因,我认为是一个组织问题,不是技术问题。 多语言模块的负责人在回答一个运营问题:一个说着我们不支持的语言的用户来了,把他送到哪里最不容易流失。答案通常是英文站或者主要市场站。 结构化数据的负责人在回答一个品牌问题:我们这个品牌的官网地址是什么。答案通常是裸域名,因为那是印在名片和包装上的那个。 两个答案在各自的语境里都对。但它们被放进同一份HTML之后,就变成了两个互相矛盾的身份声明,而读这份HTML的机器不知道这两句话是两个部门说的。 要说明的是,这两个字段本来就不必相同,这不是硬性错误。真正的风险在于当同一个页面上有三四个来源、彼此各指一处的时候,接收方必须自己挑一个作为准。挑的过程你参与不了,结果你也控制不了。 ## 多语言站的地址为什么特别容易拼错 这12条里出现了两处斜杠拼接错误——一个三斜杠,一个双斜杠路径。这不是巧合。 单语言站的页面地址通常是两段:域名加路径。多语言站至少是四段:域名、语言码、地区码、路径,有时候还要加上货币或者渠道标识。每一段之间的斜杠归谁管,就是一个需要被明确规定的事。 常见的错法是这样:域名变量自带末尾斜杠,拼接的时候又硬加了一个,于是出现双斜杠;或者反过来,两边都以为对方会加,结果一个都没有,两段直接粘在一起。 更麻烦的是,这类错误在浏览器里往往看不出来。浏览器对多余的斜杠很宽容,双斜杠路径照样能打开,页面正常显示。只有当这个地址被当成字符串去比较、去归并、去做规范判断的时候,多出来的那个字符才会变成一个真正的分歧。 防它只有一个可靠办法:地址拼接必须走同一个函数,函数内部统一规定每一段的斜杠归属,其他地方一律不许手工拼。听起来是老生常谈,但这批中大型站里做到的还不到三分之一。 ## 先统一哪一处 如果你的站已经有了这个问题,改造有先后。 先统一规范网址和og:url,这两个通常最容易,改一处就行,而且它们的分歧率本来就低,改完能立刻拿到一个干净的基准。 再统一结构化数据里的地址。这一步的难点是那个字段的语义容易被理解成品牌官网而不是当前页面地址,所以改之前要先跟负责的人对齐它到底该写什么。我的建议是:页面级实体写当前页地址,组织级实体写裸域名,两者分开,别混在一个字段里。 面包屑也是一处地址声明,面包屑导航SEO怎么做 (https://zhangwenbao.com/seo-breadcrumbs-types-schema-implementation.html)讲了四种类型。 实体之间的关系怎么搭,Schema的graph与知识图谱 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)讲了做法。 最后才动多语言声明。它牵涉的运营逻辑最多,改动前要跟负责各市场的人确认兜底策略。这一步经常改不动,改不动也没关系——只要另外三处是齐的,剩下一处的分歧对结果的影响就小得多。 ## 这12个站的行业分布说明了什么 把这12个站的行业排一下:骑行服饰、快时尚、母婴、香氛、厨房家电、清洁电器、储能设备、园艺工具、数码配件、骑行装备、水晶饰品、充电配件。 看不出行业集中,但看得出另一个共同点:它们全都是做多个国家市场的品牌,而且大多数是在近几年才快速铺开市场的那一类。 这个共同点比行业更有解释力。一个站的地址结构,通常是在它只有一个市场的时候定下来的,那时候地址简单、声明也少。等到开第二个、第三个市场,语言前缀、地区路径、国家子域名一层层加上去,而最初那套地址生成逻辑没有跟着重构。 多市场该建几个站,出海该建一个大站还是多个品牌小站 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)算过这笔账。 新市场的地址由新模块生成,老的声明还留在老地方。于是分歧不是某一天突然出现的,是随着市场扩张一点点积累的。 这一条对正在做多市场扩张的独立站特别有用:地址结构的重构窗口在开第二个市场的时候,不在开第五个的时候。第二个市场的时候改,成本是一个模板;第五个的时候改,成本是五套跳转规则加一次全站地址迁移。 ## 默认版本到底该指向哪 既然这个字段是分歧的重灾区,那就把它该怎么设说清楚。 新市场的节奏怎么排,新品上市从蓄水到复盘的GTM框架 (https://zhangwenbao.com/dtc-new-product-launch-gtm-prelaunch-presale-playbook.html)是另一篇。 它的定义是:当访问者的语言和地区都匹配不上你声明的任何一个版本时,把他送到这一版。所以判断标准只有一个——对一个你完全不了解的陌生人,哪一版最不容易让他掉头就走。 常见的三种选法各有代价。选英文国际版最稳,代价是对已有明确主市场的品牌来说,可能把本该进主市场的人分流走了。选主市场版转化最好,代价是一个来自完全不相干地区的人会看到一堆他买不到的商品和一个不对的货币。选一个语言选择页最中立,代价是多一次点击,而且这个页面通常内容很薄。 陌生访客的意图怎么判断,看SERP后落地页要改成什么样 (https://zhangwenbao.com/search-intent-mismatch-diagnose-from-serp.html)给了7步。 我的倾向是选英文国际版,但有个前提:这一版必须是真的能下单的完整站,不能是个空壳。兜底页的价值在于它是一个能完成交易的落点,不是一个礼貌的转接台。 还有一条容易被忽略的:这个字段的值应该和规范网址体系兼容。如果你的默认版本指向某个具体语言版本,那那个版本的页面自己得有正确的自指标签,别让它既是别人的兜底又不承认自己是一页。 能不能完成交易还看支付,独立站支付方式怎么配 (https://zhangwenbao.com/dtc-local-payment-methods-multi-gateway-conversion.html)按地区拆过。 ## 多语言站还有一个额外的风险 顺着上一句往下说,多语言站有一处特别容易出事,而且出了事很难查。 正确的做法是每个语言版本的页面都自指:中文版的规范网址写中文版自己,英文版写英文版自己,然后靠多语言声明把它们串成一组。这样每一版都是独立的一页,各自可以被收录。 常见的错法是让所有语言版本都指向同一个主版本。写的人的想法通常是“这些是同一个页面的不同语言,应该归到一起”——听着很合理,实际后果是除了主版本之外的所有语言版本都放弃了自己被收录的机会。 每个页面类型该配什么,Shopify怎么给页面加结构化数据 (https://zhangwenbao.com/shopify-schema-seo-guide.html)讲了128种类型怎么选。 这个错误的隐蔽之处在于,它在短期内看不出问题:页面都能打开,多语言声明也写了,报表上也没有报错。只有当你发现某个市场的自然流量一直起不来,去查那个语言版本的收录状态时,才会看到它被归并掉了。 判断方法很简单:打开任意一个非主语言版本的页面,看它的规范网址写的是自己还是别人。写的是别人,那就是这个错。三十秒能验完,但很少有人想到去验。 收录状态变化有时滞,已收录页面加noindex后多久消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)做了6场景实测。 ## 81.8%的首页,你输进去的地址不是它最终服务的那个 还有一层事实经常被漏掉:连你自己都不一定知道你的首页地址是什么。 ## 跳转是常态,不是例外 132个能正常给出页面的首页里,97个是经过跳转才拿到的,占73.5%。而最终服务的地址与最初输入的地址不是同一个字符串的,有108个,占81.8%。 这两个数字要分开看。前者说的是发生了跳转,后者说的是跳转之后地址真的变了——包括加www、加末尾斜杠、加语言前缀、换成国家子域名这几类。 抓取报告里跳转类问题占多少,Google抓取报告怎么读 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)给了占比与排查顺序。 81.8%意味着什么?意味着在这行里,你输入的地址和你实际拿到的地址不一样,是绝对的常态。那些声明字段如果是照着某个人记忆里的地址手写的,出错几乎是必然的。 ## 跳转链上还藏着别的东西 这批数据里的跳转链,短的一步,长的三四步。步数多本身不算问题,但每多一步就多一个能写错的地方,前面那两个443端口就是在跳转链上写死的。 跳转配错就变成软404,GSC 404错误修复 (https://zhangwenbao.com/google-search-console-404-error-fix-guide.html)讲了排查实战。 多域名跳转怎么配才干净,多域名301跳转到主域名的完整配置 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)有实例。 还有一类值得留意:跳转的目标随请求方变化。上一篇量到过好几个站,浏览器身份被送到中国站,搜索引擎身份被送到国际站。这种情况下,你的规范网址标签在两个不同的落点上会呈现出完全不同的一致性,而你从自己电脑上只能看到其中一种。 做审计的时候,最终地址这一列必须从真实的跳转链里取,不能用你输入的那个。这听起来是常识,但很多现成工具默认报的是你输入的地址。 中国这一侧的分流更复杂,中国搜索流量不是百度的天下 (https://zhangwenbao.com/china-fragmented-search-ecosystem-seo-2026.html)拆了5个战场。 工具看到的和真实的可能不同,网页历史快照还能怎么查 (https://zhangwenbao.com/webpage-cache-snapshot-viewing-tools-guide.html)列了5个工具。 ## 一个可以马上做的检查 打开命令行,对你的首页发一次跟随跳转的请求,把每一跳的状态码和目标地址打印出来,再把最终地址和页面里的规范网址标签放在一起看。 这个动作三十秒,能一次性回答三个问题:跳了几次、最后落在哪、声明的和落点是不是同一个。如果这三个答案里有任何一个让你意外,那就说明你对自己网站地址的认知已经过期了。 ## 跳转链的四种常见形态 把这批站的跳转链归一下类,形态就四种,各有各的坑。 第一种是补全型:从裸域名跳到带www,或者从http跳到https,或者补上末尾斜杠。这一类最常见也最无害,只要声明字段写的是跳转之后的那个形式就行。 第二种是分地区型:根据来源把你送到某个国家站。这一类要小心,因为不同请求方看到的终点不同,你的声明只能对准其中一个。 第三种是路径迁移型:老地址跳到新地址。这一类的风险是链条会越接越长,改版几次之后可能变成三跳四跳,每一跳都是一次损耗。这类跳转应该用永久重定向,MDN关于301永久重定向的条目 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/301)写明了它与临时重定向在缓存与方法保留上的差别。 按设备分流是同一类做法,JS判断移动端并自动跳转 (https://zhangwenbao.com/js-judges-mobile-automatically-jumps-to-mobile.html)讲了它的SEO代价。 迁移后的层级关系要重新声明,Shopify博客多级面包屑导航 (https://zhangwenbao.com/shopify-blog-breadcrumb.html)给了3种方案。 第四种最少见也最麻烦:跳到一个功能页,比如国家选择页或者语言选择页。这种情况下你的首页实际上不是内容页,而是一个中转站,而中转站的内容通常很薄。本文数据里那个把变量名当路径输出的站,它的模板变量名恰好就叫国家选择器,多半就属于这一类。 ## 裸域名还是带www,到底怎么选 这个老问题在这批数据里有个新角度。 导航把人送到哪一屏是同一类问题,类目导航改版做了三轮 (https://zhangwenbao.com/category-navigation-scope-custody.html)讲了那一屏缺什么。 从收录角度看,两者没有高下,选哪个都行,关键是选定之后全站统一。真正的差别在运维层面:带www的可以用别名记录,裸域名在很多解析服务上只能用A记录,切换服务商的时候会更麻烦一点。 这批数据里绝大多数站选了带www,少数几个选了裸域名,其中一个就出了前面那个家具品牌的问题:规范网址写不带www,服务器服务带www。这不是选错了,是选完之后没有把所有地方都改过来。 资源类型也跟这个选择有关,GSC网域与网址前缀资源对比 (https://zhangwenbao.com/domain-property-vs-url-prefix-property-in-gsc-which-is-better.html)给了6场景选型。 所以决定权其实不在选哪个,而在于你有没有一份清单,列出所有需要写死这个选择的地方:跳转规则、规范网址、站点地图、社交标签、结构化数据、内部链接、广告落地页、邮件模板里的链接。漏掉任何一处,都会在某个时刻变成一份竞争性证据。 ## 跳转链每多一跳,损耗在哪 常有人问多一跳到底有没有代价。有,但不在你以为的地方。 邮件那一侧的链接也归它管,Flow和Campaign到底有什么区别 (https://zhangwenbao.com/email-marketing-flow-vs-campaign-automation-broadcast-strategy.html)讲了两者的分工。 权重传递的损耗这两年已经被官方多次淡化,正常的永久跳转基本不损失权重。真正的代价在另外三处。 第一是抓取成本。每一跳都是一次完整的请求往返,链条越长,抓完同样数量的页面需要的请求次数越多。对页面数量大的站,这笔账是实的。 权重从哪来,谷歌SEO外链建设的16种白帽做法 (https://zhangwenbao.com/google-seo-link-building-strategies.html)讲了获取路径。 第二是延迟。用户端每一跳都要重新建连接、重新握手,在跨境网络条件下一跳可能就是几百毫秒。三跳跳完,首字节时间可能已经超过了大多数人的耐心阈值。 第三,也是跟本文最相关的:链条越长,中间某一跳写错的概率越高,而中间跳的目标地址几乎没有人会去检查。前面那两个带443端口的案例,一个就出现在两跳链条的第二跳上。 首字节时间怎么优化,TTFB怎么优化才不白费 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)串起了缓存与抓取。 实践建议是把链条压到一跳。改版多次积累下来的老跳转,与其一层层接,不如定期把它们摊平成直接指向最终地址。这个动作在跳转规则文件里是一次批量替换,成本很低,但很少有人做。 ## 跳转链该被记下来 还有一件几乎没人做但成本极低的事:把关键页面的跳转链定期记一份。 做法就是每周对首页和几个主要入口跑一次跟随跳转的请求,把每一跳的状态码和目标地址存成一行文本,带上日期。存三个月,你就有了一份跳转链的历史。 记录多了要管好,服务器日志怎么管才不爆盘 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)有轮转方案。 这份历史的价值在出事的时候才显现。有一天某个页面的地址在搜索结果里变了,或者广告落地页开始报审核不通过,你打开这份记录,一眼就能看出跳转链是哪天变的、变成了什么。没有这份记录,同样的问题要靠回忆和猜测排查,通常要花掉半天。 它跟前一篇提到的身份可达性监测可以合并成同一个脚本:同一次请求,既记状态码和字节数,也记整条跳转链。多存两个字段而已。 ## 11个站的首页根本没有规范网址标签,会怎么样? 反方向也得看。 ## 没有声明,接收方就自己定 132个站里有11个的首页完全没有规范网址标签,覆盖百货、家居、快时尚、母婴、咖啡机几个大类,都不是小站。 没有这个标签不等于会出事。搜索引擎在没有声明的情况下会自己选一个作为规范版本,判断依据包括哪个地址被链接得更多、哪个跳转的终点、哪个内容更完整、哪个在站点地图里。选得对的概率其实不低,尤其是结构简单的站。 问题出在两种情况。一种是同一份内容有多个可达地址——带参数的、带追踪码的、带地区前缀的——这时候它可能选中你不想要的那一个。另一种就是开头那个案例:几个域名共用过同一个停放页或者过渡页,内容一模一样,它就可能把你的地址归并到别人那儿去。 选完还要分层,Google分层索引揭秘 (https://zhangwenbao.com/google-index-tiers-base-zeppelin-landfill.html)讲了三层的差别。 买域名前该查什么,域名生成器怎么用 (https://zhangwenbao.com/domain-generator-naming-strategy-tld-seo-guide.html)讲了命名策略与避坑。 ## 为什么共用过停放页会导致这种结果 这个机制值得讲清楚,因为它解释了那张吓人的截图。 搜索引擎判断两个地址是不是同一个页面,用的是内容相似度。两个域名在某段时间里都指向同一个域名注册商的默认停放页,那段时间它们的内容是逐字节相同的。系统就会把它们归成一组,从组里挑一个当代表。 等你把新站上线了,你这个地址的内容变了,但归并关系不会立刻解除。它需要重新抓取、重新比较、重新分组,而这个过程是有滞后的。这也是官方建议“过几周再看”的原因。 这一条是采信型故障的典型特征:你改了,但它要等;等多久不由你定,而且没有任何进度条。 抓取频率能不能提,Google抓取预算优化的12项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)给了边界。 ## 新站上线时该做的三件事 如果你正好在做一个新域名的站,这三件事能明显缩短那个等待期。 第一,首页和所有重要页面都写上自指的规范网址标签。它不是万能的,但它是你唯一能直接表达意图的地方。 第二,站点地图提交上去,并且确保里面写的地址和规范网址标签完全一致,包括末尾那个斜杠。站点地图是一份很强的信号,它和标签一致的时候,两份证据是叠加的;不一致的时候,是互相抵消的。 第三,尽快让新内容跟老的停放页产生足够大的差异。内容差异越大,归并关系解除得越快。这也意味着上线初期就该有真实的内容,别拿一个只有导航的骨架页占着。 这份文件写错的方式很多,Sitemap到底怎么写才不出错 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)收了2400个站的坑。 内容要形成共识才被引用,AI搜索不引用你的共识层6信号 (https://zhangwenbao.com/seo-consensus-layer-ai-search.html)给了90天路径。 ## 参数地址是最容易被忽略的那份证据 没有规范网址标签的站,最大的风险来自参数。这一节单独说,因为它在电商站上普遍存在。 一个商品页可能同时有这些形式能打开:原始地址、带广告追踪参数的、带社交分享参数的、带站内搜索来源标记的、带筛选条件的、带排序方式的。它们的内容完全相同,地址各不相同。 每一个能打开的形式,都是一份独立的证据。你在广告里投了三个月带追踪参数的地址,那个形式被点击了几十万次,还被别人复制粘贴分享出去——从证据强度上说,它未必比你那个从没人链接过的原始地址弱。 处理办法按力度分三档。最轻的是保证所有参数形式都输出指向原始地址的自指标签,这样参数再多也归一。中等的是在服务器层把已知的无意义参数剥掉再跳转过去。最重的是干脆不产生这些地址,改用别的方式传递来源信息。 要提醒一句:不要用robots规则去屏蔽参数地址。屏蔽的后果是接收方读不到那些页面上的规范网址标签,反而没法把它们归并到正版上,问题会变得更难解决。这是一个经典的把采信型当送达型处理的错误。 ## 那11个站有什么共同点 把这11个没有规范网址标签的站放在一起看,共同点比我预想的清楚。 筛选页该不该禁有判别法,电商筛选URL要不要写Disallow (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)给了三类分法。 第一个共同点:它们里有好几个是本文前面提到的多语言大站,也就是说地址结构最复杂的那一批里,反而有几个连最基本的声明都没有。 第二个共同点更有意思:这11个里有几个的首页HTML本身就很薄,几千字节,内容基本靠脚本在浏览器里生成。这就跟前两篇的结论接上了——一个页面如果连正文都没在字节里,那它多半也不会在字节里认真声明自己是谁。 多市场要面对的不止一家搜索引擎,2026全球搜索引擎格局 (https://zhangwenbao.com/search-engine-landscape-seo-strategy-guide.html)做了多平台拆解。 第三个共同点是它们大多有地区跳转。首页不是一个内容页,而是一个把你分流到某个国家站的中转站。中转站的模板往往是单独做的,很简陋,SEO模块根本没挂上去。 三条合起来指向同一个判断:缺失地址声明,很少是一个孤立的疏忽,它通常是首页架构本身有问题的一个症状。发现这一条,值得顺手去看看这个首页还缺什么别的。 ## 新站上线的时间线,大概长这样 既然讲到新域名,把这条时间线摊开写一遍,省得干等着焦虑。 上线当天到第三天,通常什么都不会发生。这几天的任务是把该做的都做完:自指标签、站点地图、内部链接形式统一、内容填满。这三天做的事,决定了后面几周的走向,之后再补效果就差很多。 第一周到第二周,开始被抓取,但收录状态大概率还是模糊的。这段时间最容易做出错误动作——看到状态不对就去改标签,改完再等,等不到再改。忍住。 新站前期该干什么,零预算SEO增长的5个策略 (https://zhangwenbao.com/zero-budget-seo-traffic-growth-guide.html)附了30天清单。 第二周到第四周,如果有域名共用历史这类问题,这段时间是它解除归并的窗口。判断依据是抓取记录:如果抓取频率在上升、抓到的页面数在增加,那就是在正常推进。 一个月之后还没有变化,才轮到重新排查。这时候排查的对象也不该是标签,而是那份竞争性证据到底还在不在。 这条时间线是个粗略的参考,具体快慢跟站的规模、内容更新频率、外部链接情况都有关。它的用处不在精确,在于给出一个心理上的锚——知道两周内没动静是正常的,就不会在第五天去做那个会重置周期的动作。 ## 它为什么必须自己选一个? 讲完现象,回到机制。这一节是全篇的落点。 ## 接收方面对的是一堆证据,不是一条指令 很多人对规范网址标签有个误解,以为它是一条命令。官方文档里其实写得很明白,它是一个强信号,不是指令。这一点在最早的规范里就定下来了——RFC 6596对canonical链接关系的定义 (https://www.rfc-editor.org/rfc/rfc6596.html)用的词是偏好版本,而不是唯一版本。 接收方要做的是从一堆证据里选出最可信的那个。证据包括:你的规范网址标签、你的站点地图、你的内部链接指向、你的跳转终点、别人链接到你时用的地址、你的多语言声明、你的结构化数据。这七样里只有前两样是你明确写下的,其余五样都是你在无意中产生的。 另一份也常被误当成指令的文件,robots.txt写废了网站会从谷歌消失 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)讲了它的真实约束力。 内链的形式也是一份证据,给内链加UTM参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)讲了取舍。 当这些证据一致的时候,选择是显然的。当它们打架的时候,系统按自己的权重去评,而这个权重表你看不到。 本文的数据说明的正是这件事:23%的页面在给出互相矛盾的证据,而它们的所有者大概率不知道。 ## 两个并列字段就是采信型的标志 怎么一眼认出你正在面对一个采信型问题?看官方界面上有没有两个并列的字段,一个记录你说的,一个记录它选的。 规范网址是最典型的一对:一栏叫“用户声明的规范网址”,另一栏叫“谷歌选定的规范网址”。这两栏并排存在,本身就是在告诉你,第二栏可以不等于第一栏。 你写的 | 它可能改成的 | 它依据什么改 | 规范网址标签 | 它选定的规范网址 | 跳转终点、内外链形式、内容相似度 | 页面标题 | 搜索结果里显示的标题 | 正文里的大标题、查询词、标题长度 | 页面描述 | 结果里显示的摘要 | 正文中与查询词相关的段落 | 商家名称 | 展示出来的名称形式 | 官网、其他平台上的写法一致性 | 结构化数据里的分类 | 实际展示的富媒体类型 | 字段完整度与页面内容匹配度 | 这张表里的每一行都遵循同一个逻辑:你提供的是一份候选,不是一个指令;对方在你的候选和它自己观察到的证据之间做选择。 识别方法也统一:凡是官方界面上把“你填的”和“实际的”分成两栏显示,或者措辞里出现选定、检测到、系统判定这类词,都属于这一类。 反过来,那些只有一栏的字段,比如robots指令、跳转规则、页面上真实存在的文字,基本都是指令型的,说了就算。分清哪些是指令、哪些是候选,比记住每个字段该怎么写更有用。 这个模式在别处也一样成立。页面标题你写一份,搜索结果里显示的可能是另一份;描述你写一份,摘要可能是它自己从正文里摘的;商家名称你填一份,展示出来的可能是它认定的另一个形式。凡是措辞里出现“选定”“检测到”“系统判定”这类词的字段,都属于这一类。 认出来之后,处置方式跟另外两种病完全不同:你不能直接指定结果,只能去改变证据的分布。 商家名称的展示形式也是它定的,112个独立站里17个在犯的双语重复 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是实测。 标题被改写的机制,title写了为什么被Google改写 (https://zhangwenbao.com/title-meta-description-seo-mechanism-at-scale.html)讲了截断与重复。 ## 能控制的和不能控制的,得先分清 面对采信型问题,最耗人的不是修不好,是分不清哪些事根本不该花力气。 完全能控制的有四样:跳转规则、页面里的各处声明、站点地图、内部链接使用的地址形式。这四样加起来已经覆盖了证据里的大部分权重,而且改动成本都不高。 部分能控制的有两样:外部链接使用的地址形式、内容与其他页面的相似度。前者你能做的只是在给出链接时统一形式,别人怎么写你管不着;后者你能做的是让内容尽快变得独特。 哪些下滑不该算你的账,流量下降不等于SEO失败 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)给了8个维度。 完全不能控制的有三样:对方的评估周期、对方的权重表、以及历史上这个域名发生过什么。开头那个案例里的域名共用历史,就属于这一类——你什么都没做错,你只是买了一个有前科的域名。 把三类分开之后,动作就清楚了:在四样完全可控的上面做到极致,在两样部分可控的上面做能做的,在三样不可控的上面只做一件事——等,并且记下开始等的日期。 域名本身的选择也有讲究,带连字符的域名到底伤不伤SEO (https://zhangwenbao.com/hyphenated-domain-name-seo-impact-overseas-site-decision.html)讲了官方口径。 这个分类还有一个心理上的好处。采信型问题最折磨人的地方是没有确定的反馈,很容易让人不断折腾。知道哪些事已经做到头了,才敢停手。 ## 投入和产出之间没有确定的时间关系 采信型还有一个让人难受的属性:滞后。 缺失型是阶梯式的,补一处多一处,改完刷新就能验证。送达型是开关式的,关掉就通,验证同样立刻。采信型两样都不是——你改完之后要等它重新抓取、重新评估、重新分组,而这个周期从几天到几周不等,取决于你的站被抓取的频率。 这个属性带来两个实际后果。一是不要在等待期里反复改,每改一次等于把评估周期重置一次。改完就停手,记下日期,两周后再看。 二是不要用短期数据去判断有没有效果。三天没变化说明不了任何事,因为它可能还没重新抓到那一页。 ## 七份证据,权重各不相同 既然结果由证据决定,那就得知道哪份证据重。官方没有公布权重表,但从公开文档和大量案例里能推出一个大致的强弱顺序。 证据 | 强度 | 你能控制吗 | 301跳转的终点 | 最强 | 完全能 | 规范网址标签 | 强 | 完全能 | 内部链接普遍使用的形式 | 较强 | 能,但要改很多处 | 站点地图里列出的地址 | 中 | 完全能 | 外部链接使用的地址 | 中 | 基本不能 | 多语言声明 | 中偏弱 | 能 | 结构化数据里的地址 | 弱 | 能 | 这张表有两个用法。 第一,当低强度的证据和高强度的证据打架时,通常不会翻盘,但会增加不确定性。结构化数据写错一个地址不太可能真的改变结果,但它会让本来清晰的信号变模糊。 第二,也是更重要的:最强的那份证据恰好是你最容易忘记的那一份。跳转规则往往是几年前配的,配的人可能已经离职,而它的权重比你精心维护的标签还高。做审计时先看跳转,再看标签。 ## 站点地图这份证据被低估了 表里排中间的站点地图,实际使用中经常被当成一个纯粹的收录工具,忽略了它同时也是一份地址声明。 老配置该定期回看,Apache服务器怎么安全加固 (https://zhangwenbao.com/apache-server-security-hardening-version-hide-directory-access-control-waf.html)讲了从版本隐藏到访问控制。 你在站点地图里写的每一个地址,都是在说这个形式是正版。如果站点地图里写的带末尾斜杠,而规范网址标签写的不带,那你就自己给了两份互相打架的证据,而且两份都出自你手。 这类不一致极其常见,因为站点地图通常由另一个插件或者另一个脚本生成,它有自己的地址拼接逻辑。这又回到了同一个根因:地址不是在一处生成的。 所以对齐审计的最后一步永远是比对站点地图,而且要逐字符比,不要肉眼扫。肉眼扫是看不出末尾斜杠差异的,这也是为什么这类问题能长期存在。 站点地图自己生成也一样,免插件sitemap实战指南 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)讲了分页与缓存策略。 ## AI答案里的那个官网链接,取自哪一份 这一节往前看一步,因为地址声明的读者名单这两年变长了。 当一个AI答案提到某个品牌并附上官网链接的时候,那个地址是从哪来的?可能的来源有三个:它抓到的页面里的结构化数据、它抓到的页面的实际地址、或者它从别的信息源里学到的那个地址。 三个来源里,结构化数据是唯一你能直接写死的那个。而它恰恰是本文那张证据强度表里排最后的一份。在传统收录的语境里它权重最低,在实体信息整理的语境里它反而是最直接的来源。 AI引用到底看什么,3000条数据揭开AI搜索引用的认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)做了实证。 这个错位有实际含义:同一个字段在两条链路上的重要性不一样,所以不能只按其中一条链路去决定怎么写它。 具体的建议是把两类实体分开写。描述当前这个页面的实体,地址写当前页;描述组织或者品牌的实体,地址写你希望被当成官网的那一个,通常是带www的裸首页。两个写在一个结构化数据块里没问题,写成两个并列的实体即可,别让它们共用一个地址字段。 另外要提醒的是,本文数据里结构化数据的覆盖率是65.2%,也就是有三分之一的站在这个字段上什么都没说。在传统收录时代这不算大事,在实体信息被大量整理的今天,它等于把这道题的答案权完全交给了别人。 ## 为什么加大声明力度反而会把事情弄糟? 这是采信型最典型的误判动作,值得单独讲。 实体权威怎么建,AI搜索时代实体权威的四阶段协作框架 (https://zhangwenbao.com/entity-authority-ai-search-seo-content-collaboration.html)给了路径。 ## 常见的三种错误反应 发现它选的不是你写的,大多数人的第一反应会落在这三种里。 第一种是再声明一遍。既然它没听我的,那我多写几个地方,规范网址写、社交标签写、结构化数据也写。这个动作的实际效果,是把证据数量从三份增加到五份,而如果新加的这两份和已有的不完全一致,你反而制造了新的矛盾。 第二种是写得更绝对。把相对路径改成绝对路径,把参数全带上,把大小写统一。这些动作本身没错,但它们解决的是格式问题,而你面对的是真分歧。 第三种是反复提交重新抓取。这个动作除了重置评估周期之外,没有别的作用。 旧内容怎么改才有效,把旧版更新为AI搜索可信来源 (https://zhangwenbao.com/revise-old-content-for-aeo-ai-search-optimization.html)给了12步。 为什么这三种反应这么本能?因为在日常生活里它们通常有效。别人没听清,你就再说一遍、说大声一点、说得更肯定,这套办法对人管用。对一个从多份证据里做加权判断的系统,它一点都不管用,因为问题从来不是音量。 这也是我把这三种病分开讲的原因。缺失型和送达型都可以靠“做得更多”来解决——多补一处内容、多开一个白名单。只有采信型不行,它要的是做减法。在一个习惯了加法的行业里,减法是最反直觉的那个动作。 正确的动作只有一个:去找那份竞争性证据,然后消除它。不是加强你的声明,是让对方看不到别的选项。 ## 怎么找出那份竞争性证据 按这个顺序找,命中率最高。 先看同一个页面上的其他声明来源。把本文列的那五处逐个抠出来放在一起比,这是最容易命中的一步,本文数据里23%的页面在这里就能找到问题。 再看这个内容有几个可达地址。带参数的、带追踪码的、大小写不同的、带与不带末尾斜杠的、分页形式的,逐个试一遍能不能打开。能打开的每一个,都是一份竞争性证据。 然后看内部链接。你自己的导航、页脚、面包屑、站点地图里,指向这个页面用的是哪个形式的地址。如果站内用的是A形式而标签写的是B形式,那是一份很重的反向证据。 站内搜索页就是典型的一批,站内搜索URL该Disallow吗 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)对比了4种方案。 页脚这块地怎么用,独立站页脚不是杂物抽屉 (https://zhangwenbao.com/ecommerce-footer-design-trust-conversion.html)讲了它的收口作用。 最后才看外部因素:别人链接你时用的地址、有没有域名共用历史、有没有做过站点迁移。 ## 消除的手段有三种 找到之后,处置手段按力度从轻到重是三种:改成一致、跳转过去、彻底不可达。 改成一致最轻,适合那些本来就该一致的字段,比如同一页上的几处地址声明。跳转过去中等,适合那些有历史原因存在的替代地址,让它们都301到正版。彻底不可达最重,适合那些纯属意外产生的地址,比如测试环境泄漏出去的那一套。 三种手段的共同点是:它们都在减少选项,而不是在加强主张。这是采信型问题的通用解法,也是它跟另外两种病最根本的区别。 测试环境泄漏怎么清,Staging站被索引后的8步清除 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)给了四层防御。 ## 一个真实的处置顺序 保哥去年处理过一个户外用品客户的类似情况,过程可以直接照搬,就不展开细节了,只讲顺序。 症状是某个分类页在搜索结果里始终显示成另一个带筛选参数的地址,标题和描述都是那个筛选版本的,看起来很像被降级了。 第一步不是改标签,是列可达地址。列完发现同一份内容有五个形式能打开:干净地址、带排序参数的、带每页数量参数的、带一个历史遗留的活动参数的、以及一个大小写不同的。 筛选和搜索结果页的落地问题,40个电商站的站内搜索页实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)是同一类。 第二步查内部链接。结果很打脸:站内导航里那个入口用的就是带排序参数的地址,因为设计上希望用户进来默认按销量排。整站所有指向这一页的链接,用的都是那个参数版本。 第三步才明白发生了什么。规范网址标签写的是干净地址没错,但站内几百条内部链接都在投票给参数版本,而内部链接的证据强度比标签只低一档。两边打架,对方选了票多的那个。 第四步的处置是改内部链接,不是改标签。把导航入口改成干净地址,默认排序改成在服务端处理而不体现在地址上。改完之后大约三周,显示的地址换了回来。 这个案例里有两条经验值得记:一是错的地方和症状出现的地方经常不是同一处;二是等待期真的有三周,中间那两周什么都没发生,很容易让人以为改错了而去乱动。 ## 一份地址声明对齐清单,怎么跑? 最后落到可以照着做的步骤上。 等待期里怎么验证,提示词级前后测实验框架 (https://zhangwenbao.com/ai-search-prompt-experiment-framework.html)讲了怎么设计对照。 ## 五步,一个页面十分钟 第一步,取事实。命令行发一次跟随跳转的请求,记下每一跳的状态码和最终地址。这是基准,别用你输入的那个地址。 第二步,取声明。把页面源码保存下来,抠出规范网址、og:url、hreflang的默认版本、结构化数据里的url这四处。注意要看原始源码,不是浏览器渲染之后的,因为有些框架会在运行时改写它们。 第三步,做分层比对。先严格比,不一致的再忽略末尾斜杠比一次,还不一致的再忽略www比一次。记下它在哪一层变成一致,那一层就是问题的性质。 第四步,列可达地址。把这个页面所有能打开的地址形式列出来,逐个确认它们是不是都指回了同一个规范版本。 第五步,比对站点地图。确认站点地图里那一条和规范网址标签逐字符一致。 ## 全站怎么抽样 一个页面十分钟,全站显然跑不完,所以抽样规则比跑得多更重要。 按模板抽,不要按流量抽。地址声明是模板层的东西,同一个模板生成的一万个页面,问题是完全一样的。所以先把站里的模板类型列出来——首页、分类页、商品页、内容页、专题页、搜索结果页,每类抽一个就够。 然后在每类里挑最复杂的那一个,不是最典型的那一个。带参数最多的、路径最深的、语言版本最多的那一个,最容易暴露拼接问题。典型页面往往是模板作者测试时用的那个,早就被检查过了。 抽样审计的完整方法,AI时代技术SEO的五个新层次 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)列了42步。 最后补两个特殊对象:一个是最近上线的新模板,一个是从别处迁移过来的老页面。这两类是问题最集中的地方。 加起来大概八到十个页面,一个下午能跑完,覆盖的是全站绝大多数的地址生成路径。比起跑一万个页面拿到一万条重复的结论,这个投入产出比高得多。 ## 做成例行检查的两个触发点 全站每页都跑不现实,选触发式更划算。 第一个触发点是上线新模板或者新插件。地址声明基本都是模板层的东西,改模板最容易一次性改坏几十个页面的一致性。 第二个触发点是上多语言或者开新市场。本文的数据已经很清楚了,分歧率最高的四对全部跟多语言声明有关。开新市场之前先把地址生成逻辑统一到一处,比开完之后再来对齐便宜得多。 ## 把三项检查合成一张表 这三篇讲的三件事,实操上可以合并成一次抓取、一张表。 抓取只做一次:对目标页面发一次跟随跳转的请求,把每一跳和最终的HTML都留下来。这一份字节能同时喂给三项检查。 第一项是内容可读性:把标签剥干净,数一下剩多少可读字符。低于阈值就是空壳,这一项决定了后两项还有没有意义。 第二项是身份可达性:换两三个爬虫身份把同一个地址再要一次,比状态码和正文长度。有差异就是送达问题。 内容在哪一步丢的,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)讲清楚了。 第三项就是本文这一项:把几处地址声明抠出来,跟最终地址做分层比对。 防护层怎么查,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)拆过一遍。 三项跑完,一个页面十几分钟,输出是三行结论:它有没有内容、机器拿不拿得到、拿到之后认不认它说的身份。这三行合起来,基本覆盖了一个页面在机器那一侧可能出的所有基础问题。 交付的时候把三项并排放在一张表里,比分成三份报告有用得多——因为它们经常互相解释。一个页面同时在第一项和第三项上出问题,那多半是模板整个没做好,不是三个独立的疏忽。 这一项通常和抓取可达性放在同一张表里交付。原因是它们回答的是同一个问题的两个部分:机器能不能拿到你的页面,以及拿到之后认不认你说的那个身份。 ## 用什么工具跑 不需要买东西,命令行加一个能解析HTML的脚本就够了,但有几个细节决定了结果准不准。 取源码要用跟随跳转的方式,并且记录整条链,别只要最后那一份。很多现成工具默认只给你最终内容,跳转链上的信息就丢了。 日志那一侧有现成工具,服务器日志分析工具教程 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)讲了怎么读预算浪费。 解析要用真正的HTML解析器,不要用正则去抠标签。这批数据里有个站的规范网址标签中间插了一个额外属性,还有个站的标签闭合方式不一样,正则很容易漏掉或者抠错。 结构化数据要能处理嵌套。现在很多站用的是图结构,一个脚本块里放好几个实体,顶层的地址字段可能在第二层。只取第一个url字段是这类脚本最常见的错。 解析这件事有更稳的写法,5种PHP代码识别搜索引擎蜘蛛 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)含反转换法。 嵌套结构怎么写才对,FAQPage结构化数据的8步实战 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)有完整示例。 还有一条容易忽略:要看原始源码,不是浏览器渲染之后的。有些前端框架会在运行时改写头部标签,两者可能不一样,而搜索引擎和大多数抓取器读到的是前者。 ## 报告怎么写才有人改 这类发现最容易被写成一堆没人看的技术细节,最后归档了事。有效的写法是三列。 单页应用的问题更集中,SPA站AI爬不到的真相 (https://zhangwenbao.com/ai-search-skips-spa-rendering-passage-level.html)对比了四种渲染模式。 第一列写事实:这一页的几处声明分别是什么,服务器实际服务的是什么,逐字符列出来,别做任何美化。 第二列写它落在哪一层:格式差异还是真分歧。这一列决定了优先级,也决定了归谁改。 第三列写具体动作:改哪个文件的哪一处,改成什么。不要写“建议统一地址声明”这种话,写“把主题模板里那一行改成调用规范地址函数”。 最后加一句预期时间:改完之后需要等两到三周才能看到变化,这段时间内不要反复调整。把这句写进报告,能省掉后面好几轮“怎么还没效果”的沟通。 交付物写成规范才不返工,内容简报怎么写才能一次到位 (https://zhangwenbao.com/content-brief-production-spec-engineering.html)是同一个思路。 ## 交给别人做的时候,怎么验收 这类活儿经常外包给建站服务商或者代运营,验收的时候有几个问题值得直接问出口,因为它们不太好糊弄。 第一个问题:这个站的地址是在哪一处生成的?能指出具体是哪个文件、哪个函数的,说明确实动过手;答不上来或者说各个模块自己处理的,那就是本文说的那种状态。 第二个问题:末尾斜杠这件事是怎么定的?这个问题看着琐碎,但它是本文数据里最大的一块差异来源。一个连这个都没有明确约定的项目,其余的一致性多半是碰运气碰出来的。 第三个问题:多语言的兜底版本指向哪,为什么是它?答案里如果只有技术理由没有运营理由,说明这个值是插件默认给的,没人真的做过决定。 第四个问题:怎么验证改完之后生效了?期待的答案是一个可以复现的检查步骤,而不是一句我们会持续关注。能给出检查步骤,说明对方知道这件事需要等,也知道等完之后看什么。 四个问题不到十分钟,比看一份几十页的审计报告更能判断对方的水平。这不是刁难,是因为这几个问题的答案恰好覆盖了地址一致性的全部要害:在哪生成、格式怎么定、多版本怎么选、改完怎么验。 反过来,如果你就是被问的那一方,这四个问题也值得自己先答一遍。答不上来的那一个,通常就是你的站下一次出问题的地方。 ## 什么时候该停手 最后说一个容易被忽略的判断:不是所有分歧都值得修。 有三种情况可以放着不管。第一种是那些语义上本来就允许不同的字段,比如多语言的兜底版本和页面身份,前面已经说过。第二种是末尾斜杠这类格式差异,记成技术债,等下次改模板时顺手带上。 第三种最需要判断力:当修复的成本明显超过风险的时候。比如一个多年不更新的历史专题页,它的几处声明对不上,但它既没有流量也没有商业价值,那就别动它,把时间花在商品页上。 反过来,有三种情况必须立刻修:首页、主要分类页、以及正在投放广告的落地页。这三类的共同点是它们既有流量又有多个可达形式,正是分歧最容易产生实际后果的地方。 老页面还有没有价值,主题权威做到位为什么还是不选你 (https://zhangwenbao.com/topical-authority-limits-ai-search-entity-evidence.html)列了18大盲区。 还有一条判断线可以直接用:如果一处分歧会导致搜索结果里显示出一个你不希望别人看到的地址,那它就必须修,不管流量多少。地址是给人看的,一个带着测试参数或者促销活动名的地址出现在搜索结果里,损失的是信任,那笔账不好算但确实存在。 ## 最后一个数字 再回到那张表:严格比29.4%,放宽到极限77.0%。中间那57个站被一个斜杠救回来,而剩下的23%,无论你怎么放宽规则都救不回来,因为它们说的确实不是同一件事。 信任是怎么攒起来的,出海独立站的社会证明体系 (https://zhangwenbao.com/dtc-social-proof-system-reviews-ugc-trust-conversion.html)讲了信任工程。 你的页面对自己是谁说了三遍以上,而每四页里就有将近一页,三遍说的不一样。在这种情况下,接收方选了一个你不喜欢的答案,其实一点都不奇怪——它只是从你给的几个答案里挑了一个。 三篇写到这里,那条链算是走完了:东西得先在字节里存在,然后得送到对方手上,最后它到了还得被采信。三段各有各的判据、各有各的投入曲线,也各有各的典型误判。同一句“没通过”,在这三段里分别意味着你还没做、你做了但它没到、它到了但不算数。 如果只带走一件事,那就带走这个提问顺序:先问这个信息除了眼睛还有谁能读到,再问换个身份要一次结果一不一样,最后问这个结论是我声明的还是它算出来的。三个问题,十分钟,能省掉几周朝错误方向使的劲。 ## 常见问题解答 ## 搜索平台里显示的规范网址和我写的不一样,是不是我写错了? 不一定。那两个字段是并列的,一个记录你声明的,一个记录系统选定的,它们本来就允许不同。规范网址标签在官方定义里是强信号不是指令,系统会把它和站点地图、内部链接指向、跳转终点、外部链接使用的地址、多语言声明、结构化数据一起当成证据来评估。所以先别改标签,先去找那份跟你的声明打架的证据。本文实测的132个首页里,有23%在页面内部就存在无法用格式差异解释的真分歧。 三个问题各自的验证方法,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)讲了日志那一条。 ## 末尾那个斜杠到底要不要紧? 对收录来说通常不要紧,主流搜索引擎会把根域名带不带末尾斜杠当成同一个地址。但它在本文的数据里贡献了最大一块差异:严格按字符串比只有29.4%的页面所有声明一致,只忽略末尾斜杠就跳到74.6%,一条规则救回57个站。它真正的意义是一个信号——同一个页面上的两个模块连这种事都没对齐,说明它们之间没有共享的地址生成逻辑,今天差一个斜杠,明天上多语言就会差一个语言前缀。 ## 为什么hreflang的默认版本和其他声明最容易打架? 因为它回答的是另一个问题。规范网址回答的是这一页的正式地址是哪个,而hreflang的默认版本回答的是语言都匹配不上时把用户送到哪一版,前者是身份,后者是兜底策略,本来就不必相同。问题在于多语言模块通常由另一套插件或者另一个团队负责,它按自己的逻辑挑兜底版本,完全不知道页面上还有别的地方在声明身份。本文数据里,它跟结构化数据的分歧率是31.7%,跟规范网址是28.1%,都是全表最高的几项。 ## 首页没有规范网址标签会出什么问题? 大多数时候不会出问题,系统会自己选一个规范版本,结构简单的站选对的概率不低。风险集中在两种情况:一是同一份内容有多个可达地址,带参数的、带追踪码的、带地区前缀的都能打开,这时候它可能选中你不想要的那一个;二是这个域名过去和别的域名共用过停放页或者过渡页,那段时间内容逐字节相同,系统会把它们归成一组并挑一个代表,而这个归并关系在你上线新内容之后不会立刻解除。 ## 发现选定的规范网址指向一个陌生域名,我该做什么? 按顺序做三件事。先确认自己的页面有自指的规范网址标签,并且站点地图里的地址与标签逐字符一致,包括末尾斜杠。再尽快让内容与那个共用过的停放页产生足够大的差异,差异越大归并关系解除得越快。最后是等,官方给的建议是几周之后再看。切忌在等待期里反复改动或者反复提交重新抓取,每改一次都等于把评估周期重置一次,反而更慢。 ## 多写几个地方声明同一个地址,是不是更保险? 正好相反。这是采信型问题里最典型的错误动作。多加两处声明,如果它们和已有的三处不完全一致,你就把矛盾从三份证据扩大到了五份。本文数据里,规范网址与og:url的分歧率只有2.2%,因为它们通常是同一段代码生成的;而涉及多语言声明的几对分歧率都在20%以上,正是因为它们出自不同的模块。正确的做法是减少选项,不是加强主张。 ## 地址里那个443端口是怎么来的? 是站点自己写死在跳转响应里的。本文数据里有两个站的最终地址带着443端口,我特意把它们的跳转链原样打出来核对过:一个站的301响应头里目标地址原文就带着端口,另一个先308跳到裸域名再301到带端口的地址,都不是抓取工具加的。443是加密连接的默认端口,写不写在语义上没区别,但作为字符串就是两个不同的值,而地址处理有很多环节是按字符串来的。 ## 这套对齐检查要不要全站都跑? 不用,选触发式更划算。两个触发点最值得盯:上线新模板或新插件的时候,因为地址声明基本都是模板层的东西,改一次能同时改坏几十个页面;以及上多语言或开新市场的时候,本文数据里分歧率最高的四对全部与多语言声明有关。日常抽查的话,首页、一个分类页、一个商品页各跑一次就够,一个页面十分钟。 ## 规范网址和og:url不一致,严重吗? 严重。这一对在本文数据里的分歧率只有2.2%,是全表最低,因为它们在绝大多数系统里由同一段代码生成,或者一个直接引用另一个。它们不是达成了共识,是同一句话说了两遍。所以一旦你的站这两个字段对不上,说明连最容易一致的一对都出事了,几乎可以断定是两处分别硬编码的结果:有人在模板里手写了一个,又在插件设置里填了另一个。这类硬编码是所有地址不一致里最难发现的一种,因为它不遵循规律、只在某一页上错,逐页人工检查反而抓不到。 ## 怎么判断一个问题属于采信型而不是另外两种? 看官方界面上有没有两个并列的字段,一个记录你说的,一个记录它选的。规范网址是最典型的一对,页面标题、描述摘要、商家名称展示形式也都属于这一类。凡是措辞里出现选定、检测到、系统判定这类词的字段,结论都是对方算出来的,你只能通过改变证据分布去影响它,不能直接指定。这跟缺失型(东西不在字节里)和送达型(东西在但那次请求没拿到)的处置方式完全不同,用错了不只是无效,还会更糟。 ## 权威参考资料 ## robots.txt说允许,GPTBot仍有10个站进不去 - URL:https://zhangwenbao.com/robots-allow-vs-actual-delivery-bot-identity-audit.html - 分类:技术SEO - 发布:2026-08-14 | 更新:2026-08-15 - 摘要:网站内容一个字没改,自然流量却在两周里归零,购物列表全部消失,广告费还在照常扣。这类事故的拦截发生在边缘节点,你的服务器日志里干净得一条记录都没有。 - 关键词:技术SEO,AI爬虫,独立站运维,爬虫拦截 > **TLDR**:摘要:同一批211个独立站首页,这次换了7种身份各要一次,只看谁拿得到、谁拿不到。132个站愿意对普通浏览器给出真页面,在这132个上,Googlebot拿到97.7%,GPTBot拿到90.9%,而什么身份都不报的那一次只拿到48.5%。更意外的是反向:robots.txt里明确点过GPTBot名字的13个站,13个全都把页面交了出来;真正在送达环节挡住AI爬虫的,恰恰是那些robots.txt里一个字都没提过它的站。文章还记了一个55字节的402付费墙和一个字节数为0的418。 > 摘要:同一批211个独立站首页,这次换了7种身份各要一次,只看谁拿得到、谁拿不到。132个站愿意对普通浏览器给出真页面,在这132个上,Googlebot拿到97.7%,GPTBot拿到90.9%,而什么身份都不报的那一次只拿到48.5%。更意外的是反向:robots.txt里明确点过GPTBot名字的13个站,13个全都把页面交了出来;真正在送达环节挡住AI爬虫的,恰恰是那些robots.txt里一个字都没提过它的站。文章还记了一个55字节的402付费墙和一个字节数为0的418。 上一篇文章的结尾留了个尾巴。当时抓211个独立站首页,最后只剩132个能拿来做内容分析,剩下那79个要么连不上、要么撞上人机验证、要么直接被403挡回来。我说那79个的去向是另一篇文章的题目。 这就是那一篇。 那一篇把132份首页的可读字符逐个数了一遍,132个独立站首页有28个是空壳 (https://zhangwenbao.com/html-shell-page-readable-text-audit.html),算是这次实验的上半场。 先把两篇的关系交代一下,免得混。上一篇问的是:抓回来的字节里到底有没有字。这一篇问的是更前面的一个问题:字节到底有没有到你手里。前者是内容问题,后者是通路问题,而通路出事的时候,内容写得再好也没有任何意义。 这两个问题的先后顺序不能颠倒。先确认拿得到,再讨论拿到的东西够不够好。顺序反了,你会在一个根本没送出去的页面上花几周时间调标题、补描述、加结构化数据,然后困惑于为什么一点变化都没有。 先讲一件2026年8月中旬在圈子里传得挺广的事,原始报道是Search Engine Roundtable关于误配置内容分发网络重创SEO的那篇 (https://www.seroundtable.com/misconfiguring-cloudflare-seo-41865.html)。有位技术顾问接手了一个客户,客户的自然流量在两周里几乎归零。所有人第一反应都是算法更新,因为曲线掉得又快又干净,长得就像被核心更新削了一刀。查完之后真相是这样的:客户的IT外包商在内容分发网络的后台点开了一个爬虫控制开关,一键屏蔽所有机器人。 同样的顺序问题在流量诊断里也成立,收录、排名、流量是三件事 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)讲的就是别把三层混在一起查。 这类后台的选项密度确实高,独立站的缓存与回源率优化决策树 (https://zhangwenbao.com/cloudflare-cache-real-world-optimization-decision-tree.html)能帮你分清哪些开关碰得、哪些碰不得。 这一下同时打穿了三条业务线。搜索引擎抓不到,页面陆续掉出索引;购物广告的商品列表全部消失;而广告账户那边毫无察觉,钱照扣,一天没落下。整整两周,客户的网站内容一个字都没改过。 我把这件事记下来,不是因为它离奇,而是因为它太不离奇了。这一类故障有一个共同的形状:东西明明还在,只是那一次请求没拿到。它和“东西根本不存在”是两种病,药方还互为毒药——上一篇讲的是前者,这一篇讲的是后者。 掉出去之后怎么捞回来,页面不被Google收录的急救手册 (https://zhangwenbao.com/google-not-indexed-fix-playbook.html)按症状分诊列了完整流程。 更麻烦的是它的隐蔽性。缺失型故障你自己能查出来,抓一次页面剥掉标签数一数就完了。送达型不行,因为拦截发生在边缘,请求根本没到你的服务器。你的访问日志里干干净净,一条记录都没有,唯一记着这件事的是对方。 所以这篇文章不打算讲配置怎么点。配置面板一年改三次版,写下来第二个月就过期。它要解决的是更前面那个问题:一个页面拿不到,你怎么在十分钟之内判断它属于哪一种病。判据只有一条,后面会用211个站的实测数据把它撑起来——同一个地址,换一个身份再要一次,两次结果不一样,那就是送达型。 日志能回答什么、不能回答什么,AI爬虫到底有没有抓你的站 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)那篇分得很细。 把这类判据成体系地排一遍,AI时代技术SEO的五个新层次 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)是本站的审计总纲。 ## 一次开关被点开,为什么你的后台什么都看不到? 先把这类事故的形状讲清楚,不然后面的数据你会不知道该往哪儿放。 ## 三条业务线是被同一个动作打穿的 前面那个案例里最值得咂摸的细节,不是流量掉了多少,是三件事同时发生却互不通气。自然搜索的排名开始滑坡,购物广告的商品列表消失,付费广告继续正常投放并且正常扣费。 这三件事共用同一个前提:机器要能读到你的落地页。搜索引擎读不到就不给排名,购物平台读不到就下架商品,而广告投放系统的账单逻辑跟落地页能不能被读到没有强绑定,于是它就成了三条线里唯一没报警的那条。 商品列表这条线还有自己的资质门槛,跨境电商GTIN怎么申请 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)讲的是它另一头的合规要求。 这就是送达型故障最恶心的地方。它不会给你一个统一的报警,它会给你三个互相矛盾的信号。一条线沉默,一条线报警,还有一条线在正常收钱。你坐在中间,很难第一时间想到这三件事其实是一件事。 另一位顾问在同一周晒出了另一个案例。一家在线市场类网站被爬虫压得服务器扛不住,团队只好在防火墙层加了一层机器人访问限制,纯粹是为了让站活着。结果曲线掉得跟被算法更新处理过一模一样。他的原话是:这看着像核心更新甚至像垃圾内容更新,但它不是。 多个信号打架的时候需要一条共同的时间轴,SEO变更日志的企业站治理 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)给的就是这套记法。 被抓到扛不住是真实存在的,网站被恶意流量打崩时的识别与应急拦截 (https://zhangwenbao.com/wordpress-ddos-protection-guide.html)讲的是另一头的压力。 ## 为什么它长得像算法更新 两者的曲线确实很像,因为掉的都是“被收录页面能带来的流量”这一层。但形状上有几处能分开。 算法更新的下滑通常有结构:某一类页面掉得多,另一类掉得少,长尾和头部的比例会变,不同国家的市场往往不同步。防火墙误伤的下滑没有这种结构,它是整片的,所有类型的页面按同一个节奏往下走,因为拦的是请求,不看你是什么页面。 时间点也不一样。算法更新有一个业内共同的时间戳,你在几个行业媒体上都能查到同一天。配置误伤的时间戳只在你自己的变更记录里,而绝大多数团队根本没有变更记录这个东西。 还有一个更简单的分法:算法更新不会让你的购物广告商品列表消失。一旦出现“自然流量和商品列表同时消失,但广告费照常扣”这种组合,八成不是算法的事。 到底是谷歌动了还是你自己动了,排名突然抖一下的分层归因 (https://zhangwenbao.com/search-ranking-volatility-algorithm-layers-attribution.html)有一套现成判据。 抓取报告里那几类问题地址各占多少,Google抓取报告怎么读 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)给了排查顺序。 ## 日志里为什么找不到证据 很多人的第一反应是去翻服务器日志,看看搜索引擎爬虫是不是不来了。这个动作方向没错,但会得到一个误导性的结论。 拦截发生在边缘节点,也就是内容分发网络那一层。请求在那里就被判了,返回一个403或者一个人机验证页,然后结束。这一整趟往返,你的源站从头到尾都不知道发生过。所以你打开访问日志,看到的不是“爬虫来了被拒绝”,而是“爬虫没来”。 这两句话在日志里长得一模一样,含义差着十万八千里。前者是送达问题,后者是抓取需求问题,处置方式完全相反。分开它们的唯一办法,是去边缘那一层的日志里看,或者更直接——自己扮成那个身份去要一次。 边缘那一层能做的事比多数人以为的多,边缘SEO是什么 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)讲了它的原理与落地形态。 日志里要看得出真实来源IP,得先把格式配对,访问日志怎么配才查得清问题 (https://zhangwenbao.com/apache-customlog-logformat-access-log-configuration-remoteip.html)有现成模板。 ## 三条业务线,三套互不相通的告警 再往深一层看,这类事故之所以能拖两周,跟工具本身的设计也有关系。 搜索端的报告有延迟。抓取异常的数据从发生到出现在报表里,通常要隔一到三天,而且它默认按周汇总,一条曲线要跌得足够深才会引起注意。等你看见它,事情已经发生一阵子了。 购物端的反馈快一些,商品被拒会有邮件通知。但那封邮件的措辞通常是商品层面的,比如某个商品的落地页无法访问,看着像是单个商品的问题。收件人多半是运营,运营的第一反应是重新提交,而不是怀疑整个站的机器人策略。 这份报表的口径坑不少,GSC的数字为什么人人都读错 (https://zhangwenbao.com/google-search-console-complete-guide-diagnosis.html)逐项拆过一遍。 重新提交之后多久能回来,网站收录速度实操指南 (https://zhangwenbao.com/seo-kpi-guide.html)用三个平台的数据给了参考区间。 广告端根本不参与。投放系统关心的是出价、预算、素材和落地页能不能打开——注意,是能不能被真人打开。真人打得开,钱就照花。于是三条线里唯一实时的信号,恰好是唯一不报警的那一条。 这也解释了为什么这类故障的发现往往靠一个巧合:某个人手痒去查了一下收录,或者某个客户问了一句为什么搜不到你们了。它不是被监控发现的,是被人撞见的。 ## 变更记录这件小事,值多少钱 开头案例里有一个容易被忽略的细节:动手的是客户的IT外包商,而发现问题的是SEO顾问。这两个角色之间通常没有共享的变更记录。 我见过太多这样的结构了。网站的域名解析在一个人手里,内容分发网络在另一个人手里,服务器在第三个人手里,而对流量负责的那个人,往往三个后台都没有账号。出了事,第一小时全花在找谁动过手上。 解法不复杂,就是一份共享的变更记录,谁在哪个后台改了什么,一行字。它的价值不在于防止犯错,而在于把排查时间从两周压缩到两小时。 把这些分散的动作收进定时任务,独立站服务器怎么用cron把运维自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)是最省心的做法。 做外贸独立站的团队还有一个额外的复杂度:链路上的角色更多。域名可能在境外注册商,加速可能用了境外的内容分发网络,源站可能在境内,中间还可能夹着一层做国内访问优化的节点。每多一层,就多一个能悄悄拦人的地方。 这条链路上最常见的意外,是那些为国内访问做的优化配置。有些高防和加速产品的默认规则对境外来源的请求更严,而搜索引擎爬虫的出口恰恰全在境外。你为了让国内用户打开得快一点,顺手把抓取你的那批机器归进了可疑名单。 判断方法还是那一条:换个身份要一次。如果境内出口的请求正常、境外出口的请求被挡,那问题就在这一层,跟你的内容毫无关系。 主机放境内还是境外本来就是取舍,外贸独立站用国内主机还是国外主机 (https://zhangwenbao.com/china-vs-overseas-hosting-for-cross-border-independent-site.html)把备案、速度与合规摆在一起算过。 海外用户打不开的排障路径,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)是同一套方法的另一面。 如果连这个都推不动,还有一个更低成本的替代品:把关键配置定期导出成文本存一份。内容分发网络的规则、robots.txt、跳转规则,每周一次,存进版本库。下次出事的时候,跑一次比对就知道动了什么。 这也是我决定跑这次实验的原因。与其猜,不如把211个站排成一排,用7种不同的身份各要一次,看看谁拿得到、谁拿不到。 跳转规则这一层最容易失控,.htaccess的六层综合治理 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)给了可版本化的写法。 ## 同一个首页,7种身份各要一次会发生什么? 方法先交代清楚,因为这篇所有的百分比都挂在这一段上。 ## 7种身份是怎么选的 样本沿用上一篇那211个国际化独立站的域名,覆盖服饰、家居、消费电子、美妆、户外几个大类,都是有独立品牌、面向多国市场的品牌自营站。用同一批样本的好处是,两篇文章的结论可以直接互相印证。 身份一共7种,除了用户代理串不同,其余请求参数完全一致:都跟随跳转,都开压缩,都不执行脚本,超时都是同一个数,并发窗口也是同一个。 这批站几乎都做了多语言,国际化SEO和hreflang怎么做 (https://zhangwenbao.com/international-seo-hreflang-complete-guide.html)是理解它们结构的前提。 身份 | 它代表谁 | 为什么要测它 | 桌面Chrome | 一个普通访客 | 基线。它拿不到的,别人更拿不到 | Googlebot | 搜索引擎主力爬虫 | 拿不到就意味着掉索引 | Bingbot | 另一家搜索引擎 | 顺带覆盖多个AI答案系统的上游 | GPTBot | 一家AI公司的训练抓取 | 近两年被拦得最多的那一类 | ClaudeBot | 另一家AI公司的抓取 | 用来验证拦截是按名单还是按类别 | PerplexityBot | AI搜索产品的抓取 | 它的行为常被单独讨论 | 空用户代理 | 什么都不报的一次请求 | 对照组,用来看“沉默”的待遇 | 需要说清楚一件事:我报的这些名字全部是自称。用户代理串本来就是一行可以任意填写的文本,这一点MDN关于User-Agent请求头的说明 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent)里写得很清楚。请求是从一台普通的云服务器发出去的,IP地址跟这些爬虫官方公布的网段没有任何关系。也就是说,这台机器唯一做的事情,就是在请求头里写下一行字。 这个设定不是偷懒,它恰恰是实验的一部分。真爬虫的身份是可以被反查的:拿到IP之后做一次反向域名解析,再把解析出来的域名正向解析回去,看两次能不能对上。这套流程各大搜索引擎都公开写过。所以这次实验里,一个站放不放我进去,直接反映了它到底是按名字判断,还是按行为判断。 ## 基线不能拍脑袋定,得从数据里长出来 211个域名里,普通Chrome请求真正拿到一个像样页面的只有132个。剩下79个的构成是:32个直接给了人机验证页,18个连不上或者连接被重置,12个返回4xx,还有十几个返回了正文极短的空响应。 各家爬虫的串长什么样、怎么验,爬虫识别与UA分类指南 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)列得很全。 验证页背后那套机器人管理逻辑,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)拆过一遍。 所以后面所有比例都算在这132个上。这么定的理由是:只有当一个地址已经证明了它愿意对普通请求给出真页面,你才有资格说另一个身份被“挡住”了。否则你只是在统计一堆本来就打不开的站。 这一步看着琐碎,其实是这类审计最容易出事的地方。上一篇栽过一次跟头:把一批HTML里几乎没有可读文本的空壳页混进结构审计的样本,某个结论虚高了6.4倍,另一个虚高了11倍。判据一个字都没写错,错在样本边界。 ## 7种身份的成绩单 身份 | 拿到真页面 | 占132的比例 | 被挡或降级 | Googlebot | 129 | 97.7% | 3 | PerplexityBot | 127 | 96.2% | 4 | Bingbot | 125 | 94.7% | 6 | ClaudeBot | 122 | 92.4% | 8 | GPTBot | 120 | 90.9% | 11 | 空用户代理 | 64 | 48.5% | 63 | 数字在传播中走样是通病,10条最佳实践清单里8条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)是另一个例子。 先看前五行。搜索引擎爬虫和AI爬虫之间确实有差距,但没有传言里那么夸张——最高97.7%,最低90.9%,中间隔着不到7个百分点,换算成绝对数是9个站。 然后看最后一行。什么身份都不报的那一次请求,通过率直接砍掉一半还多。在这批站上,沉默比自称是AI爬虫的代价大得多。 抓取量的对比更悬殊,AI爬虫抓取量已超Googlebot 3.6倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)给了量级。 ## 什么算“拿到了页面” 这个判据得说清楚,因为它决定了上面每一个数字。 一次请求要算成功,得同时满足四个条件:状态码在200到299之间,最终正文超过1500字节,不是人机验证页,连接没有失败。任意一条不满足,都记成没拿到。 1500字节这条线是有来历的。这批数据里,正常首页的字节数中位数在3万以上,而所有验证页和错误页都在3000以下,中间有一段非常干净的空档。把线画在这个空档里,两边都不会误判。 字节这条线两头都要看,46个电商站的页面体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)量的是上限那一头。 识别验证页的办法是看正文特征:这类页面通常带一段固定的提示文案和一个挑战脚本,长度集中在2000到6000字节之间,标题字段往往是“请稍候”或者“正在验证”这一类。逐个人工核对过一批之后,我把特征固化成了几条字符串匹配。 这里有一类特别容易漏的情况:状态码200、正文只有几百字节的“薄响应”。全部211个域名里,普通Chrome拿到这种薄响应的有10个。它们不是拒绝,也不是验证,就是一个空壳——服务端返回了一个骨架,内容等着客户端去请求。 薄响应在监控里是最隐蔽的一种,因为它状态码正常、响应时间正常、甚至还有HTML结构。要发现它,只能加一条正文长度的检查。这也是上一篇文章的主题。 薄响应多半是渲染模式造成的,AI爬虫抓不到JS渲染的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)做过对比。 可提取性有更系统的量法,语义化HTML到底影响AI抓取吗 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)拿样本页跑过。 ## 为什么只测7种,不测更多 能测的爬虫身份远不止7种,光是叫得出名字的AI相关抓取程序就有二三十个。选这7个是有取舍的。 桌面Chrome和空用户代理是两个必需的极端,一个代表“最受欢迎的身份”,一个代表“没有身份”。中间五个覆盖了三类利益关系:会还流量的搜索引擎、只取不还的训练抓取、以及介于两者之间的AI搜索抓取。 这些串在日志里长什么样,AI Agent抓取日志的8类UA实测 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)做过完整账本。 再加身份的边际收益很低。同一家公司的多个抓取程序,在防护规则里通常被归进同一个分类,测三个和测一个的结果高度重合。而每多一个身份,就要多跑211次请求,对被测站是实实在在的负担。 时间窗也是个变量。全部1477次请求在同一个时间窗内跑完,避免出现“这个站是白天抓的、那个是深夜抓的”这种偏差。做送达型测试,时间必须被控制住,因为限流规则本身就是时间的函数。 ## 这次实验的边界在哪里 把局限性摆在前面说,后面的数字才好用。这份数据有四个地方是不能超出去解读的。 时间维度还有另一层,304状态码能省抓取预算 (https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html)量的是同一批站的条件请求能力。 第一,只测了首页。首页往往是全站防护配置最松的一页,因为它承担品牌展示的职责,谁都不希望它出问题。商品页、搜索结果页、筛选页的待遇通常更严。所以这批通过率应该被理解成上限,不是平均值。 第二,只采了一次。送达型故障有很强的时间性,限流是按窗口算的,某个站在某一分钟拒绝你,下一分钟可能就放行。单次采样能看出结构性的差异,看不出偶发的抖动。 搜索结果页本身也有问题,40个电商站的站内搜索页实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)发现查无结果和查得到长得一样。 响应时间和抓取预算是联动的,TTFB怎么优化才不白费 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)把两头串在了一起。 第三,只有一个出口。所有请求从同一台机器发出,IP在中国。这个条件对做了地理分流的站影响很大,后面有一整节在讲它。换个出口重跑,部分结论会变。 第四,身份是自称的。这既是实验设计的一部分,也是一个边界——它测的是“按名字放行”这套逻辑,测不出那些真的做了验证的站会怎么对待真爬虫。不过从结果看,做验证的站少到可以忽略。 跨语言的实体对不上是另一类顽疾,国际化SEO最难的不是hreflang (https://zhangwenbao.com/multilingual-entity-seo-cross-lingual-reconciliation.html)列了五大根因。 把这四条摆清楚之后,这份数据能支撑的结论其实只有一句话:在同一个时刻、同一个出口、只看首页的条件下,身份这一个变量能造成多大的差别。而答案是:能造成从48.5%到97.7%的差别。这已经足够说明问题了。 这个结果第一眼是反直觉的。按常理,你不说自己是谁,系统应该没有理由针对你。实际情况正好相反,而原因在下一节。 ## 空用户代理的通过率只有一半,被挡的63次里有59次撞上验证页 这一节讲那个对照组,因为它是整份数据里信息密度最高的一行。 ## 被挡的不是拒绝,是验证 空用户代理的63次失败里,59次拿到的是人机验证页,只有4次是干脆的403。这个比例几乎是压倒性的,说明拦它的不是一条黑名单规则,而是那套“我不认识你,先证明你是人”的默认逻辑。 验证页和拒绝页是两种东西。拒绝页的意思是“我知道你是谁,我不给”,验证页的意思是“我不知道你是谁,你先过一关”。前者针对身份,后者针对未知。 三层拦法各有代价,拦AI爬虫该不该 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)给了robots、UA与WAF的选型框架。 而机器过不了那一关。它不执行脚本,不算工作量证明,不点复选框。所以对一个不执行脚本的请求方来说,验证页在效果上等价于永久拒绝,只是它长得更客气一点,还回一个看起来正常的HTTP状态。 这里有个细节值得记一笔:这59个验证页里,很多返回的状态码不是403而是200,正文两千来字节。如果你的监控只看状态码,它们会被记成“正常”。一个返回200的验证页,在你的可用性看板上是绿的,在爬虫眼里是一堵墙。 ## 36个站的robots.txt字节数几乎一样 整理这批数据的时候,我顺手把每个站的robots.txt也抓了下来,本来只想统计规则。结果排序的时候看到一件怪事:132个站里有36个的robots.txt大小挤在3560到3720字节这个极窄的区间里。 状态码的语义值得复习,HTTP状态码怎么影响SEO (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)把301、302、404和410的选择讲透了。 自己写这份文件时有虚拟与物理的优先级问题,robots.txt该怎么写才不冲突 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)说明了顺序。 一百多个互不相干的品牌,文件大小差不到5%,这不可能是巧合。翻开内容一看,规则结构确实高度一致,屏蔽的都是购物车、结账、订单、后台那几类路径,只有域名和站点地图那几行不一样。这是同一个建站平台自动生成的模板。 真正有意思的是下一步:这36个站里,有34个的空用户代理请求撞上了人机验证页。比例是94.4%,远高于全样本的47.7%。 哪些页面类型值得屏蔽,电商robots.txt该屏蔽的7类页面 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)给了清单。 同一批站的另一处平台默认值,53个支付页的CSP实测 (https://zhangwenbao.com/payment-page-csp-factory-default-script-policy.html)也是配了等于没配。 把这两件事合起来看,结论就出来了:这批站的声明层是平台给的,送达层也是平台给的,店主两边都没有动过手。他打开后台,看到一份写得挺规整的robots.txt,很容易以为那就是自己网站对机器的全部态度。其实那份文件只是平台的说明书,真正决定谁能进门的是另一套他没打开过的开关。 顺带一提,做完归一化去掉域名之后,这36份文件里只有2份是完全一致的。模板是同一个,但每个站都被注入了那么一点点属于自己的东西——就像同一款毛坯房,交房时每家的电表编号都不一样。 ## 37个站还在配一个搜索引擎早就不读的指令 既然robots.txt都抓下来了,就顺手多量了几项。123份能正常解析的文件里,112份声明了至少一个站点地图,总共550行,平均每个站快5行。这个数字挺健康。 另一项就没那么健康了:37个站还在用Crawl-delay这条指令,占比30%。这条指令主流搜索引擎早就明确说过不支持,抓取节奏由它自己的算法决定。 站点地图写错的方式比想象中多,Sitemap到底怎么写才不出错 (https://zhangwenbao.com/xml-sitemap-complete-guide.html)收了2400个站踩过的坑。 两种robots指令的分工经常被搞反,robots.txt和meta robots什么时候用哪个 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)讲了边界。 这37个站不是写错了语法,是在对着一个没人听的收音机认真调频。它不会造成伤害,但它是一个信号:这份文件多半是很多年前配好之后就再没人碰过。一个多年没人碰过的robots.txt,和一套去年才上线的机器人防护策略,凑在同一个域名上,两边说的话对不上是迟早的事。 文件大小的分布也很有意思。最小的一份只有39字节,第二小的62字节,最大的一份57578字节,中间差着1476倍。57578字节是个什么概念?它比这批站里三分之一的首页HTML还大。 ## 一份39字节的robots.txt和一份57578字节的robots.txt 这两个极端值得各说几句,因为它们代表了两种完全不同的治理思路。 39字节那一份,内容只够写一行用户代理加一行允许。它传达的信息是:我们知道这个文件应该存在,所以放了一个,但我们没有任何要限制的东西。对一个内容不多、结构简单的品牌站来说,这个选择其实相当合理。 57578字节那一份是另一个极端。这么大的文件里塞的通常是成百上千条筛选参数的屏蔽规则,一条一条列出来。它反映的是一个站的URL空间已经膨胀到必须靠黑名单去管的地步。 这两种做法没有绝对的高下,但有一条经验是通用的:robots.txt的长度和站点的URL治理质量,往往成反比。规则越长,说明能被生成出来的无效地址越多。真正干净的架构不需要那么多条禁令。 筛选器地址爆炸有系统解法,电商筛选器URL不爆炸的方案 (https://zhangwenbao.com/faceted-navigation-filter-url-seo-crawl-trap.html)是一套8步流程。 无效地址进了索引就是另一笔账,索引膨胀的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)给了决策矩阵。 还有一个观察角度是站点地图声明。112个站在robots.txt里声明了站点地图,总共550行,平均每站4.5行。声明多行的通常是做了分卷的大站,这是好习惯。而那11个一行都没声明的站,等于把发现新页面这件事完全交给了链接爬行。 ## 平台默认值正在替大多数人做决定 把这一节的几个发现串起来,会得到一个比单条数据更重要的判断。 靠链接爬行就得看架构深浅,独立站网站架构怎么搭 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)讲的正是抓取深度。 36个站用同一份模板生成robots.txt,其中34个的空用户代理请求被同一套逻辑拦下。这不是36个独立的决策,这是一个决策被复制了36次。 这件事本身不坏,平台默认值通常是行业里比较稳妥的选择,能挡掉大量低质量抓取。问题在于所有权的错觉:店主以为那是他的配置,其实那是平台的配置,而平台会改。 平台改默认值的时候,通常会发一封邮件或者写一篇更新日志,很少有人读。等到下一次分类逻辑调整,你的站的行为会跟着变,而你的文档里什么都没变。 所以对用建站平台的独立站来说,有一个动作特别值得做:把平台生成的robots.txt完整存一份到本地,注明日期。每季度取一次,做一遍比对。变了不一定是坏事,但不知道它变了,一定是坏事。 ## 报一个名字就能进,129个站没有一个反查过我的IP? 现在回到那个最锋利的问题上。 托管平台悄悄改规则的事发生过,托管主机可能正悄悄拦AI爬虫 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)是一个真实案例。 ## 这台机器什么都没做,只是写了一行字 再强调一次实验的设定:发请求的是一台普通云服务器,IP在中国,跟任何一家搜索引擎或AI公司的官方网段都没有关系。它做的唯一一件事,是在请求头里写下Googlebot这个词。 结果是129个站把首页交了出来。 用代码识别蜘蛛有几种写法,5种PHP代码识别搜索引擎蜘蛛 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)含反向验证的做法。 没有一个站对我做过反向解析验证。这件事在数据里是可以证明的:如果有站做了验证,我这个身份必然通不过,因为我的IP反查出来是一家云厂商,怎么都不会变成googlebot.com。而129这个数字,跟真Googlebot能拿到的上限已经贴得很近了。 反向解析验证这套流程一点都不神秘,各大搜索引擎的官方文档里都写着,很多服务器软件也内置了。它的原理是拿到访问者IP,先反查域名,再把域名正查回IP,两次对得上才认。整个过程一次请求,几毫秒。 没人做的原因也不神秘:默认配置里它是关的,打开它需要一点点运维知识和一点点性能预算,而不打开它在绝大多数日子里不会出任何问题。 反查验证在Nginx上怎么配,Nginx拦AI爬虫与限速怎么不误伤Googlebot (https://zhangwenbao.com/nginx-ai-bot-blocking-rate-limit-rdns-misblock-account.html)有完整配置。 ## 按名字放行,就等于把门锁交给了报名字的人 把这条结论和上一节的空用户代理放在一起,整套逻辑就完整了。 这些防护系统的判据是名字,不是行为。你说你是Googlebot,它就当你是Googlebot;你什么都不说,它就把你当可疑对象拦下来验证。于是在这套规则里,愿意报名字的都进去了,什么都不说的反而被挡在外面。 这个机制有一个直接的商业后果,值得每一个正在纠结“要不要拦AI爬虫”的站长想清楚:你在后台勾掉的那些复选框,只对那些老老实实报名字的爬虫有效。真想拿你数据又不在乎规矩的那一类,改一行用户代理串就绕过去了,成本是零。 换句话说,这类拦截的实际效果是筛掉守规矩的,留下不守规矩的。你想拦的没拦住,不想拦的拦了一堆。 想知道它们到底抓什么,AI爬虫到底抓你什么 (https://zhangwenbao.com/ai-crawler-reverse-engineering-fetch-behavior-llms-strategy.html)是从代码逆向出来的。 ## 那三个连Googlebot都没进去的站 129之外还剩3个。Googlebot在这3个站上也没拿到页面,其中2个撞了验证页,1个连接直接失败。 撞验证页的那两个里有一个是运动品牌的主站。它的表现相当极端:普通Chrome拿到200,17万字节的完整首页;空用户代理也拿到200,同样17万字节;而Googlebot、Bingbot、GPTBot、ClaudeBot、PerplexityBot这五个身份,全部拿到366字节左右的403。 五个身份,五张几乎一样大的拒绝页,而那两个不报名字的请求畅通无阻。这个站的规则写得清清楚楚:只要你自称是爬虫,不管你是哪家的,一律不给。 17万字节还不算大,Googlebot抓取的2MB限制 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)才是那条硬线。 另一个站更彻底。普通Chrome和空用户代理都能正常拿到3万多字节的页面,五个爬虫身份全部是连接失败,状态码0,一个字节都没有,连robots.txt都取不到。这不是拒绝,是根本不建立连接。 ## 反向解析验证怎么开,为什么很少有人开 既然按名字放行有这么大的窟窿,那把验证打开不就完了?确实是这样,但阻力比想象中大。 这份文件取不到的后果很重,网站突然从谷歌消失多半是robots.txt写废了 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)讲了机制。 技术上,这个功能在主流的Web服务器和防护产品里都有现成的开关。原理前面说过:拿到访问者IP,先做反向域名解析,再把解析出来的域名正向解析回IP,两次对得上才认这个身份。搜索引擎官方也公布了可供比对的IP段清单,直接按段匹配更快。 阻力主要有三个。第一是性能,反向解析要走DNS查询,虽然可以缓存,但在流量高峰期加一层外部依赖,运维不愿意。第二是维护,AI爬虫的官方IP段列表更新频繁,而且不是每一家都公布,公布了的格式也各不相同。 按IP段核验伪造爬虫的做法,后台日志里的爬虫伪造识别 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)有5000个站的实战数据。 新出现的代理型爬虫怎么认,Google-Agent是什么 (https://zhangwenbao.com/google-agent-ai-crawler.html)单独讲过一个。 第三个阻力最实在:不打开它,99%的日子里什么都不会发生。伪装爬虫身份来抓数据的行为,对绝大多数独立站来说不构成可感知的成本,那就没人有动力去开这个开关。 我的建议是分层处理。对搜索引擎爬虫做严格验证,因为误伤代价太高,值得那点性能开销;对AI爬虫按名字放行或者拒绝就够了,反正真想绕的也绕得过去。把验证的力气花在你最不能失去的那个身份上。 ## 按行为判断长什么样 名字之外还有另一条路,就是看行为。这条路更贵,但更结实。 行为特征包括请求节奏、路径分布、是否读取样式和脚本资源、是否遵守robots.txt里的禁令、有没有携带合理的接受头。真爬虫和伪装者在这些维度上的差别,比用户代理串那一行字大得多。 举个具体的:真正的搜索引擎爬虫会去读robots.txt,而且会在抓取之前读。一个从来不取robots.txt、上来就直奔商品列表的请求方,不管它自称是谁,都值得怀疑。 抓取和渲染分几步,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)决定了哪些资源会被取。 再举一个:真爬虫的请求间隔通常是分散的,会跟着服务器响应时间自动调节;脚本化的抓取往往节奏固定得像节拍器。把访问日志按秒聚合画一条曲线,规律得过分的那一条,多半不是它自称的那个。 这些判断在中大型站上有成熟的产品可以买,小站自己做性价比不高。但知道这套逻辑存在是有用的,至少你在选防护产品的时候,可以问一句:你们是按名字判还是按行为判。 现成工具能省很多事,服务器日志分析工具教程 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)讲了怎么读出预算浪费。 ## 132个站里有77个至少挡了一个身份 把整张矩阵摊开数一遍,结果比单看某一行更有冲击力。 132个证明了自己愿意给普通请求真页面的站里,7种身份全部拿到页面的只有55个。剩下77个站,至少有一个身份在门外。占比58.3%。 这77个的构成很不均衡。绝大多数只挡了空用户代理那一个身份,属于默认防护带来的副作用,站主大概率不知道。真正对多个爬虫身份区别对待的,是十几个。 同一批站的另一项体检,211个站有152个拿不出图标 (https://zhangwenbao.com/favicon-site-name-platform-picks-one.html)用的是同一个样本池。 把这77个按“挡了几个身份”分一下:挡1个的最多,挡2到3个的少数,挡5个以上的只有个位数——但这几个站恰好都是知名品牌,防护配置明显是专门做过的。 这个分布本身说明了一件事:大多数的拦截不是决策,是默认值。真正做过决策的站,你从矩阵上一眼就能认出来,因为它们的模式是干净的、有规律的,而不是零星地缺一格。 顺带纠正一个常见的误解。行业里聊起爬虫拦截,语气通常是“大家都在拦AI”。这批数据不支持这个说法。真正针对AI爬虫做过区别对待的站是个位数,绝大多数站的AI爬虫通过率跟搜索引擎爬虫只差几个百分点。拦AI这件事在讨论区里的热度,远高于它在配置文件里的热度。 把这类矩阵纳入固定动作,企业网站SEO审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)给了完整检查表。 ## robots.txt写着允许,为什么GPTBot还是有10个站进不去? 这一节是全篇的骨架,讲的是同一个网站的两层配置怎么互相不认识。 ## 声明层和送达层是两套独立的系统 先把概念摆清楚。robots.txt是声明层,它写的是“我希望你抓什么”,本质上是一份君子协定,靠对方自觉遵守。防火墙、机器人管理、边缘规则是送达层,它决定“你这次请求到底拿不拿得到字节”,是物理层面的强制。 协定这个词是有出处的,机器人排除协议一直到2022年才正式成为标准文档,也就是RFC 9309定义的机器人排除协议 (https://www.rfc-editor.org/rfc/rfc9309.html),在那之前它当了将近三十年的行业惯例。而送达层那些工具,大部分是最近五到八年才普及的。 误以为它有强制力就会写出错误规则,robots.txt能禁止UTM追踪参数吗 (https://zhangwenbao.com/robots-txt-disallow-utm.html)是个典型误区。 抓取、索引、排名这条链的基本盘,搜索引擎到底怎么工作 (https://zhangwenbao.com/how-search-engines-work-crawl-index-rank.html)讲得最清楚。 两层的年龄差、归属团队差、更新节奏差,凑在一起就是本节数据的来源。 ## 写规则的和配防护的,通常不是同一批人 这个组织问题比技术问题更难解,但它才是错配的真正源头。 robots.txt归谁管?多数公司里归做SEO的那个人或者那个外包团队,因为它是SEO工具箱里的东西。改它不需要权限,只要能改网站根目录的一个文本文件。 防护规则归谁管?归运维或者安全。他们的KPI是可用性和防攻击,不是收录量。在他们的世界里,多拦一个来源是安全的,少拦一个是有风险的。所以每一次拿不准的时候,默认动作都是往紧了配。 不同页面类型的规则要分开配,各类页面的meta robots和canonical配置 (https://zhangwenbao.com/typecho-meta-robots-canonical-seo-rules.html)按5类页面拆过。 跨部门讲清楚价值有方法,老板听不懂SEO错其实在我们 (https://zhangwenbao.com/explain-seo-geo-value-to-non-technical-leadership.html)给了一套讲法。 这两拨人开会的频率,通常是一年一次,还是在出事之后。他们之间也没有共享的语言:一个说的是抓取预算和收录率,另一个说的是每秒请求数和阻断率。 有一个成本很低的改善办法,是把“爬虫可达性”变成一个双方都认的指标。做法是把本文那个每天跑的脚本的输出,同时发给这两拨人。同一个数字,两个部门看,比开十次会管用。 抓取预算这个词要用对,Google抓取预算优化的12项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)说明了它的边界。 更进一步,可以在防护规则的变更流程里加一个必选项:任何涉及机器人分类的改动,上线前跑一次身份对照。这个动作三分钟,能挡掉本文开头那一整类事故。 ## 两个方向的错配,各占一半 身份 | robots写允许,实际拿到 | robots写允许,实际没拿到 | robots写禁止根目录,照样拿到 | Googlebot | 106 | 1 | 15 | Bingbot | 105 | 4 | 12 | PerplexityBot | 106 | 3 | 13 | ClaudeBot | 100 | 8 | 14 | GPTBot | 99 | 10 | 13 | 上线流程里还该加一道防护,Staging站被索引后的8步清除 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)讲的是反方向的泄漏。 先看中间那一列。robots.txt明明写着允许,实际却没拿到页面,GPTBot有10个站,ClaudeBot有8个,Bingbot有4个,PerplexityBot有3个,连Googlebot都有1个。 这10个站的名单我逐个核过,涵盖家居、快时尚、手机配件、护肤、户外装备几个大类,没有明显的行业集中。它们的共同点只有一个:写规则的人和配防护的人不是同一批人。 再看最右边那一列,这个方向更值得玩味。robots.txt里明确写着禁止抓取根目录,服务器却照样把页面交了出来,Googlebot有15个站,ClaudeBot有14个,GPTBot和PerplexityBot各13个,Bingbot有12个。 同一批站的商家名称也体检过,112个独立站里17个在犯的双语重复 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是另一处细节。 这个方向严格来说不算故障,因为robots.txt本来就只约束自觉遵守它的一方,服务器没有义务照着它拦人。但它把那件事说透了:这两层根本不通气,谁也不知道谁写了什么。 ## 为什么错配总是往一个方向偏 把两列放在一起看,能看出一个规律:越是新出现的爬虫身份,声明与送达不一致的概率越高。Googlebot只有1个站错配,GPTBot有10个,差了整整十倍。 站内搜索页该不该禁,站内搜索URL该Disallow吗 (https://zhangwenbao.com/should-search-page-urls-be-disallowed-in-robots-txt.html)对比了4种方案。 原因不难想。Googlebot出现了二十多年,几乎所有防护产品的默认白名单里都躺着它,误伤它的成本人尽皆知,出厂设置就已经替你避开了。GPTBot是2023年才出现的名字,它落在哪一档、被哪条规则匹配到,取决于每家产品各自的分类逻辑,而这套分类逻辑还在频繁调整。 这条规律有实用价值:做排查的时候,别从最老的那个身份查起,从最新的那个查起。老身份大概率被默认放行了,新身份才是错配的高发区。 这些产品各自的抓取策略并不相同,主流AI搜索工具实测对比 (https://zhangwenbao.com/what-is-ai-search-tools-comparison.html)做过10款横评。 ## 那10个站分成三种形态 把robots.txt写允许却没送达的那批站逐个翻开,形态其实只有三种。 第一种是挑战型。服务端返回了人机验证页,状态码可能是403也可能是200。这类站的意思是“我不确定你是谁”,属于默认防护开得比较紧。这一类占了大头。 第二种是直拒型。干脆的403,正文很短,服务器字段指向某家边缘产品。这类是有人明确配过一条规则,只是配规则的人不知道robots.txt里写了允许。 第三种最容易被忽略:跳转丢失型。服务器返回301指向另一个地址,而那个地址对这个身份又是另一套待遇,跟着跳几次之后就断在半路。表面上没有任何拒绝动作,结果是一样的。 这三种的修法完全不同。挑战型要去调防护等级或者加白名单;直拒型要去找那条规则;跳转丢失型要去查跳转链本身。把它们混在一起当成同一个问题处理,是这类排查最常见的浪费。 跳转链本身也常出错,HTTPS 301跳转的双向实战 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)有可直接抄的配置。 ## 做一次两层对齐审计需要多久 这件事其实不难,难在没人把它当成一个固定动作。 做法是列一张两列的表。左边一列从robots.txt里抠出来:每个被点名的身份,允许还是禁止,禁止的是哪些路径。右边一列从实测里来:同一个身份实际拿到了什么。 然后只看不一致的行。左允许右没拿到,是误伤,优先级最高。左禁止右拿到了,是声明没有强制力,通常不用管,除非你本来指望它拦住什么。 一个中等规模的站,这张表连测带填半小时能做完。而它能回答一个几乎没人能立刻回答上来的问题:你的网站到底对哪些机器开着门。大多数团队对这个问题的答案,是基于三年前某一次配置的记忆。 有的爬虫根本不吃通配符,robots规则的星号对AdsBot无效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)就是一个例外。 保哥做技术审计的时候,这张表通常放在报告的第一页。原因很简单:它是整份报告里唯一一个客户看完会立刻打开后台去改的东西。 ## 点名了GPTBot的那13个站,一个都没有真挡住它 接下来这组数据是这次实验最出乎我意料的一条,它把上一节的结论又推进了一层。 让报告推得动预算有套讲法,预算会上SEO总被砍怎么办 (https://zhangwenbao.com/seo-budget-planning-and-roi-model-for-leadership.html)用的是商业语言。 ## 写过条款的,全部放行 123份能解析的robots.txt里,明确点过GPTBot名字的有13个站——不管是允许还是禁止,只要文件里出现过这个词就算。 这13个站里,GPTBot实际拿到页面的是13个。一个不落。 表态这件事有更可核查的写法,AI内容披露怎么写 (https://zhangwenbao.com/ai-usage-disclosure-negative-list.html)主张用不做什么的清单。 而剩下那110个从没提过GPTBot的站,GPTBot拿到页面的是99个,通过率90%。 身份 | robots里点过名的站 | 其中实际拿到 | 没点过名的站 | 其中实际拿到 | GPTBot | 13 | 13(100%) | 110 | 99(90.0%) | ClaudeBot | 10 | 10(100%) | 113 | 104(92.0%) | PerplexityBot | 12 | 12(100%) | 111 | 107(96.4%) | 三个AI爬虫身份,三条一模一样的结论:凡是在robots.txt里认真写过它的站,没有一个在送达层挡住它;真正挡住它的,全部来自那些robots.txt里一个字都没提过它的站。 ## 这个反差说明了什么 第一层解释是最直白的:认真写过AI爬虫条款的团队,说明有人专门想过这件事。想过这件事的人,通常也会去检查防护规则有没有误伤,两层是同一批人配的,自然对得上。 第二层解释更有意思。没写过条款不代表没态度,恰恰相反,那110个站里挡住GPTBot的11个,多半是买了一套“一键拦AI爬虫”的服务,钱付了,开关开了,规则由服务商维护。他们的态度写在账单上,不写在robots.txt里。 这也就意味着,你去读一个站的robots.txt,读到的信息量比你以为的少得多。它只能告诉你这个站有没有人手写过规则,告诉不了你这个站到底放不放行。要知道后者,只有一个办法:真的去要一次。 凭感觉选策略容易翻车,GEO效果怎么验证 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)建议给每条建议配一个对照组。 数据源打架时该信谁,收录数据到底信site命令还是GSC (https://zhangwenbao.com/site-search-operator-vs-gsc-coverage-accuracy-decision.html)给了三源校准法。 ## 顺手量到的AI爬虫条款分布 既然统计了,就把完整名单放出来。123个站的robots.txt里,各个AI相关爬虫被点名的次数是这样的:GPTBot 13次,PerplexityBot 12次,OAI-SearchBot 11次,ClaudeBot和ChatGPT-User各10次,Google-Extended 9次,Amazonbot 8次,CCBot 7次,anthropic-ai、Applebot-Extended、Bytespider各6次,Claude-Web和meta-externalagent各5次。 点名之后真写了禁止根目录的更少:Bytespider 3个站,CCBot和Amazonbot各2个,GPTBot、ClaudeBot、Google-Extended、Applebot-Extended、meta-externalagent各1个。 两组数字放一起,画面就清楚了:132个中大型独立站里,真正在robots.txt里明确禁止某个AI爬虫的,一只手数得过来。行业里关于“要不要拦AI”的讨论声量很大,但落到文件里的动作非常少。大多数站的做法是既不表态也不设防,把这件事整个交给平台默认值。 ## 被点名最多的和被禁止最多的不是同一批 把点名次数和禁止次数放在一起排,会看到一个错位。 点名次数最高的是GPTBot,13次,但真写了禁止根目录的只有1个站。禁止次数最高的是Bytespider,6个站点名、3个站禁止,禁止率50%。CCBot和Amazonbot的禁止率也都在四分之一以上。 这个错位说的是两种不同的心态。写GPTBot的人多数在做一件“表明我知道这件事”的动作,具体规则往往是允许或者只禁几个目录。而写Bytespider的人通常是被抓怕了,那是一条带着情绪的规则。 顺便说一句,名单本身也在快速变化。这123份文件里出现的AI相关爬虫名字有二十来个,其中有几个是2024年之后才出现的,还有几个已经改过名。一份三年没更新的robots.txt,上面的AI爬虫名单大概率有一半已经失效。 国内那几家的抓取和带量情况,AI流量来源漏掉九成 (https://zhangwenbao.com/ai-referral-source-domestic-entries-gap.html)按日志逐条拆过。 按UA拦截的老代码尤其容易过期,WordPress拦截恶意User-Agent (https://zhangwenbao.com/wordpress-http_user_agent.html)记了一次死亡迁移。 ## 一份能拿去对照的身份清单 为了让上面那些数字能直接用,把这批文件里出现频率最高的几个身份整理成表。每一行的最后一列是最要紧的:拦掉它,你会失去什么。 身份名 | 本次被点名站数 | 它在做什么 | 拦掉的后果 | GPTBot | 13 | 训练数据抓取 | 内容不进训练语料,对当下的引用影响间接 | OAI-SearchBot | 11 | 为AI搜索建索引 | 直接失去在该产品里被检索到的机会 | ChatGPT-User | 10 | 用户提问时的实时取页 | 用户问到你时抓不到,等于当场缺席 | PerplexityBot | 12 | AI搜索的索引抓取 | 失去该产品的引用位 | ClaudeBot | 10 | 训练与检索抓取 | 同上,视产品形态而定 | Google-Extended | 9 | 控制内容是否用于生成式产品 | 不影响搜索收录,只影响生成式用途 | Amazonbot | 8 | 购物与语音助手相关抓取 | 影响特定生态的商品可见性 | Bytespider | 6 | 抓取量大,常被抱怨 | 拦掉的实际代价通常较小 | 这张表里最容易配错的是第三行和第六行。ChatGPT-User不是训练抓取,它是用户在对话里问到某个地址时才去取一次的实时请求,把它归进“拦AI训练”这一档,效果是用户当场问起你的品牌,对方拿不到你的页面。 Google-Extended则相反,它只控制生成式用途,不影响搜索收录,是唯一一个可以放心用来表达“不想被拿去训练”的开关。很多想拦AI又怕影响收录的站,其实要的就是这一个,却去动了别的。 实时取页决定了当场能不能被引用,2万条数据揭秘AI引用机制 (https://zhangwenbao.com/ai-search-citation-mechanism-content-optimization.html)总结了5条规律。 官方对这类做法的态度也变过,Google官方指南叫停的5个动作 (https://zhangwenbao.com/googles-ai-search-guide-aeo-geo-still-seo.html)值得对照着看。 做配置之前把这张表过一遍,能避开大半的误伤。名单会变,但分类逻辑不太会变——分清“训练用”、“检索用”、“用户实时取页”这三类,比记住二十个名字有用得多。 ## 那个空用户代理进得去、AI爬虫进不去的站 数据里有一个站的组合特别值得单拎出来,因为它把本节的结论翻过来演示了一遍。 按引擎分别优化更有效,四大AI搜索引擎的GEO策略 (https://zhangwenbao.com/ai-search-engine-geo-optimization-strategy.html)做了分引擎拆解。 这是个北欧家居品牌。普通Chrome拿到200,Googlebot拿到200,Bingbot拿到200,空用户代理也拿到200,四个身份拿到的字节数几乎一模一样,都是6040上下。 而GPTBot、ClaudeBot、PerplexityBot三个身份,全部拿到403,正文2097字节的人机验证页。 同一批数据里品牌词那条线更隐蔽,AI引用拆品牌词和非品牌词 (https://zhangwenbao.com/brand-nonbrand-split-grounding-query.html)画在一句你看不到的话上。 这个站的规则设计得非常清楚:搜索引擎放行,未知来源放行,AI抓取拦截。在它这儿,报出AI爬虫的名字比什么都不报还要吃亏。 这个案例的价值在于它证明了名字判断的双向性。上一节说沉默会被当成可疑,这个站说沉默反而安全,两者并不矛盾——因为规则是每个站自己写的,而这批站的规则彼此之间毫无共识。 没有共识这件事本身就是结论。你没法从“行业惯例”推出任何一个具体站点的行为,只能一个一个去测。在机器人这件事上,不存在一套大家都在用的规矩,只存在一百多套各不相同的默认值。 ## 那64个连空用户代理都放行的站 反方向也值得看一眼。132个站里有64个把页面给了什么都不报的那次请求,占48.5%。 这64个站的共同特征是防护层比较薄。要么是自建服务器没上第三方防护,要么是上了但只开了基础的攻击防御,没开机器人管理。它们不是特意对匿名请求友好,是压根没配这一层。 这个状态好不好,得看你怎么权衡。好处是任何读取方都能拿到内容,包括那些还没被主流防护产品收录进分类表的新爬虫——这两年新出现的AI抓取程序,多数属于这一类。坏处是低质量抓取和数据采集也一样畅通。 服务器这一层影响SEO的地方不止一处,服务器配置对SEO的20项影响 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)列了完整清单。 我的看法是,对绝大多数独立站来说,这个状态比默认全拦要好。被多抓几次的成本是可计算的带宽,被少收录一次的成本是看不见的流量。两边都不确定的时候,选那个错了还能补救的。 换个角度说,如果你是那个做AI抓取的一方,最理性的策略就是不报名字。这大概是整个机器人协定体系里最尴尬的一处:老实交代身份的一方,承担了全部的不确定性。 抓取本身是有成本的,碳中和SEO运营 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)把爬虫经济学算进了同一套规范。 ## 402这个1997年就写好、二十多年没人用的状态码,怎么突然出现了? 这一节讲一个单独的站,因为它一个站就讲完了整件事的未来形态。 ## 55个字节的付费墙 这个站是做手机配件的国际品牌。7种身份的结果分成三档,干净得像是有人特意设计过: 身份 | 状态码 | 正文字节 | 最终落到哪里 | 桌面Chrome | 200 | 175233 | 中国站 | Googlebot | 200 | 173747 | 国际站 | PerplexityBot | 200 | 175233 | 中国站 | Bingbot | 402 | 55 | 被拦 | GPTBot | 402 | 55 | 被拦 | ClaudeBot | 402 | 55 | 被拦 | 那55个字节是一段JSON,内容类型是application/json,正文是一句话:请联系站点所有者以获取访问权限。响应头里的服务器字段是那家内容分发网络的名字。 402这个状态码的正式含义是“需要付款”。它1997年就被写进HTTP规范,在现行的RFC 9110的HTTP语义定义 (https://www.rfc-editor.org/rfc/rfc9110.html)里也仍然在册,之后二十多年一直挂着“保留待将来使用”的牌子,是整个状态码表里最著名的那个空位。MDN关于402状态码的条目 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/402)至今还写着它是实验性的、尚未有标准用法。现在这个空位被填上了。 响应头这一层能表达的东西很多,HTTP响应头的X-Robots与Vary机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)逐个讲过。 ## 三档待遇背后是一套定价逻辑 把这三档摆开看,它不是防护,是分级供货。 浏览器免费拿,因为浏览器背后是可能下单的人。搜索引擎免费拿,因为搜索引擎会把流量还回来。而训练型AI爬虫既不下单也不还流量,于是它拿到一张账单。 这个逻辑一旦成立,接下来的事情就顺理成章了。同一家内容分发网络在2026年8月宣布,要给AI代理配上可以按访问付费的钱包;同一批新闻里还有一条更要紧的:从2026年9月15日起,新注册域名的默认设置会变成——被归类为训练型或代理型的爬虫,在展示广告的页面上一律屏蔽;而那些“既做搜索又做训练”的混合型爬虫,在所有拦AI训练的配置下都会被屏蔽。 流量还回来这件事本身在变,流量下降不等于SEO失败 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)给了8个维度的解释。 同一家还在推另一种交付方式,给AI交付内容的HTTP内容协商实操 (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)讲了怎么配。 混合型这三个字是关键。Googlebot就在这一档里。 这条变更公布之后,社区里已经有人报告,把AI训练设成屏蔽之后,Googlebot和Bingbot取站点地图开始收到403,把开关关掉就恢复,完整经过见Search Engine Journal关于AI爬虫屏蔽波及Googlebot的报告 (https://www.searchenginejournal.com/report-that-cloudflare-ai-bot-blocking-prevents-googlebot-from-indexing-sites/584673/)。到底是配置误操作还是分类逻辑提前生效,官方还在核实。但对独立站站长来说,结论是一样的:那个看起来只关乎AI的开关,另一头连着你的自然流量。 ## 你现在就该做的一件小事 不用等到9月。打开你的防护后台,把爬虫分类那一页翻出来,逐条确认三件事:搜索类是不是允许,训练类你选的是什么,混合类被归到了哪一边。 另一家搜索引擎值得单独维护,Bing SEO怎么做 (https://zhangwenbao.com/bing-seo-complete-guide-organic-ranking.html)讲了它被低估的地方。 后台之外源站这一层也要看,Nginx全页缓存怎么配 (https://zhangwenbao.com/nginx-fastcgi-cache-fullpage-php-wordpress-purge-microcache.html)影响的是同一条链路。 如果你的后台里根本没有“混合类”这个概念,那更要留意,说明你用的版本还没更新到这一套分类,等它更新的那天,你的选择会被自动映射到新分类里去,映射规则不一定合你的意。 ## 按访问付费一旦普及,独立站有三条路 这件事对独立站的影响还没显现,但方向已经能看出来了。往前推演,大致有三条路。 第一条是收费。你把内容当成资产,给AI抓取标个价。这条路只对内容本身有稀缺性的站成立——独家评测、原创数据、专业教程这一类。绝大多数电商站的商品页不具备这个条件,因为同样的商品信息在十几个渠道都有。 第二条是全放。你判断被AI引用带来的曝光价值高于内容被使用的损失,于是彻底开放,甚至主动优化机器可读性。做品牌认知、做长尾获客的站多数会走这条。 这类内容的索引控制有讲究,帮助中心和知识库SEO怎么做 (https://zhangwenbao.com/knowledge-base-help-center-seo-indexing-ai-citation.html)讲了工程化做法。 可见性怎么系统地做,AI搜索可见性的5维度策略 (https://zhangwenbao.com/ai-search-visibility-deep-seo-strategy.html)给了实战路径。 第三条是分层。核心内容收费或者屏蔽,导购型、目录型的内容全放。这条路技术上最麻烦,但商业上最讲得通。 选哪条不是这篇文章能替你决定的,但有一个前提是共通的:你得先知道现在的状态是什么。这批132个站里,绝大多数处在“既没选也不知道自己在哪一档”的位置上,而默认值正在替他们做选择。 ## 混合型分类为什么是个陷阱 再回到那条9月生效的分类规则上,因为它设计得确实别扭。 问题的根源是同一个爬虫在做两件事。搜索引擎抓你的页面,一部分用于建索引给你导流量,一部分用于训练它的生成式产品。这两件事共用一个用户代理串,站长没有办法只同意前者不同意后者。 于是分类系统只能造一个“混合型”的桶把它装进去,然后规定:只要你选了拦AI训练,混合型就一起拦。逻辑上自洽,后果上很吓人——你以为你在拒绝被训练,实际效果是拒绝被收录。 另一处说不清的争议,结构化数据对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)做了官方说法加实测。 这个设计把一个本该由内容方和平台方去谈的问题,转嫁成了站长的一个二选一。站长手里那个开关,只有全开和全关两档,中间那些他真正想要的选项并不存在。 短期内能做的只有一件事:确认你现在选的是哪一档,以及默认值变更之后你会被映射到哪一档。这两个问题的答案不在文档里,在你自己的后台里。 两层都得写才生效的例子还有一个,一键退订必须写两层 (https://zhangwenbao.com/one-click-unsubscribe-header-body-two-layers.html)少一层就被限流。 顺便说一句,从技术上说,402现在的用法比它原本的设想更实在。原本的设想是给网页做小额支付,从来没落地过;现在它变成了机器之间的收费闸口,居然跑通了。一个状态码等了二十九年,等来的客户不是人,是机器。 ## 被挡回来的那几百个字节,能告诉你什么? 拒绝页本身是有信息量的,而且信息量远比大多数人以为的大。这一节讲怎么读它。 ## 先看服务器字段和状态码的组合 把132个站上所有“没拿到页面”的响应汇总,按服务器和状态码分组之后,分布是这样的: 服务器字段与状态码 | 出现次数 | 典型含义 | cloudflare | 403 | 61 | 边缘机器人规则 | AkamaiGHost | 403 | 10 | 另一家内容分发网络的边缘规则 | 无响应 | 0 | 8 | 连接层被丢弃 | CloudFront | 403 | 5 | 第三家边缘规则 | nginx | 301 | 5 | 被跳走且没跟到落点 | openresty | 403 | 4 | 源站自己的规则 | cloudflare | 402 | 3 | 按访问付费 | 其余各1到2次 | 10 | 含418、301、AmazonS3等 | 自定义错误页配不好会变成软404,自定义错误页怎么配才不踩坑 (https://zhangwenbao.com/apache-errordocument-custom-error-pages-http-status-codes-soft-404.html)讲了状态码的坑。 第一行就占了六成。这说明一件很实际的事:你排查送达问题的时候,大概率只需要打开一个后台。 另外有一条负面结论也值得记:这批被挡的响应里,那个专门用来标记“本次拦截由谁做出”的响应头,一个都没出现。这个头是有标准的,但默认不开。所以别指望响应头会自己承认是它拦的,你得靠状态码、服务器字段和正文长度这三样去推。 ## 正文长度是个被低估的线索 拒绝页的字节数比你想的更能说明问题。这批数据里有几个非常清晰的簇。 默认不开的响应头不止这一个,浏览器HTTP缓存头怎么配 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)是另一处容易漏的地方。 第一个簇是356到372字节,一共出现了几十次,横跨十几个互不相干的品牌——运动鞋、快时尚、百货、奢侈品、小家电都有,服务器字段全是同一家内容分发网络。十几个毫不相干的大牌,用的是同一张370字节的拒绝页。它们甚至不知道自己撞了衫。 第二个簇更整齐:某个快时尚集团旗下六个品牌,六个独立域名,拒绝页字节数在357到366之间,服务器字段被隐藏了。同一套基础设施,六张同款的门。 同一家边缘产品的行为值得摸清,CDN对SEO到底有什么影响 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)拆了6层缓存与边缘路由。 第三个簇是极短的那些。有两个站的403正文只有25字节,还有两个站只有17字节。17个字节是什么概念?一条短信的十分之一。它们连“你被拒绝了”这句话都懒得写完整。 正文长度之所以有用,是因为它能帮你判断这道墙是谁砌的。几百字节的标准页,多半是内容分发网络的默认拒绝模板;十几二十个字节的,通常是有人手写了一条规则并且随手返回了一个字符串;几千字节还带脚本的,那基本就是人机验证页。 ## 六个品牌,六个域名,同一张门 第二个簇值得再拆一下,因为它演示了一件很多人没意识到的事。 批量查异常地址有成套方法,网站死链怎么批量查出来 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)从检测到提交一条龙。 那六个品牌分属同一个快时尚集团,各自有独立的域名、独立的站点、独立的运营团队,在消费者眼里是六个不同的牌子。而在这次实验里,它们对爬虫身份的响应是同一套:同样的403,同样隐藏了服务器字段,正文字节数在357到366之间。 这意味着六个品牌共用同一套基础设施和同一份防护策略。改一次,六个站一起变。对做竞品分析的人来说这是个好消息——测一个就等于测了六个;对这个集团自己来说,这是一处单点风险。 一个大站还是多个小站,出海该建一个大站还是多个品牌小站 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)算的正是这笔账。 同样的模式在另一家的十几个大牌身上也成立,只不过它们不属于同一个集团,而是买了同一家内容分发网络的服务,用了同一份默认拒绝模板。运动鞋、快时尚、百货、奢侈品、小家电,五个八竿子打不着的行业,被同一张370字节的纸挡住。 从审计的角度,这个现象有一条很实用的推论:当你发现某个站的拒绝页字节数落在几个常见值附近,基本可以判定它用的是默认模板,也就意味着这条规则大概率没有人专门配过。没有人专门配过的规则,通常也是最容易改回去的。 反过来,如果拒绝页是定制的、带品牌标识的、甚至写了联系方式,那说明有人认真对待过这件事。这时候你要做的不是去改配置,是去找那个人聊。 ## 那几个特别的响应 有一个站对ClaudeBot返回了418。 418这个状态码的正式定义来自1998年愚人节的一份玩笑规范,含义是“我是一个茶壶”,用来表示这台设备拒绝冲泡咖啡因为它是茶壶。它从来不是正经的HTTP状态码,但主流软件栈里一直留着它,很多防护系统拿它当“我就是不想理你”的委婉表达。 这个响应的正文字节数是0,服务器字段是空的。一个茶壶,什么都没说。这大概是整份数据里最有幽默感的一次拒绝。 拦截也可以在更前面一层做,Linux服务器的防火墙端口规则怎么配 (https://zhangwenbao.com/linux-ufw-firewall-server-port-rules-ssh-cloud-security-group.html)讲了端口层的做法。 还有4个站的情况完全不同:它们对7种身份一视同仁,全部返回429,也就是请求过多。其中3个站的429响应带着3万3千多字节的HTML正文,服务器字段是同一家前端托管平台。 这4个站不在132的基线里,因为连普通Chrome都没拿到页面。它们不是在挡爬虫,它们是在挡所有人。如果你只测了爬虫身份没测浏览器身份,很容易把这种情况误读成“我被针对了”。 负载高到要限流的时候,服务器突然变慢负载飙高怎么排查 (https://zhangwenbao.com/linux-server-performance-troubleshooting-high-load-cpu-memory-disk-io-diagnosis.html)是上游的功课。 429这个状态码的含义是请求过多,正确的用法是配一个说明什么时候可以重试的响应头。这4个站里没有一个配了。对爬虫来说,这意味着它只能靠自己猜下次什么时候再来,而多数爬虫的策略是保守——猜错了就少来,少来就意味着你的新页面被发现得更慢。 更值得注意的是那三个带着3万多字节HTML正文的429。一个状态码说“你请求太多了”,同时又给了你一整页内容,这在协议层面是矛盾的。检查工具会按状态码判失败,浏览器会按内容正常渲染,两边看到的是两个世界。这种自相矛盾的响应,是监控系统误报的重要来源。 ## 限流是按什么算的 既然说到429,顺手把限流的机制讲清楚,因为它是送达型故障里最容易被误解的一种。 限流通常按三个维度中的一个或几个算:来源IP、身份标识、或者两者的组合。按IP算的话,同一个数据中心出来的所有请求会共用配额——这就是为什么你从云服务器测的结果,可能比真实用户的体验差。 时间窗也有讲究。有的按固定窗口算,每分钟清零;有的按滑动窗口算,看过去六十秒。前者在窗口边界会出现两倍的突发容量,后者更平滑。这个差别决定了你的监测脚本会不会周期性地误报。 同源请求还有别的副作用,给内链加UTM参数为什么伤SEO (https://zhangwenbao.com/tracking-parameters-internal-links-seo-damage.html)讲了分析与抓取的取舍。 还有一层是并发限制,跟总量无关,只看同一时刻有几个连接。一个每秒只发一次请求但从不关闭连接的脚本,照样可能触发它。做监测的时候记得让每次请求独立完成,别复用长连接。 还有一个站更离奇:7种身份全部返回404,正文10个字节,服务器字段是某家对象存储服务。一个知名户外品牌的主域名首页,对所有人都是404。这多半是域名解析或者跳转规则出了问题,而它显然已经这样有一阵子了。 监测跑起来之后日志会涨,服务器日志怎么管才不爆盘 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)有现成的轮转方案。 ## 怎么让脚本自动认出拒绝页 如果要把这套检查做成每天跑的自动化,识别拒绝页这一步必须机器化。人工看一眼当然准,但没人愿意每天看。 可以用的信号有四个,按可靠性排序。 最可靠的是正文长度加状态码的组合。正常首页几万字节,拒绝页几百字节,验证页两千到六千字节,中间的空档非常宽。定一条阈值几乎不会误判,前提是你先测过自己站的正常值。 第二可靠的是关键字符串。在你的正常首页里挑一段一定会出现、又不会出现在任何错误页上的文字,比如某个固定的导航项或者版权行。检查这段字符串在不在,比检查状态码结实得多。 第三是内容类型。前面那个402返回的是application/json,而正常首页一定是text/html。类型不对,直接判失败。 第四是服务器字段的变化。正常情况下你的站每次返回的服务器字段应该是稳定的,一旦某次变成了另一个名字,说明这次响应不是你的源站给的。这一条特别适合发现“被中间层接管了”的情况。 把四个信号组合起来,一个几十行的脚本就能跑。误报率主要来自站点自己发版本,所以报警最好带上一句“和昨天比变了什么”,而不是只说“失败了”。 ## 字节数相同不代表内容相同 还有一个反过来的陷阱,是我在整理这批数据时才意识到的。 那几个Akamai集群的拒绝页,字节数在356到372之间浮动,差几个字节。刚开始我以为是不同的模板,核对之后发现是同一张页面——差的那几个字节是页面里嵌的请求标识符,每次都不一样。 反过来也成立。那三个返回429的前端托管站,七次响应的字节数分别是33790、33801、33799、33795、33793、33793、33791,全都在33790附近抖动,看着像七个不同的页面,其实是同一个模板加上时间戳。 所以做长期监控的时候,不要把字节数当成内容指纹,它每次都会抖。要比对内容,得先把动态部分剥掉再做散列,或者干脆只比关键字符串在不在。这个坑我见过不止一个团队踩,表现是监控天天报警,报到最后没人看了。 ## 同一个域名,为什么给浏览器和爬虫送去了不同的国家? 这一节要讲一个我原本没打算测、但数据自己跳出来的维度。 ## 身份不是唯一的变量,来源地也是 先坦白一个实验条件:这批请求是从一台位于中国的服务器发出去的。这个条件我原本当成噪音,后来发现它是信息。 那个运动品牌的例子最典型。普通Chrome请求最终落在中国站,服务器字段是一个国产的网关软件,17万字节;而五个爬虫身份落在国际站的403上。同一个域名,两条完全不同的路。 中国这一侧的搜索生态是另一套,中国搜索流量不是百度的天下 (https://zhangwenbao.com/china-fragmented-search-ecosystem-seo-2026.html)拆了5个战场。 咖啡机品牌那个更直白:Chrome和空用户代理都被送到了它的中国站,五个爬虫身份连接都建立不起来。手机配件品牌也是,Chrome和PerplexityBot拿到的是中国站的175233字节,Googlebot拿到的是国际站的173747字节。快时尚品牌那个则是Chrome和Googlebot进了中国站,其余五个身份被301跳到国际域名之后就停在那儿了。 这四个站说的是同一件事:决定你拿到什么的不只是“你是谁”,还有“你从哪儿来”。 ## 这件事对做多市场的独立站意味着什么 如果你的站做了地理分流,那么你在自己办公室里打开页面看到的东西,和搜索引擎在它的数据中心里看到的东西,可能根本不是同一个页面。 这不是什么新鲜风险,但它在送达型故障里会变成一个特别讨厌的干扰项:你从北京测一次没问题,同事从法兰克福测一次也没问题,而爬虫从它自己的出口测一次拿到403。三个人拿着三个不同的结果吵架,谁都没说谎。 所以排查这类问题,测试请求的出口位置必须被当成一个变量记下来。一份不写明“从哪里发的”的送达测试报告,价值大概等于一份不写单位的体检报告。 ## 字节数差两倍以上的那四个站 还有一类更隐蔽的差别:页面给了,但给的不是同一份。 把Chrome和Googlebot拿到的字节数逐个对比,差异超过两倍的有4个站。一个户外配件品牌给爬虫的字节是给浏览器的2.13倍,一个北欧家具品牌只给了0.17倍,一个运动鞋品牌给了0.38倍,还有一个生活杂货品牌给了1.74倍。 字节数不等于内容量,多出来的可能只是没被压缩的模板,少掉的可能只是延迟加载的组件。但2.13倍和0.17倍这种量级,基本可以断定服务端确实按身份走了不同的分支。 给爬虫和给浏览器的差别还有更细一层,Googlebot为什么不读preload (https://zhangwenbao.com/why-googlebot-ignores-resource-hints.html)讲的就是这类差异。 给爬虫的比给浏览器的多,通常是好意——把客户端才会渲染的内容提前吐出来了。给爬虫的少一大半,那就要查一查少掉的是什么。0.17倍的意思是,爬虫看到的那一版页面,六分之五的内容不在。 ## 地理分流和多语言声明是两件事 这里要澄清一个经常被混为一谈的问题。 地理分流发生在服务端,它根据你的IP决定把你送到哪个版本,动作是跳转或者直接改变响应内容。多语言声明发生在页面里,它告诉搜索引擎“这个页面还有这些语言版本”,动作是提供信息,不改变任何人拿到什么。 前者是强制的,后者是建议的。一个把用户强行跳走的站,就算多语言声明写得再完整,搜索引擎也可能只收录到它被跳到的那一版。 这些声明的实际待遇比预期低,hreflang写的语言版本只被当成规范页的别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)是上个月的实测。 这批数据里能看到这个后果。四个做了地理分流的站,爬虫身份拿到的最终地址和浏览器身份完全不同,有两个甚至落在了不同的顶级域名上。对搜索引擎来说,它抓到的就是它被送到的那一个,其余版本能不能被发现,取决于别的路径。 比较稳的做法是:不强制跳转,给出一个明显的地区切换入口,让访问者自己选,同时把各语言版本的关系声明完整。这话说起来容易,跟增长团队的KPI经常打架,但从收录的角度它确实是最干净的方案。 ## 怎么测多个出口 如果你的站做了地理分流,那单点测试是不够的,得从多个出口各测一次。 首屏那块地怎么安排,首页首屏从导航到分类区怎么设计 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)有一份取舍清单。 成本最低的办法是用几家不同区域的云服务器,各开一台最小规格的机器,跑同一个脚本。三个区域基本够用:你的主要市场、你的第二市场、以及搜索引擎数据中心比较集中的那个区域。 更省事的办法是用现成的多地拨测服务,很多监控产品自带这个功能,配置一下就能从十几个城市同时发请求。缺点是这类服务通常不让你自定义用户代理串,做不了本文这种身份对照。 多台机器跑起来之后备份也得跟上,服务器怎么用rsync做增量备份 (https://zhangwenbao.com/linux-server-rsync-incremental-backup-snapshot-link-dest-offsite-restore.html)讲了异地恢复。 还有一个几乎零成本的土办法:找几个在不同国家的同行或者客户,请他们打开页面截个图。不够严谨,但发现“某个国家看到的是完全不同的页面”这种问题,它足够了。 ## 怎么在十分钟内判断故障属于哪一种? 数据讲完了,这一节讲怎么用。 ## 三种病的判据表 一个检查没通过,可能是三件完全不同的事:东西根本不存在、东西存在但对方没拿到、对方拿到了但不采信。这三种的处置方式互为毒药,用错了不只是无效,是把事情弄得更糟。 类型 | 判据 | 30秒粗筛 | 投入曲线 | 典型误判 | 缺失型 | 把字节抓下来用对方的解析器解一遍,找不到就是不存在 | 关掉样式和脚本,看还剩什么 | 阶梯式,补一个多一个,有终点 | 以为它在,因为你自己看得见 | 送达型 | 同一个地址换个身份或换个时刻再要一次,两次结果不同 | 这条链路上有没有第三方在中间 | 开关式,要么全通要么全断 | 跑去改内容,而内容一个字没错 | 采信型 | 官方存在两个并列字段,一个写“你说的”,一个写“我选的” | 这个结论是不是对方算出来的 | 滞后式,改完要等它重新评估 | 加大声明力度,而问题是存在竞争性证据 | 判据这件事在选题上也成立,一个词值不值得单开一页 (https://zhangwenbao.com/keyword-own-page-duplicate-wordset-audit.html)用87个站的站点地图先替你答了一半。 这张表可以贴在工位上。同一句“没通过”,在这三格里分别意味着:你还没做、你做了但它没到、它到了但不算数。 ## 送达型的两个特有属性 送达型故障有两个属性是另外两种没有的,理解它们能省掉大量无用功。 第一个是开关性。它几乎没有中间态,要么全通要么全断,不存在“部分页面受影响”这种渐变。所以如果你看到的是某一类页面掉、另一类不掉,那大概率不是送达问题,别往这个方向查。 开关型与滞后型的差别在实验里也有,A/B测试赢了上线却掉了 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)问题出在那26天。 第二个是恢复的不对称。把开关关掉,拦截立刻消失,但流量不会立刻回来。索引要重新建立,商品要重新审核通过,抓取频率要重新爬回原来的水平。开头那个案例里,配置改回来之后,客户的流量是“只是刚开始恢复”。 这个不对称有一个很实际的推论:送达型故障的成本跟它持续的时间不是线性关系。断三天和断两周,恢复周期差的远不止四倍。所以这类问题的排查优先级应该高于它表面上的严重程度。 ## 恢复要等多久,分四段看 把恢复这件事拆开,能看到四段各自独立的时钟,它们不同步。 第一段是拦截解除,这一段是即时的。开关一关,下一次请求就能过。这也是唯一你能控制节奏的一段。 第二段是重新抓取。搜索引擎不会因为你修好了就立刻回来,它按自己的调度表走,而且刚经历过一批失败的地址,重试频率通常会被下调。这一段从几天到几周不等,站的权重越高越快。 第三段是重新索引。抓到不等于立刻回到索引里,还要过一遍质量评估。掉出去的页面重新进来,往往比第一次进来更慢。 第四段是排名恢复。这一段最不可控,因为在你缺席的这段时间里,你原来的位置已经被别人占了,而占位的一方现在有了新的数据支撑。你不是回到原来的位置,你是重新去争一次。 那几种状态各自意味着什么,Google索引覆盖的8种状态 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)给了算法决策路径。 回来之后进哪一层索引也不一定,Google分层索引揭秘 (https://zhangwenbao.com/google-index-tiers-base-zeppelin-landfill.html)讲了三层的差别。 购物类的商品列表是另一条时钟,通常比自然搜索快,因为它有明确的重新审核机制,但也要按批处理。开头那个案例里,配置改回来之后一段时间,客户的状态是“只是刚开始恢复”——注意这个措辞,那已经是修好之后的事了。 把四段加起来,一次两周的送达故障,完全恢复往往要一到两个月。这就是为什么这类问题值得用一个每天跑一分钟的脚本去防。 ## 十分钟的分诊流程 真到了现场,按这个顺序走: 第一步,用普通浏览器的身份从外网要一次首页,确认站本身是活的。这一步排除掉“其实所有人都进不来”那4个站的情况。 第二步,换成搜索引擎爬虫的身份要同一个地址,比较状态码和字节数。两次结果不同,送达型基本坐实。 第三步,再换两三个AI爬虫身份各要一次。如果只有新身份被挡,去查防护产品的分类规则;如果连搜索引擎身份都被挡,立刻处理,这是在烧钱。 第四步,看拒绝响应的服务器字段和正文长度,定位是哪一层拦的。 第五步,才轮到去读robots.txt。注意顺序:robots.txt是最后一步不是第一步,因为它只能告诉你意图,告诉不了你事实。这一节的数据已经证明了,这两件事经常对不上。 ## 三种病会同时出现 判据表是为了讲清楚才分成三格的,真实现场经常是混着的,而且顺序有讲究。 典型的混合形态是这样:一个页面既是空壳(缺失型),又对某些身份拿不到(送达型)。这时候先修哪个?先修送达。因为送达没解决,你补的内容对方一个字也读不到,改了等于没改。 另一种混合是送达型加采信型:页面能拿到了,但搜索引擎选了另一个地址当规范版本。这时候先解决送达,再等它重新评估,因为采信的前提是它得先拿到你的新版本。 三种病连在一起,其实是一条有先后的链:东西得先存在,然后得送到,最后才谈采信。修的顺序必须跟这条链一致,跳着修就是白干。 反过来,诊断的顺序可以倒着来,因为最容易验证的是最后一环——去看看对方到底采信了什么,通常一个后台工具就能看到。发现它采信的不是你想要的,再往前推是送到了没有,最后才问东西在不在。 ## 误判的代价不一样 三种病判错的代价并不对称,这个不对称决定了你该往哪边偏。 把送达型误判成缺失型,代价是你花几周重写内容,问题一点没解决,而且这几周里损失一直在累积。这是最贵的一种误判。 把缺失型误判成送达型,代价小得多:你去查了一圈防护配置,发现没问题,然后回头查内容。浪费半天,但不会往错误方向投入大量资源。 把采信型误判成缺失型,代价是最典型的那个错误动作——加大声明力度。同一件事再声明一遍、写得更绝对,而对方不采信的原因是存在竞争性证据。这种情况下加强声明不但无效,有时候还会因为新增了一处不一致而让情况更糟。 所以经验法则是:拿不准的时候先按送达型查,因为它最便宜、最快、而且误判它的代价最高。十分钟能排除掉的事,没有理由放到最后。 ## 三句话,把三种病问出来 如果只想记一件事,就记这三句问句,它们能覆盖绝大多数现场。 第一句:这个信息,除了眼睛之外还有谁能读到?问出来的是缺失型。答案如果是“打开页面就看得见啊”,那你已经答错了——看得见靠的是浏览器执行了脚本,而对方没有那双眼睛。 第二句:换一个身份再要一次,结果一样吗?问出来的是送达型。这句话的好处是它可以立刻被执行,不需要讨论,两分钟就有答案。 第三句:这个结论是我声明的,还是对方算出来的?问出来的是采信型。凡是对方算出来的东西,你只能提供证据去影响它,不能直接指定它。措辞里带着“已选定”“已检测到”这类词的字段,多半都属于这一类。 三句话按顺序问,能在十分钟内把方向定下来。方向定错了,后面做多少都是负数。这也是这一系列文章想说的全部意思:先分清是哪种病,再谈治法。 顺序还有一层用处,是它能帮你判断该找谁。缺失型的活儿落在前端和内容那一侧,送达型的活儿落在运维和安全那一侧,采信型的活儿多半落在信息架构和数据一致性那一侧。问错了人,得到的答案通常是一句真诚的“我这边看着没问题”,而这句话在三种病里都成立。 所以真到了要拉群的时候,先把这三句问句发进去,让每一方各自回答与自己相关的那一句。比起描述现象,让各方去验证一条明确的判据,能省掉大半的扯皮。 ## 这套自查怎么跑才不会误伤自己? 最后讲操作层面的注意事项,都是踩过的。 ## 别用真爬虫的身份去压别人的站 先说边界。这套方法用在自己的站上没有任何问题,那是必要的运维检查。用在别人的站上要克制:单个地址取一次,间隔拉开,不要并发压。 这次实验对每个域名只发7次请求,全程跑完,没有对任何一个站造成可感知的负载。做竞品调研和做压力测试之间只隔着一个频率参数,别越过去。 ## 三个容易读错的信号 第一个,200不等于拿到了页面。前面那59个验证页里有相当一部分返回的是200。判断标准要加一条正文长度,或者干脆检查正文里有没有你期待的关键字符串。 第二个,403不等于robots.txt写了禁止。这两件事在不同的层,403是送达层的动作,robots.txt是声明层的文字。看到403就去改robots.txt,是本文开头说的那种“药方互为毒药”的典型。 第三个,连接失败不等于站挂了。有8次响应是连接层就被丢弃的,状态码是0。这种情况下站本身活得好好的,只是那个身份的握手被拒了。 ## 把这件事变成例行检查 送达型故障的最佳防御不是配置得多完美,而是缩短发现它需要的时间。开头那个案例损失了两周,而这个检查跑一次不到一分钟。 做法很简单:写一个每天定时跑的小脚本,用三到四个身份各请求一次首页和一个商品页,把状态码和正文长度记下来,任意一项跟昨天不一样就发个通知。不需要复杂的监控系统,一个定时任务加一个通知接口就够了。 保哥给客户做技术审计的时候,这一项现在是固定动作,成本极低但抓到过好几次问题。有一次是客户换了套防护方案,服务商的默认模板把两个AI爬虫身份归进了黑名单,客户完全不知情,是脚本第二天早上报出来的。 ## 这个脚本大概长什么样 说得再具体一点,免得看完还是不知道从哪儿下手。 需要的东西只有三样:一个能发HTTP请求的命令行工具、一个能定时执行的任务、一个能把消息推到你手机上的接口。三样在任何一台Linux服务器上都是现成的。 循环的结构是两层:外层遍历你要监测的地址,一般是首页、一个分类页、一个商品页,三个足够;内层遍历身份,桌面浏览器、搜索引擎爬虫、一个AI爬虫,三个也够。九次请求,跑完不到一分钟。 每次请求记四个值:状态码、正文字节数、最终地址、服务器字段。存成一个纯文本文件,一行一条,带上时间戳。 比对逻辑就是拿今天的文件和昨天的比,任意一个值变了就推送一条消息,消息里带上变化前后。不要设复杂的阈值,任何变化都值得看一眼,因为这些值在正常情况下本来就不该变。 唯一需要注意的是别把自己的监测请求发成攻击。间隔至少几秒,串行跑,别并发。你监测的是自己的站,但如果同一个脚本被复制去测别人的站,这条纪律就重要了。 ## 哪些地址值得放进监测清单 三个地址不是随便挑的,选错了监测等于没做。 首页必选,它是防护配置最松的一页。首页出问题,说明配置改得很激进,性质严重。但反过来不成立——首页正常不代表别的页面正常,这也是为什么不能只测首页。 第二个选一个分类页或者列表页。这类页面通常带参数,而很多防护规则是按参数特征触发的。它是最容易被误伤的一类,因为筛选参数长得很像自动化抓取的痕迹。 移动版和桌面版还可能不是同一页,移动优先索引的渲染机制 (https://zhangwenbao.com/mobile-first-indexing-mechanism-googlebot-rendering-evolution-survival.html)讲了掉量自救。 筛选页要不要禁有判别法,电商筛选URL要不要写Disallow (https://zhangwenbao.com/filter-generated-pages-robots-txt-disallow.html)给了三类分法。 第三个选一个商品详情页,而且要选那种深层路径的。它代表你真正想被收录的那一层,也是抓取链路最长的一层。 还有两个可选项。一个是站点地图文件本身,前面提到的社区报告里,最先出问题的就是它——爬虫取站点地图收到403,而首页是好的。另一个是robots.txt,它被拦住的话性质更严重,因为爬虫会因此暂停整站抓取。 加上这两个,一共五个地址,三个身份,十五次请求。跑完两分钟,覆盖了这类故障90%以上的表现形态。这可能是整个技术SEO工具箱里投入产出比最高的一个动作。 指令生效的时滞也要算进去,已收录页面加noindex后多久消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)做了6个场景的实测。 ## 交付给客户的时候怎么写 最后说一句写报告的事,因为这类发现很容易被写成一堆没人看的技术细节。 有效的写法是三行。第一行写事实:某某身份在某某地址上拿到的是什么,附上状态码和字节数。第二行写后果:这个身份拿不到页面,会导致什么业务后果,尽量换算成能被理解的东西。第三行写动作:具体到哪个后台的哪一页,改什么。 不要在报告里解释协议原理。决策者需要的是“这个开关关着,你的商品列表就没了”,不是机器人排除协议的历史沿革。原理放附录,或者放到这样一篇文章里。 给数字配上口径说明同样重要,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)是个反面教材。 交付物写成规范才不返工,内容简报怎么写才能让稿子一次到位 (https://zhangwenbao.com/content-brief-production-spec-engineering.html)是同一个思路。 最后留一个数字当结尾。这次实验里,129个站把首页交给了一台只是在请求头里写了个名字的普通服务器。它们既没有查这个名字的真伪,也没有看这次请求的行为。门锁装得很认真,钥匙是喊出来的。 ## 常见问题解答 ## robots.txt写了Allow,为什么爬虫还是抓不到页面? 因为这是两层不同的东西。robots.txt是声明层,写的是你希望对方抓什么,靠对方自觉遵守;防火墙、机器人管理、边缘规则是送达层,决定这次请求到底能不能拿到字节。本文实测的132个站里,robots.txt写着允许但GPTBot实际拿不到页面的有10个站,ClaudeBot有8个,连Googlebot都有1个。排查顺序应该是先测实际送达,最后才读robots.txt。 ## 怎么快速判断流量下滑是算法更新还是爬虫被拦? 看三个特征。算法更新的下滑通常有结构,某类页面掉得多、某类掉得少,不同市场不同步;爬虫被拦是整片下滑,所有页面按同一节奏走。算法更新有全行业共同的时间戳,配置误伤只在你自己的变更记录里。最有辨识度的一条是:如果自然流量和购物广告的商品列表同时消失,而付费广告照常扣费,那基本可以排除算法更新。 ## 为什么空用户代理的请求反而更容易被挡? 因为这类防护是按名字放行的,不是按行为。你自称是某个已知爬虫,规则里能匹配到对应的条目就放行;什么都不报的请求匹配不到任何已知条目,直接落进“未知来源先验证”的默认分支。实测数据里,空用户代理的通过率只有48.5%,被挡的63次里有59次是撞上人机验证页,而不是干脆的拒绝。 ## 我的服务器日志里查不到爬虫被拒绝的记录,是日志坏了吗? 不是。拦截发生在边缘节点,请求在那里就被判了并返回响应,整趟往返你的源站从头到尾不知情。所以源站日志里看到的不是“爬虫来了被拒绝”,而是“爬虫没来”。这两句话在日志里长得一样,含义完全不同。要看到真相,得去边缘那一层的日志,或者自己扮成那个身份去要一次。 ## 2026年9月15日那次默认设置变更,我需要做什么? 那次变更的要点是:新注册域名的默认设置里,被归类为训练型或代理型的爬虫在展示广告的页面上会被屏蔽,而“既做搜索又做训练”的混合型爬虫在所有拦AI训练的配置下都会被屏蔽。Googlebot属于混合型。所以要做的事只有一件:现在就去防护后台把爬虫分类那一页翻出来,逐条确认搜索类、训练类、混合类各自被归到了哪一边,别等默认值自动映射。 ## 拦AI爬虫到底有没有用? 对守规矩的那一批有用,对不守规矩的那一批没用。本文的实验已经证明了这一点:一台普通云服务器只在请求头里写了一行字,129个站就把首页交了出来,没有一个站做过反向解析验证。真想拿数据又不在乎规矩的,改一个用户代理串就绕过去了,成本是零。所以这类拦截的实际效果,是筛掉了愿意报名字的那一批,留下了不报名字的那一批。 ## 只测首页够不够,为什么还要测站点地图? 不够。首页通常是全站防护配置最松的一页,因为它承担品牌展示职责,谁都不希望它出问题;而分类页带参数、商品页路径深,被误伤的概率都更高。站点地图和robots.txt这两个文件尤其要测:社区里那份关于AI爬虫屏蔽波及搜索引擎的报告,最先出问题的就是站点地图取不到,而首页一直是好的。robots.txt被拦的性质更严重,爬虫会因此暂停整站抓取。建议的监测清单是首页、一个分类页、一个深层商品页、站点地图、robots.txt,共五个地址。 ## 为什么修好之后流量没有立刻回来? 因为恢复分四段,只有第一段是即时的。拦截解除是开关一关就生效;重新抓取要等搜索引擎自己的调度,而且刚经历过一批失败请求之后重试频率通常会被下调;重新索引还要再过一遍质量评估;排名恢复最不可控,因为你缺席的那段时间里位置已经被别人占了,你不是回到原位,是重新去争一次。一次持续两周的送达故障,完全恢复往往要一到两个月。这个不对称正是这类问题排查优先级要高于其表面严重程度的原因。 ## 做这种多身份检测,会不会对被测网站造成压力? 用在自己的站上完全没问题,属于必要的运维检查。用在别人的站上要克制:单个地址取一次,间隔拉开,不做并发压测。本次实验对每个域名总共只发了7次请求,全程没有对任何站造成可感知的负载。做竞品调研和做压力测试之间只隔着一个频率参数。 ## 权威参考资料 ## 304状态码能省抓取预算,142个站只有52个回得出 - URL:https://zhangwenbao.com/conditional-request-304-crawl-budget-audit.html - 分类:技术SEO - 发布:2026-08-14 | 更新:2026-08-14 - 摘要:Google建议用304省抓取预算,可这条建议没有任何报告会告诉你做到了没有。四成的站连一个可以拿来协商的凭据都不给,还有一批发了凭据却不认自己发的凭据。 - 关键词:技术SEO,转化率优化,抓取预算,HTTP缓存 > **TLDR**:摘要:对211个国际化电商域名各发了七次请求,看它们在被问“这个页面变了没有”的时候答不答得上来。首页这一层,142个能正常响应的站里只有52个回得出304,占36.6%;四成的站连一个可以拿来协商的凭据都不给。更麻烦的是有25个站给了ETag却不认自己发的ETag,重发照样全量返回。另外还有16个站连发两次拿到的ETag就不一样,其中五个的字节长度段一模一样、只有哈希段在变。 > 摘要:对211个国际化电商域名各发了七次请求,看它们在被问“这个页面变了没有”的时候答不答得上来。首页这一层,142个能正常响应的站里只有52个回得出304,占36.6%;四成的站连一个可以拿来协商的凭据都不给。更麻烦的是有25个站给了ETag却不认自己发的ETag,重发照样全量返回。另外还有16个站连发两次拿到的ETag就不一样,其中五个的字节长度段一模一样、只有哈希段在变。 Google在管理抓取预算的官方文档里,有一条建议写得很短:支持304状态码。如果一个页面自上次抓取以来没有变化,返回304就等于告诉Google复用缓存那一份,替你省下服务器带宽和资源。 这条建议很好懂,也很容易被跳过。因为它跟同一份文档里的其它建议不太一样——它不在Search Console里,不在任何一份报告里,没有一个检查会告诉你做到了没有。 那到底有多少站真的做到了。保哥把手上那批国际化电商域名拿来实测了一轮:先正常请求一次拿凭据,再拿着凭据重发,看它回什么。结论是三成六。而这三成六背后的故事,比这个数字本身有意思得多。 这篇文章的前半段讲机制:条件请求到底在问什么、这条建议属于哪一类规则、为什么它没有任何反馈。后半段是实测的四道关卡,以及一份能用一条命令跑完的自检。 ## Google那句建议的原文到底说了什么? 先把原文和它所在的位置摆清楚,因为这决定了它的分量。 回原文核对是这个系列反复强调的动作,七万五千条答案实证的引用偏好 (https://zhangwenbao.com/ai-search-citation-content-types-geo-strategy.html)也是靠原始数据说话。 ## 它写在哪一份文档的哪一节 这条建议出现在大型站点抓取预算管理指南 (https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget)里,属于“减少抓取预算浪费”那一节。同一节下面还有另外八条建议,包括合并重复内容、用规则屏蔽不必要的页面、给永久删除的页面返回404或410、消除软404、保持站点地图更新、避免重定向链、优化页面加载速度、以及排查抓取问题。 同一份文档里其余八条建议怎么落地,抓取预算优化的十二项实操指南 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)里逐条拆过,可以配着这一条一起做。 把这九条排在一起看,会发现支持304这一条 (https://www.searchenginejournal.com/google-recommends-using-304-status-code-to-conserve-crawl-budget/584543/)的位置很特别:其余八条都是内容侧或者信息架构侧的活,只有它是纯服务端行为。 ## 原话的三个要点 原文一共三句话,拆开是三层意思。 抓取这一侧的硬约束不止一条,Googlebot抓取2MB限制的八步实战优化 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)是另一条会直接卡住内容的限制。 第一层是动作:支持304这个状态码。第二层是条件:当一个页面自上次抓取以来没有变化的时候。第三层是收益:告诉Google复用它缓存的那一份,从而节省你的服务器带宽和资源。 请注意第三层的措辞:省的是你的带宽和资源,不是Google的。这句话的主语很关键——它没有承诺你会被抓得更勤,也没有承诺收录会变快。它承诺的只有一件事:同样的抓取次数,你少发很多字节。 ## 这条建议的收益到底该怎么算 很多人一看到抓取预算就想到收录速度,然后期待一个排名或者流量层面的回报。这个期待多半会落空。 页面体积直接决定这笔账有多大,四十六个电商站的页面体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)量的正是同一批站的字节规模。 更实际的算法是这样:你的服务器每天为爬虫发出去多少字节,其中有多少是重复发送的完全相同的内容。本次实测里,142个站的首页平均大小是707 KB,全部加起来一次就是98 MB。如果一个爬虫每天来抓十次而内容一次都没变,那就是十次707 KB。 支持304之后,这十次里的九次可以压缩成一个空响应。省下来的不是抽象的预算,是实实在在的出口带宽和数据库查询。对流量大的站,这笔账相当可观;对小站,说实话省不了几个钱,但它也几乎不花什么力气。 还有一层收益不太容易量化但确实存在:返回304的响应,服务端往往不需要走完整的渲染流程。一个动态页面的全量响应可能要查十几次数据库、跑一遍模板、再做一次压缩;而一次304只需要比对一个字符串。这部分省下来的计算资源,在大促这类高峰时段的价值远超带宽本身。 ## 它跟抓取频率是什么关系 这是个高频误解,值得说清楚。支持304不会直接让Google抓得更勤,官方也没这么承诺过。 抓取频率的真实情况只能从日志里看,日志分析一步步挖出AI爬虫真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)给了一套可复用的分析顺序。 但它们之间有一层间接联系:抓取速率的上限,一部分取决于系统观察到的你的服务器响应状况。如果你的站响应快、错误少,系统会更愿意多抓;而全量返回一个大页面比返回一个空的304慢得多。 所以合理的预期是:这条建议的主要收益在你自己这一侧,抓取侧的收益是次生的、不确定的、也没法单独归因。把它当成一件降本的事去做,比当成一件提效的事去做更不容易失望。 ## 为什么这条建议和其它建议不一样? 这是前两篇文章里那个三分法的第三格,也是最容易被忽略的一格。 这三类规则背后是同一套身份与信任机制,实体主页怎么搭才算把品牌身份立住 (https://zhangwenbao.com/entity-home-seo-ai-brand-guide-html.html)给了整体框架。 ## 平台介入的第三种方式 前面两篇分别讲了禁止型和代劳型:禁止型是平台立规矩、违反了要挨罚;代劳型是平台自己算、你只能摆原料。这一篇讲第三种,可以叫亲自型——这件事百分之百发生在你的机器上,平台只能建议,做与不做只有你自己知道。 第一类禁止型的样本是名字字段,商家名称禁令当尺子量出来的那份结果 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)是这个系列的第一篇。 类型 | 发生在谁那儿 | 官方措辞 | 失败怎么被发现 | 禁止型 | 平台的库里 | 不被允许、可能导致 | 收到处罚通知 | 代劳型 | 平台的算法里 | 偏好、支持、会考虑 | 看展示结果不对 | 亲自型 | 你的服务器上 | 我们建议、请支持 | 永远不会被通知 | 同一批电商站的另一项体检也是这个量级,四十个电商站的站内搜索页实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)可以并排看。 ## 三十秒的判据 判断一件事是不是亲自型,问两个问题就够。 第二类代劳型的样本是图标与站点名称,favicon要上广告位而两百多个站拿不出图 (https://zhangwenbao.com/favicon-site-name-platform-picks-one.html)是这个系列的第二篇。 第一个问题:这件事发生在谁的机器上。发生在你这边的,平台只能建议,因为它没有任何执行手段——它总不能替你改服务器配置。 第二个问题,也是更好用的那个:有没有一个官方工具能告诉你做到了没有。有的话,说明平台在意这个结果、并且愿意为你提供反馈;没有的话,那这件事就完全是你自己的事。 条件请求这一条,两个问题都指向亲自型。Search Console里没有这一项,富媒体测试工具里没有,页面体验报告里也没有。你唯一的检查手段是自己发一次请求。 ## 亲自型的投入曲线是线性的 这一点跟前两类差别很大。禁止型是阶跃:过线之前为零,过线之后不再增长。代劳型是钝的:收敛候选很有用,超出之后无效。亲自型是线性的:做多少得多少,而且不封顶。 服务端这一层的活基本都属于做多少得多少,服务器配置对SEO影响的二十项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)里全是这一类。 为什么线性,因为它省下来的东西是按次计的。你的站被抓得越频繁、页面越大、变更越少,这条建议的收益就越高。这也是为什么它写在“大型站点”那份文档里——规模本身就是它的乘数。 也正因如此,它是三类里唯一一个值得长期投入的。禁止型做完就该走人,代劳型收敛完就该停手,只有亲自型的活会随着你的站变大而持续升值。 ## 没有反馈这件事有多要命 把三类规则的反馈机制并排看,差别一目了然。 没有反馈的时候只能自己造一个观测,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)讲的就是怎么造。 禁止型有明确的通知:资料被暂停会发邮件,手动操作会在后台显示,你不可能不知道。代劳型虽然没有通知,但结果是肉眼可见的——搜索一下自己的品牌,图标和名字对不对一目了然。 亲自型两样都没有。做与不做,页面表现完全一样;做错了和做对了,浏览器里看不出任何区别。你的服务器可能已经连续三年在为爬虫重复发送同样的几百KB,而没有任何一个系统觉得这值得提一句。 ## 所以它的失败模式是“一直没做” 其它两类规则的失败通常是一次性事件:某天改错了、某天被罚了。亲自型的失败是一种持续状态——它从上线第一天起就没做,然后一直没做,中间没有任何一个时刻会变糟,也就没有任何一个时刻会引起注意。 持续状态的失败最难被注意到,用户扫完一整屏一个都没点开这件事 (https://zhangwenbao.com/product-list-item-attributes-silent-rejection.html)也是同一种静默。 这解释了本次实测的一个现象:做到和没做到的分布,跟站点规模、品牌知名度、技术水平的相关性都不强,反而跟“用的是哪套基础设施”高度相关。因为绝大多数团队从来没主动做过这个决定,最终结果就是它们的服务商替它们做了。 ## 一次条件请求究竟在问什么? 要看懂后面的数据,得先把机制过一遍。这套东西不复杂,但有几个反直觉的点。 机制讲清楚了才知道报表在说什么,hreflang备用网址被当成规范页别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)也是先把机制拆开。 ## 整个流程分两步 第一步,客户端正常请求一个地址,服务端返回内容,同时在响应头里附上一张或两张“凭据”。凭据有两种:一种叫 ETag,是这份内容的一个标识符 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag);另一种叫Last-Modified,是这份内容的最后修改时间。 抓取与渲染分几步直接影响服务端要付出多少,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)把这条链路拆开讲过。 第二步,客户端下次再来的时候,把凭据带上:拿ETag的用If-None-Match这个请求头,拿时间的用If-Modified-Since。服务端比对之后,如果内容确实没变,就返回304和一个空的响应体;变了就返回200和完整内容。 这套机制的正式定义在 HTTP语义规范里条件请求那一章 (https://www.rfc-editor.org/rfc/rfc9110.html),缓存相关的部分则在另一份专讲HTTP缓存的规范 (https://www.rfc-editor.org/rfc/rfc9111.html)里。 ## 两种凭据的差别比想象中大 | ETag | Last-Modified | 本质 | 内容的标识符 | 一个时间戳 | 精度 | 可以精确到字节 | 最细只到秒 | 生成成本 | 通常要读一遍内容 | 读一下文件属性即可 | 失效风险 | 内容含随机成分就永远变 | 时间戳被写成当前时间就永远变 | 本次实测覆盖率 | 54.2% | 12.7% | 响应头这一层的能力比多数人以为的多,用内容协商给AI交付Markdown的实操 (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是另一个用法。 规范里还区分了强校验和弱校验:ETag前面带W斜杠前缀的是弱校验,表示两份内容语义等价但字节未必完全相同。本次样本里绝大多数ETag都是弱校验,这很正常,因为动态生成的页面很难保证字节级一致。 ## 弱校验在这里是加分项 很多人看到弱校验会觉得不严谨,其实反过来。弱校验允许你说“这两份内容语义上是一样的”,即使它们的字节不完全相同。这正好是动态页面需要的能力。 想看别人的响应头怎么配,十款网站技术栈检测扩展的实测对比 (https://zhangwenbao.com/seo-website-technology-stack.html)里有能直接读的工具。 理论上,一个实现得好的服务端可以主动利用这一点:把页面里那些不影响语义的部分——随机令牌、请求编号、渲染时间戳——排除在哈希计算之外,然后打上弱校验标记。这样即使字节变了,标识符也不变,条件请求照样能生效。 本次实测里没有看到有站这么做。那五个长度段不变、哈希段变的站,用的都是对整个响应体做哈希的默认实现。它们打了弱校验的标记,行为却是强校验的。标记和实现不一致,这是另一种形式的名不副实。 这也给出了一条很具体的改造思路:你不一定要把随机令牌从页面里挪走,只要把它排除在哈希计算之外就行。前者要动前端和后端的交互方式,后者只需要改一处哈希逻辑,成本差好几倍。 ## 最容易被误解的一点 很多人以为返回304就等于“这个页面被缓存了”,然后担心内容更新之后用户看到旧版。这是两件事。 缓存与索引状态经常被混为一谈,已收录页面加noindex后多久消失的六大场景实测 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)把这两件事分开量过。 缓存策略由Cache-Control这类响应头决定,它说的是“这份内容可以被存多久”。条件请求说的是“存着的那份还能不能用”。前者决定要不要问,后者决定问了之后怎么答。 所以支持304完全不影响内容的时效性——内容真变了,服务端就返回200和新内容,一秒钟都不会延迟。它省的只是那些确实没变的时候的重复传输。 ## 还有一个概念也常被混淆 304和200之间还夹着一个容易被忽略的区别:304不是“这个页面没变”,而是“你手上那份还能用”。主语是客户端手上的副本,不是页面本身。 概念混用是很多错误结论的起点,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)就是一次口径混用的代价。 这个区别在实践里有意义。假设一个页面被改了又改回来,字节完全恢复原样,那么ETag也会恢复原样,条件请求照样返回304,而中间那次改动对客户端来说等于没发生过。这套机制关心的是等价,不是历史。 反过来的情况也存在,而且更常见:内容在语义上完全没变,字节却变了。页面里换了个随机令牌、请求编号变了一位、某个时间戳精确到了秒,这些都不影响任何人读到的东西,但足以让整份内容的哈希彻底改变。 这就是后面那批数据的核心矛盾:一个用来判断“是不是同一份内容”的机制,实际判断的是“是不是同一串字节”,而这两者在动态页面上经常对不上。规范给了弱校验这条出路,可惜实测里几乎没人真的用起来。 ## 为什么这套机制没被更广泛地实现 说一句公道话:对静态文件来说这件事几乎是白送的,服务器自动就做了;难的是动态页面。 静态与动态的差别决定了这件事的难度,SaaS托管自建与纯代码的选型全拆解 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)里有各类栈的对比。 动态页面要生成ETag,服务端得先把整个响应体渲染出来,才能算出哈希——而渲染本身就是最贵的那一步。算完哈希发现可以返回304,省下的只是网络传输,计算已经花掉了。 要真正省掉计算,得在渲染之前就知道内容有没有变,这需要一个可靠的版本标识:内容的更新时间戳、缓存条目的版本号、或者数据层的变更序号。这一步是有设计成本的,也是大多数站停在半路的地方——它们生成了ETag,但那个ETag是渲染完之后算的。 ## 第一关:142个站里有多少个能被问? 要回答“变了没有”,你首先得给出一个可以拿来比对的凭据。这一关卡住的站比预想的多。 能不能被问取决于你有没有给出可引用的东西,GSC品牌词过滤器的五步使用指南 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)里那套拆分也依赖你先给出可用的标记。 ## 怎么测的 对211个域名的首页各发一次普通请求,跟随跳转,从最终那个响应的头里读ETag、Last-Modified、Cache-Control、Vary、Server这几项。211个里有142个返回了200,其余是人机验证、跳转或者连不上,不进统计。 批量发请求并读响应有现成的做法,网站死链怎么批量查出来的一条龙流程 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接改来用。 有一个技术细节值得交代:响应头必须取最后一个响应块的,不能取第一个。因为跟随跳转的时候,会依次收到跳转响应的头和最终响应的头,两者的ETag和缓存策略往往完全不同。如果取错了,测的就是跳转那一跳的行为,跟内容页没关系。 这一步在写脚本的时候特别容易搞错,而且错了之后数据看起来完全正常——你会得到一批合法的、但描述的是另一个东西的响应头。这类错误的隐蔽性跟本文后面要讲的那几个问题是同一个性质。 ## 七次请求分别在测什么 每个地址一共发七次,各有分工,列出来方便你自己复现。 测法设计决定结论能不能用,三百个站实测出来的收录速度指标怎么读 (https://zhangwenbao.com/seo-kpi-guide.html)里有同一类的设计说明。 第几次 | 发什么 | 测什么 | 第一次 | 普通请求 | 拿凭据、拿缓存策略、拿体积 | 第二次 | 同样的普通请求 | 凭据稳不稳 | 第三次 | 带上第一次拿到的ETag | 认不认自己发的标识符 | 第四次 | 带上第一次拿到的时间 | 认不认自己发的时间戳 | 第五次 | 带一个一小时前的时间 | 没有凭据时能不能答 | 第六次 | 只要响应头的那种请求 | 换个方法答不答得上来 | 第七次 | 问支持哪些方法 | 规范里那一条有没有实现 | 七次里前五次是这篇文章的主线,后两次是顺带。如果你只想自查,跑前三次就够了,两分钟。 换一种口径去看,缺口才会显形,日志里带人来的其实是另一批入口 (https://zhangwenbao.com/ai-referral-source-domestic-entries-gap.html)是同一种发现方式。 ## 并发和礼貌 顺带说一句抓取礼仪。本次是二十多个并发跑完两百多个域名的七次请求,总请求量一千五百次左右,对每个站来说就是七次,负载可以忽略。 被防护层当成可疑流量是很常见的事,五种代码识别搜索引擎蜘蛛的实战指南 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)从另一侧解释了判定逻辑。 但如果你要做更大规模的测量,请把并发限制在合理范围,并且给同一个域名的请求之间留间隔。本次有4个域名返回了限流状态码,说明防护层确实在盯着。被限流不只是拿不到数据的问题,它还会污染你的样本——被限流的站会掉出统计,而它们未必是随机掉的。 ## 被排除的那69个是什么情况 211减去142,还剩69个没进统计。分布是:返回拒绝访问的34个、完全连不上的20个、停在跳转上的8个、被限流的4个,剩下几个是各种其它状态。 被排除的样本会悄悄改变结论边界,调研数据里没有一个非会员却写给非会员看 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)是这一类的典型。 拒绝访问那34个绝大多数是人机验证——本次抓取用的是普通浏览器标识,被防护服务拦下很正常。这批站不是没做,是没让我测。它们对真实爬虫的行为可能完全不同,所以本文所有比例都只代表能被正常访问的那142个。 这个偏差的方向不好判断。一方面,上了严格防护的站通常技术投入更高,可能做得更好;另一方面,防护层本身也会改变缓存行为。说不清方向的偏差,就只能如实标出来,别假装它不存在。 ## 结果 凭据情况 | 站数 | 占142的比例 | 有ETag | 77 | 54.2% | 有Last-Modified | 18 | 12.7% | 两个都有 | 10 | 7.0% | 一个都没有 | 57 | 40.1% | 四成的站,连被问的资格都没有。爬虫想问一句“这页变了没有”,找不到任何可以引用的东西,只能整页重下。 ## 这四成里大部分是主动放弃的 翻了一遍这57个站的响应头,发现一个很清楚的规律:其中相当一部分的Cache-Control里写着no-store或者no-cache。 保守策略是有代价的,支付页CSP实测五十三个站的出厂默认 (https://zhangwenbao.com/payment-page-csp-factory-default-script-policy.html)里有同一种权衡。 no-store的意思是“任何环节都不要存这份内容”。既然不让存,那也就没有“存着的那份还能不能用”这个问题,不给凭据在逻辑上是自洽的。这批站不是没做好,是明确选择了不参与这套机制。 这个选择通常出于两个理由:一是首页高度个性化,每个人看到的都不一样;二是安全或合规要求,不希望任何中间节点留存内容。理由都成立,但代价是每一次抓取都是全量。 ## 剩下那部分才是真的漏了 另一部分站的Cache-Control写的是public加一个不小的max-age,明确表示这份内容可以被缓存很久——但它一个凭据都不给。 自相矛盾的配置该在上线前拦下来,新网站前十二周的技术地基清单 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)里有对应的检查项。 这就自相矛盾了:你说这份内容可以存一个小时,可你没给任何办法让人确认这一个小时之后它还是不是原来那份。缓存到期之后,客户端只能整页重下,前面那个max-age相当于白设。 这一类才是真正意义上的疏漏,而且修起来最简单——绝大多数服务器和CDN都支持自动生成ETag,通常就是一个开关。 ## 怎么区分自己属于哪一类 看两个头就够了。如果Cache-Control里有no-store,那是主动放弃,不用管;如果写的是public加一个max-age,或者干脆什么都没写,而同时又没有任何凭据,那就是疏漏。 一条记录背后的展开规则往往不由你定,SPF记录只有一行展开要查几次是别人定的 (https://zhangwenbao.com/spf-lookup-limit-upstream-inherited-dns.html)是同一类隐性约束。 本次142个站里,没有Cache-Control这个头的有70个,接近一半。这一档最尴尬:它既没有明确说可以缓存,也没有明确说不要缓存,缓存行为完全交给各个客户端按启发式规则去猜。 猜的规则通常是这样:客户端拿最后修改时间和当前时间的差算一个比例,得出一个自己觉得合理的缓存时长。而如果你连最后修改时间也没给,那这套启发式也用不上,结果就是每次都重下。 ## 顺带说说Vary这个头 还有一个容易被忽略的相关项。Vary声明的是“这份响应的内容会随哪些请求头变化”,比如随语言变、随设备变、随压缩方式变。 同一份内容对不同客户端呈现不同版本,浏览器自动翻译把选项改掉而问卷看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是个极端案例。 它跟条件请求的关系是:如果你的内容真的会随某个请求头变,那就必须声明,否则缓存层可能把A用户的版本拿给B用户。但反过来,Vary声明得太宽也有代价——每多一个变量,缓存的命中率就降一档。 本次没有对Vary做详细统计,只在读头的时候顺带记录了。写在这里是提醒你,条件请求这件事不是孤立的,它和缓存策略、内容协商是同一套东西的三个侧面。 ## 第二关:那张凭据稳不稳? 给了凭据只是第一步。如果同一个地址每次给的凭据都不一样,那这张凭据等于没有。 稳定性是很多机制生效的隐含前提,AI搜索可见性的五维度深层策略 (https://zhangwenbao.com/ai-search-visibility-deep-seo-strategy.html)里也有同类前提。 ## 连发两次,看凭据变不变 测法很简单:对同一个地址,间隔几秒钟连发两次普通请求,把两次拿到的ETag和Last-Modified并排比。中间没有任何人改过内容,所以理论上它们应该完全相同。 两次观测才看得出的问题,跟测试期外部扰动是同一类,测试赢了上线却掉的那二十六天 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)值得对照。 比对项 | 结果 | 两次ETag完全相同 | 57个站 | 两次ETag不同 | 16个站 | 两次Last-Modified不同 | 2个站 | 有ETag的77个站里,16个的ETag在几秒钟内就变了,占21.9%。对这16个站来说,条件请求这套机制从一开始就不可能生效——爬虫拿着上次的凭据来问,服务端一比对发现对不上,只能返回200和全量内容。 ## 这件事没有任何指标会报警 值得停下来想一想这个问题的性质。这16个站:有ETag、格式合法、响应正常、页面显示一切正常。任何一个只看单次响应的检查都会给它们打勾。 没有报警不等于没有问题,最佳实践清单里九条查得到出处八条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)也是靠人工核对才发现的。 问题只有在把两次响应并排放的时候才会暴露,而这个动作不在任何一份标准检查清单里。需要两次观测才能发现的问题,几乎注定会被单次观测的工具全部漏掉。 ## 为什么两次之间要留几秒 这个间隔的选择有讲究。间隔太短,可能命中同一个缓存条目,看不出问题;间隔太长,内容真有可能变了,那就分不清是随机值作祟还是真的更新了。 观测间隔属于测量设计的一部分,埋点之前先把测量框架设计清楚 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)讲了这类前置决定的分量。 本次用的是几秒钟的间隔,理由是:几秒内一个电商首页的实质内容变化的概率极低,而缓存层的短时命中窗口通常也在这个量级之内。如果你自己测,可以试两个不同的间隔——几秒和几分钟各一次,结果一致就更放心。 ## Last-Modified那两个不一致的更奇怪 ETag变了还能理解,毕竟它算的是内容。最后修改时间在几秒钟内变了,那就意味着这个站在说“这份内容刚刚又改过一次”。 数字对不上往往指向连接键的问题,五个渠道加起来一百五十九个百分点 (https://zhangwenbao.com/comparison-shopping-co-presence-join-key.html)是同一种反推。 本次首页这一层抓到两个,都是往回退的——第二次请求拿到的时间比第一次更早,一个退了三个小时,一个退了四分钟。这不可能是内容真的变了,只可能是两次请求落在了不同的节点上,而这些节点各自持有不同的版本。 这一条后面还会展开,因为在内页那一轮里,同类问题出现得更极端——有一个站的两次时间相差八个多小时,同样是往回退的。 ## 节点不一致这件事的连带影响 时间倒着走这个现象,暴露的问题比条件请求本身大得多。它说明同一个地址在同一时刻,会因为落在不同节点上而返回不同版本的内容。 同一份规则在不同处理路径上行为不同,robots规则的星号对某些爬虫无效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)是另一个版本。 这件事的影响面很广。对用户来说,可能刷新一下页面内容就变了;对测量来说,你做的任何A/B测试都可能被这层不一致污染;对抓取来说,系统看到的这个地址是一个不稳定的东西,而不稳定的东西通常会被更谨慎地对待。 本次能看到它,纯属条件请求这套测法的副产品——因为只有连发两次并把响应头并排比,这个问题才会露头。如果只测一次,你看到的是一个完全正常的响应。 所以这条自检的价值可能超出条件请求本身:它顺带是一次很便宜的节点一致性探测。两次请求,如果拿到的凭据在格式或者时间上有系统性差异,那你的部署八成有问题。 ## 从ETag的形状能读出什么根因? 这是本次实测最有意思的一段。把那16个站的两次ETag并排一放,成因几乎是明写在上面的。 从结构反推含义是通用手法,用SignificantLink和RelatedLink表达页面关系 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)里的标记也是可读的。 ## 第一类:长度段不变,哈希段在变 有五个站的ETag长这个样子:一个W斜杠前缀,然后一段十六进制数字,一个连字符,再接一段摘要。比如某个站两次拿到的分别是96c1d开头和96c1d开头,前面那段完全一样,只有后面的摘要不同。另外四个站分别是886f1、4295d、137cee、fa604开头,情况完全一致。 自动生成的字符串里藏着大量可读信息,Shopify的一百二十八种结构化数据类型怎么挑 (https://zhangwenbao.com/shopify-schema-seo-guide.html)里也有靠结构判断的例子。 这种格式是很多服务端框架的默认实现:前半段是内容的字节长度,后半段是内容的哈希。那么这五个站的情况就变成了一句可以直接下结论的话—— 页面的字节数一个都没多、一个都没少,内容却算出了不同的哈希。 能同时满足这两个条件的,只有一种情况:页面里嵌了一段长度固定、内容随机的字符串。最常见的就是防跨站请求的令牌、脚本安全策略里的一次性随机数、请求追踪编号、或者某个会话标识。 ## 这个推断为什么可以直接用 因为它把排查范围从“整个页面”缩小到了“一段定长随机值”。你不需要逐行比对两次的HTML,只要去搜那几类常见的定长随机串,基本一抓一个准。 靠外部观测就能定位根因的手法很值钱,GEO投毒的三条攻击路径与三层防御 (https://zhangwenbao.com/geo-ai-poisoning-315-deep-analysis.html)也用了同一类推理。 这是一条完全靠观察响应头就能得到的诊断结论,成本是两次请求。保哥觉得这是本次实测里性价比最高的一个发现——它不需要访问服务器、不需要看代码、不需要任何权限。 ## 第二类:整条ETag的格式都变了 另外两个站更奇怪。其中一个的两次ETag,第一次是十四个字符的短串,第二次是三十二个字符的长串。不但值变了,连长度和格式都变了。 同一站点不同版本共存会带来一堆隐性差异,网站无障碍访问怎么做的十八个改动 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)里提过版本一致性的重要。 同一个地址,两次请求,返回了两种不同格式的ETag,最合理的解释是这两次请求被两台配置不同的节点分别处理了。可能是不同版本的服务在灰度共存,也可能是两个机房的配置漂移了。 这一类的性质跟第一类完全不同:第一类是内容里有随机值,第二类是基础设施本身不一致。修法也不一样——前者改页面,后者查部署。 ## 第三类:缓存键相同但摘要不同 还有九个站的ETag是这样一种结构:一个固定的前缀词,一个数字编号,一个控制器名,最后是一段三十二位的摘要。两次请求里,前面三段一模一样,只有最后那段摘要在变。 缓存键与内容标识是两件事,混用会让整套机制失效,Schema聚合的五步接入方法 (https://zhangwenbao.com/yoast-schema-aggregation-agentic-web-seo.html)里也有类似的键与值分不清的坑。 从结构能看出这是某套全页缓存的实现,前面几段是缓存条目的键。缓存键相同,说明系统认为这是同一个缓存条目;摘要不同,说明它每次都重新算了一遍渲染结果的哈希。 这类实现的问题在于,哈希算的是这一次渲染出来的字节,而不是这个缓存条目的身份。一个用来标识“是不是同一份内容”的东西,被拿去标识“这一次输出的字节”,两者在有随机成分的页面上永远对不上。 ## 三类合起来的启示 形态 | 站数 | 根因 | 该找谁修 | 长度段不变、哈希段变 | 5 | 页面里有定长随机值 | 前端或模板 | 缓存键相同、摘要变 | 9 | 哈希算的是输出不是身份 | 缓存层配置 | 格式和长度都变 | 2 | 节点配置不一致 | 运维或部署 | 同一个现象三种成因三个负责人,商品页推荐位两套报表打架的那次复盘 (https://zhangwenbao.com/product-page-recommendation-attribution-mismatch.html)也是这种局面。 三种成因,三个不同的负责人,而它们在监控面板上的表现完全一样:什么表现都没有。 ## 这套读法可以推广到别处 从一个字符串的结构反推它的生成方式,这个手法本身比这次的具体结论更值钱。 拼出来的字符串都能这么读,UTM链接构建器的规范与避坑清单 (https://zhangwenbao.com/utm-builder-utm-tracking-link-campaign-url-guide.html)里那套参数就是典型的拼装结构。 能这么读的前提是:这个字符串是机器按固定模板拼出来的,而模板的每一段各有含义。符合这个条件的东西比你想的多——缓存键、构建产物的文件名、追踪参数、订单编号、日志里的请求标识,都是拼出来的。 读法也有固定套路:先找哪一段变了、哪一段没变,再问“什么情况下会只有这一段变”。这个问题往往只有一两个可能的答案,因为每一段的含义把可能性框死了。 本次那五个站就是最干净的例子:长度段没变、哈希段变了,那么“内容长度不变但内容变了”这个约束,直接把答案锁死在定长随机值上。不需要看代码,不需要问人,两次请求就够了。 ## 顺便说一个反面教训 这个手法有个前提容易被忘:你得先确认那个格式的含义,别自己脑补。 先确认含义再解释样本,品牌词和非品牌词那条线画在哪 (https://zhangwenbao.com/brand-nonbrand-split-grounding-query.html)记录过一次因为记错含义而全盘推翻的过程。 本次一开始我把某个站的ETag前半段当成了时间戳,推出一个完全错误的结论,后来对着另外几个站的样本才发现那是十六进制的字节长度。五个站的前半段分别是五个不同的值,而它们的页面大小也确实各不相同——这才是能确认含义的证据。 所以正确的顺序是:先收集足够多的同格式样本,用样本之间的差异去确认每一段的含义,再拿这个含义去解释单个样本。反过来做,你会得到一个自洽但错误的故事。 ## 第三关:真发条件请求,回不回304? 前两关都是看响应头,这一关是真的把凭据带上重发一次。 做了一半的投入最容易被忽略,共识层六信号的九十天实战指南 (https://zhangwenbao.com/seo-consensus-layer-ai-search.html)里也点过这类半成品。 ## 拿ETag去问 对77个有ETag的站,带上If-None-Match重发一次,结果是这样: 逐项验证比一次性判断可靠,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)也是一项一项过的。 返回 | 站数 | 比例 | 304未修改 | 48 | 62.3% | 200全量重发 | 25 | 32.5% | 301跳转 | 4 | 5.2% | 三成二的站,发了凭据却不认自己发的凭据。这个数字比前面两关都更让人意外——它们已经完成了最难的那一步,只差最后一步没做。 需要说明一下这个测法的一个边界:本次是把第一次拿到的ETag原样带回去问的。如果一个站的ETag本身就不稳定,也就是第二关没过,那它在这一关必然也过不了,两关的失败在统计上有重叠。所以第三关那25个里,有一部分其实是第二关的问题在这里再次显形。 把两关分开看仍然有意义,因为修法完全不同:第二关的问题在页面内容或者节点配置上,第三关的问题在比对逻辑上。但引用这两个数字的时候别把它们简单相加,那会把同一批站算两次。 这也是本系列反复出现的一条提醒:任何一个漏斗,都要先问相邻两级之间是不是独立的。不独立的话,累加、相乘、算转化率这些操作全都会失真,而失真的方向通常是把问题放大。 ## 拿时间去问 对18个有Last-Modified的站,带上If-Modified-Since重发,14个返回304,占77.8%。成功率比ETag那条路还高。 精确的机制未必更稳,微软广告改UTM自动打标之后的归因影响 (https://zhangwenbao.com/microsoft-ads-utm-auto-tagging-channel-attribution.html)里有类似的反直觉结果。 这个对比有点反直觉。ETag理论上更精确、更可靠,实际成功率却更低。原因在于精确本身就是负担:ETag要求内容一个字节都不能变,而时间戳只要求秒级不变。页面里那段随机令牌会毁掉ETag,却毁不掉Last-Modified。 不过这个对比要小心解读:Last-Modified的样本只有18个,而ETag有77个。十八个里成功十四个,跟七十七个里成功四十八个,前者的置信度低得多。这一条应该当成一个值得注意的方向,而不是一个可以直接引用的比例。 为什么样本这么不平衡,本身也说明了一件事:愿意给时间戳的站少得多,因为动态页面的框架往往不知道该填什么。而那些愿意填的,通常是真的想清楚了内容的更新时间从哪来——这批站本来就更用心,成功率高一点也在情理之中。 这是一个典型的选择偏差:不是这条路更好走,是走这条路的人本来就更强。看到两个成功率的时候,要先问一句“这两组样本是怎么进来的”,而不是直接比大小。 类似的陷阱在SEO数据里到处都是。比如“配了某项标记的站排名更好”,很可能只是因为愿意配那项标记的团队本来就更专业。相关不等于因果这句话人人会背,难的是每次看到数字的时候真的停下来问一句。 ## 再补一个额外测的场景 顺手还测了一种情况:不管这个站给不给凭据,一律带上一个“一小时前”的时间去问。这相当于在说“我手上有一份一小时前的副本,还能用吗”。 多设计一个场景往往能挖出新结论,GEO到底怎么落地的实施策略 (https://zhangwenbao.com/geo-strategy.html)里有几组类似的场景设计。 结果是142个站里只有10个返回304,占7.0%。这个数字低得符合预期——绝大多数站在这种情况下不敢说“还能用”,因为它们根本不知道自己一小时前是什么样。 这个测法的价值在于它模拟了一种真实场景:客户端手上的副本不是刚拿到的,而是放了一阵子的。能在这种情况下答得上来的站,说明它真的记录了内容的更新时间,而不只是把当前时间填了上去。那10个站,是这批样本里这件事做得最扎实的一批。 ## 合起来看 把两条路合并,只要有任意一种条件请求能返回304就算通过:142个站里52个,36.6%。 把这个数字拆开看更清楚:四成的站没凭据,两成有凭据但凭据不稳或者不认,剩下三成六才是真正做到了。三道关卡,每一关都刷掉一批。 ## 这个漏斗的形状值得看一眼 关卡 | 剩下多少 | 被刷掉的原因 | 起点 | 142 | — | 第一关:有凭据 | 85 | 57个一个凭据都不给 | 第二关:凭据稳定 | 约69 | 16个的凭据几秒内就变了 | 第三关:真能回304 | 52 | 剩下的没做比对逻辑 | 漏斗形状比单个数字更有信息量,砍掉虚荣指标只盯真信号 (https://zhangwenbao.com/vanity-metrics-north-star-omtm-ecommerce.html)讲了怎么读这类结构。 这个漏斗有个不太常见的特点:三关的流失率相当平均,没有哪一关是绝对的瓶颈。四成、两成、一成多,一路刷下来。 大多数漏斗不是这样的,通常有一个明显的卡点,你集中解决它就能大幅提升。而这个漏斗告诉你,这件事没有捷径,三个环节各有各的成因、各归各的负责人,得一关一关过。 好消息是每一关的修复成本都不高,坏消息是你得把三关都过一遍才有结果。只做第一关,也就是开个开关生成凭据,结果可能是从没凭据变成有凭据但不被认,通过率一点没涨。 这一点在实践中很容易踩到,因为“开启ETag”是搜索这个问题最容易搜到的答案,而且做完之后你去看响应头,确实多了一行,看起来像是成功了。只有真的带着凭据重发一次,才知道有没有用。 所以自检的顺序很重要:先测终点,再往回找卡在哪一关。直接发一次条件请求,回304就全通过了,什么都不用改;不回304,再往回查是没凭据、凭据不稳、还是没做比对。这个顺序能省掉大量无谓的排查。 ## 那52个通过的站有共同点吗 翻了一遍这份名单,最明显的共同点不是品类,也不是体量,而是它们跑在哪套基础设施上。几类现代托管平台的站几乎全数通过,而某些传统加速服务上的站通过率明显偏低。 早期的技术选型会一路影响到很多年后,建一个大站还是多个小站的取舍 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)里算的也是这类长期账。 这个观察跟后面那一节会讲的服务器分布是一致的,而且它有个不太舒服的含义:这批站里的多数,大概率并不知道自己做到了。它们通过,是因为服务商默认就这么做;那些没通过的,也是因为服务商默认不这么做。 换句话说,这条建议在实践中的落实情况,跟“有没有人读过那份文档”关系不大,跟“选了谁家的服务”关系很大。这正是亲自型规则最讽刺的地方——一件完全由你决定的事,实际上被你多年前的一次选型决定了。 ## 这三成六该怎么解读 先说清楚它不是什么。它不是“三成六的站做得好、六成四做得差”,因为其中有一批是主动选择不参与的,那是业务决定,不是技术缺陷。 没人考核的事最容易一直不做,把品牌当权重的四大战略 (https://zhangwenbao.com/seo-without-brand-building.html)里也讲过这类长期没人认领的投入。 更准确的读法是:在一条Google明确写进官方文档的建议上,能被外部验证做到的,只有三分之一出头。而这条建议既不涉及内容决策、也不涉及跨部门协调、更没有任何反向风险。 这个对比才是真正值得琢磨的:一件几乎没有阻力的事,落实率也只有三成六。阻力不在难度上,在可见性上——没人查、没人报警、没人考核,于是它就一直没被排进任何一个人的待办里。 本次三篇文章量的三样东西,落实率分别是六成五、两成二、三成六,形态各异,但成因高度一致。它们全都属于那种“不做也不会有人发现”的事。 ## 省下来的量有多大 那52个能回304的站,全量响应平均是798.6 KB,而304响应的响应体是零字节。省掉的是接近百分之百的传输量。 带宽与计算的账要分开算才知道优化落在哪一侧,网址用扁平还是层级在SEO上到底差在哪 (https://zhangwenbao.com/flat-urls-vs-hierarchical-urls-for-ecommerce-sites.html)也是一笔要拆开算的账。 当然这是单次的账。实际能省多少,取决于爬虫来的频率和你内容的变更频率。内容越稳定、被抓得越勤,省得越多;一个每天都在变的页面,这条机制本来也帮不上什么忙。 ## 那25个不认自己凭据的站最值得说 三成二这个比例,是本次实测里最出乎意料的一个数字。这些站已经跨过了最难的一关——它们生成了ETag,说明服务器或者框架已经算过内容的哈希了。 付出成本却没拿到收益是最亏的一档,阿里国际站五百九十万页面被清零的复盘 (https://zhangwenbao.com/alibaba-aigc-google-deindex-dtc-seo-guide.html)也是这种结局。 差的只是最后一步:收到If-None-Match之后,把它跟当前算出来的ETag比一下,相同就返回304。这一步在多数实现里就是几行代码或者一个配置项。 为什么会差这一步?最常见的两种情况:一是ETag由某个中间层生成,而处理请求的应用层根本不知道有这回事,也就不会去比对;二是应用层为了避免缓存问题,主动把请求里的条件头剥掉了,比对逻辑收到的是一个空值,自然永远不成立。 无论哪种,特征都是一样的:这个站在这件事上花了成本,却一分收益都没拿到。而它自己完全不知道。 ## 那4个返回跳转的又是另一回事 还有4个站,带上条件请求之后返回了301。这说明这几个地址在带条件头的情况下走了不同的路由分支——正常请求直接返回内容,带了条件头就变成跳转。 跳转链是抓取预算里另一条明确被点名的浪费,多域名301跳转到主域名的完整配置实战 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)里有正确写法。 这种行为本身不算错,但它很怪,因为跳转目标通常还是同一个地址。更可能的解释是某个安全或者防护层把带有不常见请求头的请求当成了可疑流量,先跳一次再说。 这一类的影响是双重的:既拿不到304,还多了一跳。而抓取预算那份文档里,恰好有另一条建议是“避免重定向链”。一条建议没做到,顺带把另一条也违反了。 ## 首页骗了你 做到这里我本来打算收工,直到想起一件事:Googlebot每天抓的绝大多数请求不是首页,是内页。于是又跑了一轮。 首页在很多维度上都是最不具代表性的一页,首页首屏的导航主Banner到分类区怎么设计 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)讲了它的特殊性。 ## 换一批地址重测 从这些站自己的站点地图里,每站挑一个有一定深度的具体页面,重复完全相同的七次请求。最后拿到90个可测目标,其中89个返回200。 换一批地址结论可能完全不同,一万个电商站的网址结构实测结论 (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)也是靠大样本才站得住。 指标 | 首页(142个) | 内页(89个) | 有ETag | 54.2% | 73.0% | 有Last-Modified | 12.7% | 6.7% | 一个凭据都没有 | 40.1% | 22.5% | ETag换304成功率 | 62.3% | 84.6% | 任一条件请求回304 | 36.6% | 65.2% | 两次ETag不一致 | 21.9% | 4.6% | ## 差了将近一倍 同一批站,首页只有36.6% 能回304,内页有65.2%,差1.8倍。而ETag不稳定这个问题几乎只在首页出现:首页两成二,内页不到百分之五。 不同页面类型的表现差异往往被平均值掩盖,信息词流量过大的六大危害与破局 (https://zhangwenbao.com/informational-keywords-traffic-dtc-ecommerce-seo-strategy.html)是同一类分层问题。 成因不难想。首页是全站个性化程度最高的一页:推荐位、促销条、地区提示、购物车数量、A/B分桶、会话令牌,全都挤在这一屏。每一样都会让这一次输出的字节跟上一次不同。而一个具体的商品页或者文章页,内容天然稳定得多。 还有一层原因是缓存策略的差别。首页往往被单独配置成不缓存或者短缓存,因为它承载的信息最杂、出错代价最高;而内页通常走通用规则,缓存策略更宽松,凭据也就更容易被生成和保留。首页的谨慎是有道理的,只是这份谨慎顺带把这条省钱的路也关掉了。 ## 这个差别对怎么排查有直接影响 如果你只测了首页、发现结果很差,正确的下一步不是大动干戈改首页,而是先去测几个内页,看看差距有多大。 本次数据里这个差距是1.8倍。如果你的站也是这个量级,那么结论就很清楚:首页那一层可能确实改不动(个性化是业务需要),但内页那一层大概率只差一个开关或者一段比对逻辑。 反过来,如果你测下来首页和内页一样差,那说明问题出在更底层——大概率是整站的服务器或者加速层配置,而不是首页的个性化。同一个测法,跑两类页面,就能把问题定位到不同的层。 ## 为什么内页样本只有90个 首页那一轮有211个域名,内页这一轮只挑出90个可测目标,差距不小,值得交代一下。 站点地图的可达性直接决定了很多流程能不能跑通,怎么实时推送搜索引擎的三种做法 (https://zhangwenbao.com/wordpress-baidu-active-push.html)也依赖同一份地址清单。 原因是内页地址来自各站自己的站点地图,而不是所有站都能顺利拿到。有些站的站点地图入口找不到,有些是索引文件套索引文件、展开层数不够,还有些返回的是压缩格式或者需要特定请求头。能拿到一个可用内页地址的,就这90个。 这个筛选是有偏的:站点地图规整、可公开访问的站,技术执行力大概率更强。所以内页那一轮65.2% 的通过率,很可能是高估。真实的全样本内页通过率应该低于这个数,但仍然会明显高于首页——因为首页与内页的差别是结构性的,不会被这个偏差抹平。 把两个方向的偏差都说清楚之后,能站得住的结论就只剩一条:首页和内页有系统性差异,测的时候必须分开。至于具体差多少,本次给出的1.8倍只能当参考量级,不能当精确数字。 ## 顺带说说怎么挑内页样本 本次是从每个站自己的站点地图里,取中间位置的一个地址。为什么取中间不取第一个?因为站点地图的开头往往是首页、分类页这类特殊页面,取中间更容易拿到一个普通的内容页。 抽样方式决定了你测到的是哪一类页面,七步GEO实战的写作流程 (https://zhangwenbao.com/seo-article-writing-tips.html)里也强调过样本选择。 这个细节看着琐碎,但它决定了你测的到底是不是有代表性的那一类页面。如果全取第一个,测出来的可能又是一批个性化重的页面,那这一轮对照就白做了。 ## 这条对照给出的实操结论 第一,别拿首页去判断你的站支不支持条件请求。首页是全站最不具代表性的一页,用它测出来的结论会系统性地低估你。 抓的和看的往往不是同一部分,那几张没露出来的商品图 (https://zhangwenbao.com/product-gallery-truncated-thumbnail-signposting.html)说明了这个错位。 第二,反过来也一样,只测内页会高估你。正确的做法是两边都测,然后分开看:首页那一类页面本来就难做,内页那一类才是能真正省下量的地方。 第三,如果你只有精力修一边,修内页。因为内页数量多、被抓的总次数远超首页,而且它们本来就快做到了,往往只差最后一步。 ## 这个对照也改变了整篇文章的结论 如果只跑首页那一轮,本文的结论会是“三成六,做得很差”。加上内页那一轮之后,结论变成了“首页三成六、内页六成五,问题集中在个性化最重的那一层”。 分母怎么选决定了结论的方向,流量下降不等于SEO失败的八维度实战 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)里有一套换分母的思路。 后一句比前一句有用得多,因为它指向了原因,也指向了动作。而这个差别,完全来自于多跑了一轮不同类型的地址。 这也是本次三篇实测里反复出现的一条方法:任何一个比例,都要问一句“这个分母是怎么选的”。换一个分母,同一批站的表现可以差出接近一倍。 ## 内页那一轮的另外两个发现 顺带记两个数。第一,内页的Last-Modified覆盖率反而更低,只有6.7%,比首页的12.7% 少一半。这说明动态生成的内容页更不知道该怎么填这个时间,索性不填。 内容页这一层往往比首页更容易做对,Shopify图片SEO从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)里的动作也是这样。 第二,内页里两次ETag不一致的只剩3个,而且成因跟首页那批不同——其中两个是整条格式都变了,属于节点不一致,不是页面里有随机值。换句话说,内页那一层几乎没有随机值污染的问题,剩下的都是基础设施问题。 这两条合起来给出的判断是:内页这一层,只要把比对逻辑补上,通过率很容易再往上抬一截。它的障碍是配置层面的,不是内容层面的。 ## 那个最后修改时间,填的到底是什么? ETag那边讲完了,回过头来看时间戳这条路。它出问题的方式完全不同,但同样隐蔽。 站点地图里那个更新时间理论上该和响应头里的是同一个值,免插件sitemap的动态优先级与分页策略 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)讲了那个字段怎么生成。 ## 两次请求,时间倒着走 本次抓到几个很有意思的样本。有一个站的首页,第一次请求返回的最后修改时间是当天下午两点多,第二次请求返回的却是当天上午十一点多——晚发的那次请求,拿到了一个更早的时间。 时间口径出问题会污染一整套数据,GA4默认追踪不到GEO流量的补法 (https://zhangwenbao.com/geo-ga4.html)是另一个时间维度的坑。 另一个站的内页更夸张,两次相差八个多小时,同样是往回退的。还有几个站的两次时间相差几秒到几十秒,方向是往前走的。 ## 两种成因 时间往回退,说明两次请求被不同的节点处理了,而这些节点各自持有不同版本的内容或者不同的时钟。这跟前面ETag格式变化那一类是同一个根因:基础设施不一致。 同一个现象要分清是内容问题还是基础设施问题,类目导航改版三轮之后仍然没写清楚用户在哪 (https://zhangwenbao.com/category-navigation-scope-custody.html)是模板层的例子。 时间往前走几秒,成因完全不同:这个站把Last-Modified写成了当前时间。也就是说,它每次响应都在说“这份内容刚刚才改过”。 后一种的后果是致命的:如果最后修改时间永远是现在,那么任何一个If-Modified-Since都不可能通过,因为客户端手上那个时间永远比“现在”早。这个站永远不会返回304,无论爬虫问多少次。 ## 怎么一眼看出自己有没有踩这个坑 方法只有一个,也很简单:请求你的页面,看返回的最后修改时间是不是接近当前时刻。如果是,那它写的是生成时间不是修改时间,这条路是断的。 一眼能看出来的自查最容易被坚持,结构化数据怎么配合SEO落地的完整指南 (https://zhangwenbao.com/seo-schema-guide.html)里也有几条这样的检查。 正确的值应该是内容真正被编辑的那个时刻——文章的最后更新时间、商品信息的最后变更时间。对静态文件来说就是文件的修改时间,服务器会自动填对;对动态页面来说,得你自己从数据里取。 顺带提醒一个容易被忽略的关联:这个时间跟站点地图里那个更新时间字段,理论上应该是同一个值。抓取预算那份文档里另有一条建议是保持站点地图更新并用好那个字段,两条建议其实指向同一份数据。 实际情况往往是两边各填各的:站点地图那边由某个插件按发布时间生成,响应头这边由服务器按文件时间生成,两个值对不上。对不上的后果是系统收到两个互相矛盾的信号,只能自己挑一个信。能对上的话,两条建议一次就都满足了。 这也是为什么动态站的Last-Modified覆盖率只有12.7%——大多数框架不知道该填什么,索性就不填了。不填至少是诚实的,填一个当前时间才是最坏的选择。 ## 动态页面该从哪取这个时间 取值的原则是:取这个页面所依赖的所有数据里,最晚被更新的那一个时刻。 商品页依赖的数据源比想象中多,电商产品评论的结构化与GEO联动 (https://zhangwenbao.com/ecommerce-product-reviews-seo-guide.html)列过其中几类。 对一篇文章页,就是文章记录的更新时间。对一个商品页,要考虑的更多:商品信息、价格、库存状态、评价数量,任何一项变了这个页面的内容就变了。取它们里面最晚的那个。 对一个分类页就更复杂:它依赖的是一批商品,其中任何一个变了都算。这时候要么取这一批里最晚的更新时间,要么干脆放弃这条路,只走ETag。 这里有个很实用的取舍:如果算这个时间的成本接近于渲染整个页面,那就别算了。这条建议的目的是省资源,为了省资源反而多花一倍计算,那就本末倒置了。 ## 一个折中办法 有个成本很低的中间方案,值得一提:给不同类型的页面定不同的粒度。 商品数据的粒度选择直接影响维护成本,跨境电商GTIN怎么申请与收录 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)里有类似的取舍。 文章、帮助文档、政策页这类内容,更新时间是现成的,直接用。商品页取商品记录的更新时间,忽略库存这类高频变动——代价是库存变了但时间没变,客户端可能拿到旧的库存显示;如果你的库存本来就是前端异步拉的,这个代价等于零。 分类页、搜索结果页这类聚合内容,干脆不给Last-Modified,只给ETag,或者两个都不给。不是每一类页面都值得为这件事花力气,挑那些量大又稳定的做就行。 ## 说了别缓存,又给了凭据 还有一档自相矛盾的配置值得单独说,因为它反映的是一种很典型的配置方式。 说一套做一套的地方最容易长期没人管,页脚不是杂物抽屉该怎么设计 (https://zhangwenbao.com/ecommerce-footer-design-trust-conversion.html)也是一个长期没人认领的区域。 ## 35个站里有6个前后不一致 142个站里,Cache-Control中写了no-store的有35个。no-store的含义非常强硬:任何缓存都不得存储这份内容的任何部分。 两层配置各说各的是很常见的故障形态,一键退订必须写两层少一层就限流 (https://zhangwenbao.com/one-click-unsubscribe-header-body-two-layers.html)是另一个双层不一致的例子。 可是这35个站里有6个,同时还给出了ETag或者Last-Modified。一边说别存,一边给一张用来判断存着的那份还能不能用的凭据。这两句话在逻辑上是互斥的。 ## 这种矛盾是怎么来的 几乎可以肯定不是有人这么设计的,而是两层配置叠加的结果:应用层出于安全考虑加了no-store,而Web服务器或者CDN那一层默认会给静态化的响应自动生成ETag。两边各自都对,合起来就矛盾了。 每一层单独看都对,合起来才出事,AI内容披露里那份不做什么的清单 (https://zhangwenbao.com/ai-usage-disclosure-negative-list.html)也强调了整体核对。 这类问题在多层架构里非常常见,而且往往没人发现,因为每一层单独看都符合自己的规范。只有把最终那个响应头完整打印出来通读一遍,矛盾才会显形。 ## 矛盾的实际后果是什么 说实话,后果不算严重。规范里no-store的优先级更高,合规的客户端会遵守它,那张凭据只是被忽略了而已。 矛盾信号会让系统对你整体降低把握,实体SEO的五阶段构建方法 (https://zhangwenbao.com/entity-seo-guide.html)解释了这套信心机制。 但它有两个间接代价。第一,生成ETag是有成本的——服务端算了一遍哈希,而这个哈希不会被任何人用到。纯浪费,虽然不多。第二,也是更重要的:这个矛盾是一个信号,说明这个站的响应头是几层配置叠出来的,没人通读过最终结果。 而没人通读过最终结果,通常意味着别的地方也有类似的问题——多余的头、互相冲突的指令、过期的策略。这跟上一篇里那个把sizes当探针用的思路是一样的:找那些错了也没人管的地方,它们最诚实。 ## 怎么快速看一眼自己的响应头 方法很土:从公网请求一次你的页面,把完整的响应头打印出来,从头到尾读一遍。不是查某一个字段,是通读。 通读比单查更容易发现叠加出来的矛盾,robots.txt的虚拟与物理优先级怎么排 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)也是一个多层叠加的例子。 通读的时候问三个问题:有没有互相矛盾的两条、有没有明显是某一层自动加上而你并不需要的、有没有该有却没有的。本次实测里的绝大多数问题,都能在这三个问题下暴露出来。 这件事一年做一次就够,前提是这一年里没换过基础设施。它的价值不在于每次都能查出问题,而在于它是唯一能看到多层叠加最终结果的方法。 ## 顺带一个更普遍的数字 142个站里,有70个压根没有Cache-Control这个响应头。接近一半。 默认状态往往就是最终状态,自建站谷歌SEO开发期的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)里列了要主动设定的项。 没有这个头不等于不能缓存,规范里有一套默认的启发式规则,但那意味着缓存行为由各个客户端自己猜。对一个电商站来说,把缓存策略交给别人猜,不是一个好的默认状态。 ## 各条指令的实际使用分布 把142个站的Cache-Control拆成一个个指令统计,出现频次最高的几个依次是:带具体秒数的最大存活时长、必须重新验证、不要直接使用缓存副本、不要存储、公开可缓存、私有。 保守策略在结账链路上尤其常见,结账流程改了很多轮用户回头改一次地址就全丢 (https://zhangwenbao.com/checkout-rework-path-vs-first-fill.html)是同一种谨慎的代价。 值得注意的是不要直接使用缓存副本和不要存储这两条加起来的覆盖面相当大,说明相当一批电商站在首页这一层选择了保守策略。这可以理解——首页往往带着购物车状态和个性化推荐,存错一份就是事故。 但保守策略也有分寸。不要直接使用缓存副本这一条,意思是每次使用前都要向服务端确认一遍,它恰恰是最需要条件请求配合的一档:既然每次都要确认,那就该给一张能用来确认的凭据。而本次数据里,这一档里也有相当一部分什么凭据都没给。 ## 这两条指令经常被混用 顺带澄清一个高频误解:不要存储和不要直接使用缓存副本,字面看着像,含义差得很远。 相似的配置项含义差很远,付款回来购物车就空了那两分钟宽限 (https://zhangwenbao.com/samesite-cookie-payment-return-session-loss.html)也是一次配置含义的误解。 前者是彻底禁止任何环节留存这份内容,用于真正敏感的页面。后者允许留存,只是每次用之前必须向服务端确认一次。后者是条件请求最理想的搭档,前者则是把这条路完全关掉。 很多站把这两条一起写上,有时候还加上一个最大存活时长为零。这样写不算错,但它表达的是最保守的那一档,也就是不要存储那一档。如果你的本意只是想每次确认一下,那就别写不要存储,你把自己的路堵死了。 ## 爬虫换一种方法问,你的站答得上来吗? 条件请求之外,还有一层很少被提起的东西:Google的爬虫并不只发普通的取内容请求。 换一种方法问答案可能完全不同,AI推荐机制与GEO实战策略 (https://zhangwenbao.com/ai-recommendation-reddit-wikipedia-geo-strategy.html)里那组对照也是靠换问法问出来的。 ## 官方确认过的方法清单 Google的工程师提到过,他们的爬虫会发出多种HTTP方法的请求,除了最常见的取内容之外,还包括只要响应头不要内容的那种、询问一个地址支持哪些方法的那种,甚至还有写入类的方法。这份方法清单的完整讨论 (https://www.seroundtable.com/google-crawlers-head-options-put-patch-delete-41833.html)当时引起过不少关注,因为大多数人从没想过爬虫会发这些。 爬虫的种类和行为都在变,Google-Agent是什么以及怎么识别和应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是另一条值得跟的变化。 既然爬虫会发,那就值得测一测你的站答不答得上来。 ## 只要响应头的那种请求 对142个站各发一次,123个返回200,占86.6%。但其中94个没有返回内容长度。 这就有点尴尬了。这类请求的全部意义就在于用极小的代价拿到关于这份内容的元信息,而内容长度恰恰是最有价值的那一项——不给长度,等于把这种请求的主要收益去掉了一大半。 没返回200的那19个里,情况五花八门:有跳转的、有直接连不上的、有返回未找到的、还有两个返回了一个表示“继续等待”的中间状态码。同一个地址,用普通方式请求好好的,换一种方式就出岔子。 其中最值得注意的是那个返回未找到的站:用普通方式请求首页返回200,用只要响应头的方式请求同一个地址返回未找到。两种方式按规范应该返回完全相同的头,包括状态码。返回不同的状态码,说明这两条路径走的不是同一套逻辑。 还有几个返回跳转的,情况类似——普通请求直接给内容,换个方法就先跳一次。这类不一致对爬虫的影响是:它拿到的元信息可能跟真实内容对不上,于是它只能放弃这条省事的路,改回全量请求。 ## 为什么不给内容长度是个问题 94个站不给内容长度,这件事需要辩护一句:如果响应是分块传输的,规范上确实可以不给这个头,这在动态生成的页面上很常见,不算违规。 知道内容多大是很多抓取决策的前提,让内容被主动引用的五个维度 (https://zhangwenbao.com/ai-search-content-writing-machine-readable-playbook.html)里也强调过让机器省力这件事。 但站在使用者的角度,结果是一样的:你发这个请求,本来是想用最小代价知道这份内容有多大、什么时候改的、标识符是什么;拿回来一个没有大小的响应头,收益就少了一块。 要不要为此专门改造,取决于你的场景。对绝大多数电商站来说,这一项优先级很低。本文把它量出来,主要是给“爬虫会发多种方法”这个说法配一个真实的分布,而不是让你去改配置。 ## 询问支持哪些方法的那种请求 这一项的结果最难看。142个站的返回分布是:找不到的57个、跳转的41个、方法不允许的9个、正常返回的6个,剩下是各种其它状态。 量出真实分布比照着传言改配置有用,文章标题怎么写才有人点的十个技巧 (https://zhangwenbao.com/how-to-write-catchy-article-titles.html)里那些公式也都配了实际数据。 而按规范应该在响应里列出支持方法清单的,只有5个站。这5个给出的清单也都很朴素,基本就是取内容和取响应头两种,个别加了提交表单那一种。 这一项要不要修,答案是通常不用。它对SEO几乎没有直接影响,本文把它量出来,是为了给“爬虫会发多种方法”这个说法配一个真实的分布。知道你的站在这一项上是什么表现,比盲目照着传言去改配置有用。 不过有一个细节值得留意:返回“方法不允许”的那9个站,其实是最规范的一档。它明确告诉对方“这个方法我不支持”,而不是含糊地返回一个找不到或者跳走。规范上,返回这个状态码的时候还应该附上支持的方法清单,而那5个给出清单的站基本都属于这一档。 ## 那些写入类的方法要不要管 官方提到的方法清单里还包括几个写入类的方法。这一项本次没有测,理由很直白:对别人的站发写入类请求是一件不合适的事,哪怕只是探测。 不需要的方法就明确拒绝,这是基本的安全卫生,品牌被仿冒抢排名的五步应对实战 (https://zhangwenbao.com/brand-domain-impostor-seo-nanoclaw-protection.html)里也有一批同样属于卫生级别的动作。 但可以给一条常识性的建议:如果你的站不需要接受这类请求,就在服务器或者网关层明确拒绝它们。这不是为了SEO,是基本的安全卫生——一个默认接受各种方法的服务端,暴露面比必要的大。 拒绝的时候记得返回“方法不允许”并附上支持的方法清单,而不是静默丢弃或者返回一个假的成功。诚实的拒绝比含糊的沉默好,这一条在本文里已经出现第三次了。 ## 按服务器类型看这三关的通过率 把142个站按响应头里的服务器标识分组,条件请求的通过率差异非常明显:有几类现代托管平台的通过率在八成以上,有一类知名的加速服务通过率不到四成,还有一类是零。 托管选择带来的连带影响比想象中多,外贸独立站用国内主机还是国外主机 (https://zhangwenbao.com/china-vs-overseas-hosting-for-cross-border-independent-site.html)里有一份对比。 这个差异说明一件事:你的通过率很大程度上不是你决定的,是你选的那套基础设施的默认行为决定的。好消息是,这也意味着修起来往往就是一个开关;坏消息是,如果你的服务商默认不做,你多半根本不知道。 ## 基础设施决定默认值这件事的普遍性 这已经是这三篇实测里第三次撞到同一个现象了。上一篇量图标的时候,兜底路径能不能取到图,几乎完全由“是传统服务器直接托管静态文件还是前端框架接管路由”决定;再上一篇量名字的时候,多店铺场景下名字会不会分叉,由平台的店铺配置结构决定。 不同主机档位的默认行为差别很大,共享主机VPS还是独享该怎么算这笔速度账 (https://zhangwenbao.com/wordpress-foreign-trade-hosting-tier-shared-vps-dedicated-cloud-seo.html)逐档比过。 这三件事的共同点是:团队从来没做过决定,最终结果是服务商替他们做的。而服务商的默认值是按通用场景定的,不是按你的场景定的。 这条观察有一个很实用的推论:当你接手一个新站、想快速判断它的技术底子的时候,与其看它做了什么,不如看它的默认值有没有被动过。有人调整过默认值,说明有人真的看过这一层;一切都是出厂设置,说明这一层从来没进过任何人的视野。 ## 换服务商的时候尤其要重测 顺着这条往下推:既然通过率主要由基础设施决定,那么任何一次基础设施变更,都可能悄无声息地把这件事改掉。 迁移之后要重验的项目比清单上写的多,换域名之后后台跳转登不上的三种改法 (https://zhangwenbao.com/wordpress-change-domain-access-management-login-jump-solution.html)记录过一次迁移事故。 换CDN、换托管平台、在前面加一层防护、把静态资源迁到对象存储——这些动作的验收清单里,通常只有“页面能打开吗、速度快不快、证书对不对”。没人会去发一次条件请求。 建议是把这一条加进迁移检查表,成本是两次请求。它跟前两篇加的那两条检查项一样,都属于“加一行、几十秒、可能省掉几年的静默损耗”那一类。 ## 三条检查项凑成一份迁移清单 这个系列做下来,正好攒了三条可以直接加进迁移检查表的项目,都属于工具查不到、出问题不报警、修起来很便宜那一类。 清单化是对抗没人认领的唯一办法,论坛和问答结构化数据怎么做 (https://zhangwenbao.com/google-forum-qa-structured-data-ai-bot-label.html)里那套字段同样需要一份清单去维护。 检查项 | 怎么查 | 坏了会怎样 | 组织名与站点名一致 | 抠出结构化数据与og标签比对 | 系统改用域名顶替 | 图标地址可用 | 逐个请求并读文件头 | 展示位上一个灰方块 | 条件请求能回304 | 带凭据重发一次 | 持续重复传输,无人通知 | 三条加起来五分钟,覆盖的是三类完全不同的失败。共同点是它们都不会让页面显示出问题,所以标准的上线验收永远抓不到。 把它们写进迁移和发版清单,是这个系列最实际的产出。不是因为这三件事本身多重要,而是因为清单是唯一能对抗“没人认领”的机制。一件事只要没被写进任何一份清单,它就只能靠某个人碰巧想起来,而人是会离职的。 这三条也可以直接给外包团队或者服务商用。它们的判据完全客观,不需要解释上下文,验收的时候一看就知道过没过。这类可验收的条目,比一堆写着“优化性能”“完善结构化数据”的模糊要求管用得多。 保哥这些年给客户写技术需求,越来越倾向于这种写法:每一条都能在五分钟内被独立验证,而且验证方式写在需求里。做不到这一点的条目,最后八成会变成一场关于“到底算不算做完了”的扯皮。 这三条恰好都符合。第一条比对几个字段是否相同,第二条看几个地址返回的是不是图片,第三条看带凭据重发回不回304。没有一条需要解释、需要判断、需要讨论。 ## 自检和修复一共几步? 亲自型规则的落地方式很直接:没人会告诉你结果,所以你得自己建立一次观测。 把动作写成可照做的顺序比讲道理有用,PAS公式在SEO内容写作中的进阶用法 (https://zhangwenbao.com/pas-formula-seo-content-writing-advanced-applications.html)也是同一种编排思路。 ## 三分钟的自检 第一步,请求你的一个典型内页,把完整响应头打印出来,看有没有ETag或者Last-Modified。一个都没有,这条路就是断的,跳到修复第一步。 自检之后要不要上工具,二十款GEO与AEO监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)可以按预算挑。 第二步,再请求一次同一个地址,把两次的凭据并排比。不一样的话,看是长度段变了还是只有哈希段变了——只有哈希段变,说明页面里有定长随机值;整条格式都变,说明你的节点配置不一致。 第三步,带上第一步拿到的凭据重发一次,看返回的是不是304。是就通过了,不是就说明服务端没有做比对逻辑。 第四步,看Last-Modified的值是不是接近当前时刻。是的话,说明它写的是生成时间,这条路等于没有。 这四步全部只需要一个能发请求并打印响应头的工具,不需要登录服务器、不需要看代码、不需要任何权限。你甚至可以拿它去测竞争对手的站——本次这批数据就是这么来的。 ## 测竞争对手这件事顺带说两句 这套方法最有意思的一点是它完全对外可用。你能测自己的站,就能测同行的站,而且拿到的是同样精度的数据。 同行对标要挑能从外部测准的指标,品牌权威度与域名权重的区别和提升方法 (https://zhangwenbao.com/moz-ba-brand-authority-seo.html)讨论过这类指标的可得性。 这在SEO里不常见。绝大多数技术指标要么需要后台权限,要么只能看到很粗的外部近似值。而条件请求这件事,从外面看到的和从里面看到的是同一份事实。 实用价值在哪?如果你要说服团队做这件事,一份“同行里有多少家做到了、我们排在哪一档”的数据,比任何理论都好使。本次那52个做到的站里,有不少是各自品类里的头部品牌,这个名单本身就是论据。 ## 顺带能测出来的其它东西 同样是这几次请求,还能顺带看到不少别的信息:对方用的是哪套加速服务、页面的真实体积有多大、缓存策略保守还是激进、有没有节点不一致的迹象。 同行数据是说服团队最省力的论据,SEO汇报怎么让不同部门看到同一份事实 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)里有现成的表达方式。 这些信息在做技术选型的时候相当有参考价值。比如你在几个托管平台之间犹豫,与其看它们的宣传页,不如去测几个跑在上面的真实站点,看默认行为长什么样。本次数据里不同服务商之间的通过率差异,从零到百分之百都有。 当然要克制。几次请求是正常访问,成千上万次就是另一回事了。做同行对标的时候,挑十几个代表性的站、每个站测一遍,足够得出结论了。 ## 这套自检有一个前提 一定要从公网发这几次请求,不要在内网或者本机测。原因是你的响应头是好几层叠出来的:应用层、Web服务器层、加速服务层,每一层都可能加东西、改东西、删东西。 观测点放在哪决定了你看到什么,用正则从GSC里挖AI搜索提问的五步实战 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)也是换了观测点才挖出东西。 从内网测,你看到的是某一层的输出;从公网测,你看到的才是爬虫真正收到的那份。本次那6个自相矛盾的配置,全部只有在最终响应里才看得出来——单看应用层,它写的是不要存储,完全正确;单看服务器层,它自动生成了凭据,也完全正确。 这条原则可以扩展到所有的技术SEO排查:凡是要判断“搜索引擎看到了什么”,观测点就必须放在跟它一样的位置上。这也是本文所有数据都从公网单点发起的原因。 ## 四种失败对应四种修法 自检发现 | 根因 | 修法 | 难度 | 一个凭据都没有 | 服务器或框架没开 | 开启自动生成ETag | 通常是一个开关 | 凭据每次都变、只有哈希段变 | 页面里有定长随机值 | 把随机值移出被哈希的部分 | 要改模板 | 凭据格式都变 | 节点配置漂移 | 统一部署配置 | 要查运维 | 有凭据但不回304 | 没做比对逻辑 | 在应用或网关层加比对 | 视架构而定 | 最后修改时间是当前时刻 | 填成了生成时间 | 改成内容真实变更时间 | 要能取到那个时间 | 把问题分类再排期,比一股脑全改高效,新网站SEO目标管理的三个里程碑 (https://zhangwenbao.com/new-website-seo-goal-management.html)有拆解方法。 ## 每一类的实际改动长什么样 把四种修法再落细一点,免得看完还是不知道该跟谁说什么。 配置层的一个开关有时候比一堆内容动作更管用,GitHub Pages寄生SEO的借力实战 (https://zhangwenbao.com/github-pages-seo-parasite-seo-strategy.html)也是靠现成能力省力气。 没有凭据这一类,去看你的Web服务器或者加速服务的配置文档,搜“实体标签”或者“自动生成校验”,绝大多数都有一个开关。开完之后立刻发一次请求确认响应头里真的多了那一行——有些服务只对静态资源生效,对动态响应不生效,光看配置看不出来。 凭据不稳这一类,先按前面那套读法判断是哪一种形状。如果是长度段不变哈希段变,去页面里找定长随机串;如果是整条格式都变,那是运维的活,跟部署一致性有关,跟页面没关系。 有凭据但不回304这一类,通常是在应用层或者网关层加一段比对:拿到请求里的条件头,跟当前算出来的凭据比,相同就返回304和一个空响应体。记得304响应里要带上凭据本身,否则客户端下一轮就不知道拿什么来问了。 时间戳填错这一类,得先确认你能不能取到内容的真实更新时间。取得到就换上;取不到,宁可不给这个头,也别给一个当前时间。这是唯一一个“不做比做错更好”的选项。 ## 先修哪一类 按性价比排:先修“有凭据但不回304”那一类,因为它离终点最近,往往就差一段比对逻辑。再修“一个凭据都没有”那一类,因为它多半是个开关。最后才是“凭据不稳”,因为它要动页面内容,牵扯最多。 先修离终点最近的那一档,用Performance Max给零流量商品再来一次机会 (https://zhangwenbao.com/zombie-sku-revival-performance-max.html)也是同样的优先级逻辑。 如果你的站声明了no-store且确实需要,那这套机制对首页就不适用,直接跳过,把力气放在内页上。本次数据已经说明,内页本来就是这条建议真正能省下量的地方。 ## 修完之后怎么验收 验收方式跟自检完全一样,只是多一步:不只验你改的那个页面,验每一类页面各一个。商品页、分类页、文章页、帮助页,各挑一个跑一遍。 验收要覆盖每一类对象,五大策略让AI搜索主动推荐品牌 (https://zhangwenbao.com/geo-strategies-ai-brand-recommendation.html)里的落地检查也是分类做的。 为什么要分类型?因为这几类页面的数据来源、缓存策略、渲染路径往往完全不同,改好了商品页不代表分类页也好了。本次实测里首页和内页差1.8倍,就是最直接的证据。 还有一件事要验:改完之后确认内容真的变了的时候会返回200。只验304不验200,有可能改出一个永远返回304的实现,那比不做还糟——用户和爬虫都会一直看到旧内容。这个验法很简单:改一下页面内容,立刻再请求一次,看是不是200。 ## 把它挂进哪个流程 建议挂进两个地方。一个是发布流程,每次发版之后跑一遍,成本是几秒钟。这条最重要,因为本次实测里那些节点配置不一致的问题,几乎肯定是某次发布带出来的。 把检查挂进既有流程比新建流程容易,大促与日常SEO的八维度差异与时间轴 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)里有排期的做法。 另一个是基础设施变更流程:换CDN、加防护层、迁移托管平台的时候各跑一遍。这一条的必要性前面已经说过了——通过率主要由基础设施的默认行为决定,而默认行为会随着你换服务商而整个改变。 不建议挂成定时监控。这件事的状态很稳定,除非有人动了配置,否则它不会自己变;为一件不会自己变的事建一个每天跑的监控,只会制造噪声。 ## 三个反直觉的判断 第一,做得最差的一关不是完全没做的那一关。四成的站没凭据,这不奇怪;奇怪的是有凭据的77个站里还有25个不认自己发的凭据——它们付出了成本却没拿到收益。 反直觉的结论往往藏在没人量的地方,被低估的九个反直觉UI设计杠杆 (https://zhangwenbao.com/counterintuitive-ui-design-conversion-levers.html)是另一组同类观察。 第二,更精确的机制在真实环境里成功率更低。ETag比时间戳精确得多,实测成功率却低了十五个百分点,因为精确意味着更容易被一段随机字符串毁掉。 第三,这一整篇文章讲的所有问题,没有一个会触发任何报警。没有报错、没有报表、没有邮件,页面在浏览器里一切正常。这正是亲自型规则的定义——它把发现问题的责任,完整地留给了你。 ## 三篇合起来的那条线 这是这个系列的第三篇,也是最后一篇。三篇量的是同一批国际化电商站的三样东西:名字、图标、以及服务器怎么回答“变了没有”。 平台介入方式的差别在专利文本里也有痕迹,从专利与专家访谈还原的GEO五步原理 (https://zhangwenbao.com/google-microsoft-patents-geo-guide.html)提供了另一个角度。 | 禁止型 | 代劳型 | 亲自型 | 本系列的样本 | 组织名与站点名 | 图标与站点名称的选取 | 条件请求与304 | 官方措辞 | 不被允许、可能导致 | 偏好、支持、会考虑 | 我们建议、请支持 | 核心动作 | 删掉多余的 | 把候选收敛到一个 | 自己实现并自测 | 什么时候停 | 过线就停 | 候选剩一个就停 | 不该停 | 怎么发现失败 | 收到处罚通知 | 看展示结果 | 只能自己去问一次 | 本次实测的通过率 | 17个域名有附加成分 | 四来源一致只有22.4% | 首页36.6%、内页65.2% | 三格的中枢是同一句话:平台给你的每一条规则背后,都藏着一个没写出来的主语——这件事到底谁动手。认错主语的代价,是把力气花在别人已经替你做完的地方,或者在别人明令禁止的地方反复试探。 ## 如果只能记住一件事 记住那个判据:有没有一个官方工具会告诉你做到了没有。 有没有官方反馈,是判断该投多少力气的关键,Schema对AI搜索到底有没有用的官方说法与实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)也是按这个判据取舍的。 有,说明平台在意这个结果,也愿意给你反馈,那就照着它的反馈做。没有,那这件事就完全是你自己的,而且很可能已经坏了很久,没有任何人打算通知你。 平台管得越松的地方,越是没人替你兜底的地方。这句话是这三篇文章唯一想说的东西。 ## 最后留一句给做技术SEO的人 这三篇量的东西——名字、图标、条件请求——有一个共同的尴尬:它们都不在任何一份标准的SEO检查清单里。 工具查不到的清单值得自己建一份,答案引擎优化怎么让内容被优先引用 (https://zhangwenbao.com/aeo-answer-engine-optimization-guide.html)里也有一批标准工具不会检查的动作。 市面上那些站点体检工具,会查标题长度、会查图片替代文本、会查内链结构、会查页面速度。没有一个会告诉你“你的服务器不认自己发的凭据”,也没有一个会告诉你“你的组织名在德国站上多了一个后缀”。 原因不难猜:工具查的是有标准答案的东西,而这三件事各有各的上下文,没法用一条通用规则判定。但没工具查,不等于没有影响;恰恰相反,正因为没人查,这些地方才会一坏好几年。 保哥的建议是给自己建一份“工具查不到的清单”,把这类东西放进去,跟着发版流程走一遍。它不会带来立竿见影的排名变化,但它是那种做完之后你不用再担心的事——而这类事情在技术SEO里,其实是最稀缺的。 这三篇量下来,最有价值的可能不是那几个百分比,而是一个很朴素的习惯:凡是官方文档里出现“我们建议”而没有配套检查工具的地方,都值得你亲自去发一次请求确认一遍。 这样的地方不多,一只手数得过来。但每一个都符合同样的特征:便宜、没风险、没人查、可能已经坏了很久。把它们一次性过完,然后写进清单,这件事的收益会一直持续到有人把清单删掉为止。 ## 这套自检值多少钱 算一笔粗账。四步自检,加起来三分钟。修复的时间差别很大:开个开关是五分钟,补一段比对逻辑是半天到一天,把随机值移出被哈希的部分可能要动模板、需要测试。 便宜且没有反向风险的动作该优先做,把旧内容更新成AI可信来源的十二步 (https://zhangwenbao.com/revise-old-content-for-aeo-ai-search-optimization.html)里有一批同类动作。 收益按前面那个口径算:假设你有十万个页面被规律抓取,平均每页300 KB,其中八成的抓取碰到的是没变过的内容。做到之后,这八成的传输量归零。具体省下多少钱要看你的带宽单价,但这是一笔按月复利的账,不是一次性的。 更重要的是它的下限:做这件事几乎没有风险。它不影响用户看到的内容、不影响收录、不影响排名,最坏的情况是白做一遍。这跟很多SEO动作不一样,那些动作往往有反向风险。 唯一需要留神的反向风险是前面提过的那一条:改出一个永远返回304的实现。那样内容更新之后爬虫和客户端会一直拿到旧版本,后果比不做严重得多。所以验收的时候一定要两头都验——没变的时候回304,变了的时候回200。 这个风险的概率不高,但值得写出来,因为它是本文唯一一个“做错了比不做更糟”的地方。其余所有情况,最坏结果都只是白做一遍。 ## 跟别的抓取预算动作比,它排第几 抓取预算那份文档里九条建议,如果按性价比排个序,这一条大概在中间偏上。 排序取决于你手上有什么资源,八家龙头怎么抢AI流量的打法拆解 (https://zhangwenbao.com/geo-concept-ai-traffic-2000billion-leaders.html)里也是按各自的资源禀赋排的动作顺序。 比它优先的是那几条“别让爬虫抓不该抓的东西”——合并重复内容、屏蔽无意义的参数组合、给删掉的页面返回正确状态码。那几条省的是抓取次数,这一条省的是每次抓取的字节,前者的杠杆通常更大。 但这一条有个别的建议没有的优点:它是一次性的、配置层的、不需要任何内容决策。合并重复内容要跟运营和内容团队讨论,屏蔽参数要理清业务逻辑,而支持条件请求只需要改一处技术配置。 所以合理的排法是:如果你的技术资源比内容资源宽裕,先做这一条;反过来就先做那几条。两边都做当然最好,但排序取决于你手上有什么人。 ## 什么情况下可以直接跳过 三种情况可以放心跳过。第一,你的站页面数很少、被抓的总量本来就不大,那这笔账省不出什么。第二,你的内容确实每次都在变——比如一个实时报价页,那这套机制本来就用不上。第三,你的页面已经很小,几十KB那种,省下来的绝对量有限。 知道自己现在是什么状态本身就有价值,AI搜索时代内容优化的底层逻辑五步 (https://zhangwenbao.com/context-first-seo-ai-search-strategy.html)里第一步也是先摸清现状。 但即便是这三种情况,花三分钟测一次也不亏,因为你至少会知道自己现在是什么状态。本次实测里最让人意外的不是做不到的比例,是那些做了一半的站——它们付出了成本却没拿到收益,而且完全不知道。 ## 常见问题解答 ## 支持304会不会让用户看到旧内容? 不会。内容有没有变是服务端判断的,变了就返回200和新内容,一秒钟都不会延迟。304只在内容确实没变的时候返回。真正决定“客户端会不会隔一段时间才来问”的是Cache-Control这类缓存策略,那是另一件事。这两件事经常被混为一谈,分清楚之后就会发现支持条件请求几乎没有风险。 ## 我的站不大,值得做这个吗? 收益跟规模成正比,小站省不了多少带宽。但成本也几乎是零——大多数服务器和CDN只要开一个开关。判断标准可以是:如果你的服务器成本里带宽占比不低,或者页面平均体积偏大,那就值得。本次样本里首页平均707KB,这个体积下重复传输的浪费是相当可观的。就算你判断不值得做,也建议花三分钟测一次,至少知道自己现在是什么状态。 ## 返回304的时候,响应头还要带哪些字段? 规范要求304响应里带上那些如果返回200时也会发送、且可能影响缓存判断的头,典型的是ETag、Cache-Control、Vary这几项。不需要带内容长度,因为响应体是空的。实践中最容易出错的是漏了ETag——客户端拿到一个不带ETag的304,下一次就不知道该拿什么去问了,于是又回到全量请求。 ## 页面里有CSRF令牌,还能支持ETag吗? 能,但要处理一下。问题的本质是这个令牌每次都不同,导致内容的哈希每次都变。有三种处理方式:把令牌从页面里挪出去,改成前端异步获取;计算哈希的时候把令牌那一段排除掉;或者干脆不用ETag,改用Last-Modified,因为时间戳对这种字节级变动不敏感。本次实测里有五个站的ETag长度段完全不变、只有哈希段在变,几乎可以断定就是这类原因。 ## 怎么判断我的ETag是渲染前算的还是渲染后算的? 从外部很难直接看出来,但有个间接的信号:观察返回304时的响应时间。如果304的响应明显比200快很多,说明服务端在返回304之前没有走完整的渲染;如果两者差不多,说明它渲染完了才发现可以返回304,那样只省了传输没省计算。后者也不算白做,因为带宽通常仍然是大头。 ## ETag和Last-Modified该给哪个,还是都给? 能都给就都给,客户端会自己挑。如果只能给一个,看你的内容性质:内容会字节级变动但语义不变的(比如页面里有随机令牌),给Last-Modified更稳;内容变更时间不容易取到的,给ETag更实际。本次实测里Last-Modified的成功率反而更高,正是因为它对字节级变动不敏感。 ## 为什么我的ETag每次请求都不一样? 最常见的原因是页面里有长度固定、内容随机的字符串,比如防跨站请求的令牌、脚本策略里的一次性随机数、请求追踪编号。判断方法很简单:连发两次请求,如果两次ETag的长度段完全相同、只有哈希段不同,那基本可以确定是这个原因。另一种可能是两次请求被不同配置的节点处理了,这种情况下连ETag的格式和长度都会变。 ## Search Console里能看到这一项吗? 看不到。这正是这类规则的特点:它完全发生在你的服务器上,平台只能建议,没有提供任何检查工具。抓取统计报告里能看到抓取请求的总数和响应大小的趋势,但它不会告诉你有多少次本来可以是304。唯一的检查手段是自己发一次条件请求。 ## 用了CDN,这件事还归我管吗? 归。CDN的默认行为差异非常大,本次实测里不同服务商之间的通过率从零到百分之百都有。而且CDN那一层的配置和你的源站配置会叠加,可能出现源站说别缓存、CDN却自动生成凭据这类矛盾。正确的做法是从公网发一次请求,看最终那个响应头长什么样,而不是看某一层的配置。 ## 拿首页测出来的结果可信吗? 不可信,而且会系统性低估。本次实测里,同一批站的首页只有36.6%能回304,内页有65.2%,差1.8倍。首页是全站个性化程度最高的一页,推荐位、促销条、购物车数量、会话令牌都在上面,这些都会让每次输出的字节不同。测的时候两边都要测,修的时候优先修内页。 ## 最后修改时间该填什么值? 填内容真正被编辑的那个时刻:文章的最后更新时间、商品信息的最后变更时间。最坏的做法是填当前时间——那样每次响应都在说这份内容刚刚改过,任何条件请求都不可能通过。自查方法是请求一次看返回的时间是不是接近当前时刻,是的话就说明填错了。取不到真实变更时间的话,宁可不填。 ## 爬虫真的会发那些不常见的请求方法吗? 官方确认过会发多种方法,包括只要响应头的那种和询问支持哪些方法的那种。本次实测的分布是:只要响应头那种有86.6%的站正常返回,但其中大部分不给内容长度;询问支持方法那种,按规范应该列出方法清单的只有5个站。这一项通常不需要专门去修,量出来是为了给那个说法配一个真实的分布。 ## 声明了no-store的站怎么办? 如果确实需要no-store,那首页这一层就不适用这套机制,直接跳过。但要注意别出现自相矛盾的配置:本次142个站里35个写了no-store,其中6个同时还给了凭据,那是两层配置叠加的结果,每一层单独看都对,合起来就矛盾了。另外,no-store通常只该用在真正含个人信息的页面上,别把它套在整站上。 ## 权威参考资料 ## AI爬虫读不到你的正文?132个独立站首页有28个是空壳 - URL:https://zhangwenbao.com/html-shell-page-readable-text-audit.html - 分类:技术SEO - 发布:2026-08-14 | 更新:2026-08-14 - 摘要:满屏商品的首页,抓下来剥掉标签一个字都没有。这28个站不是不管机器,它们写了标题、写了描述、放了结构化数据,只是没留正文。 - 关键词:技术SEO,AI爬虫,独立站建站,网页无障碍 > **TLDR**:摘要:用一台普通服务器,把211个国际化独立站的首页各抓了一次,拿到132份能分析的HTML。里面有28份的正文可读字符不到1200个,其中14份是整整0个字符。最夸张的一份传了5146465字节,一个字都读不出来。这些页面并不是不管机器——93%写了标题,82%写了描述,57%放了结构化数据,只有1个站在noscript里留了正文。它们知道机器会来,只是没给机器留内容。文章后半段把无障碍树这一层也量了一遍,并记下一次尺子失效:把空壳页混进样本,无地标区域的比例会从3.6%虚高到22.9%。 > 摘要:用一台普通服务器,把211个国际化独立站的首页各抓了一次,拿到132份能分析的HTML。里面有28份的正文可读字符不到1200个,其中14份是整整0个字符。最夸张的一份传了5146465字节,一个字都读不出来。这些页面并不是不管机器——93%写了标题,82%写了描述,57%放了结构化数据,只有1个站在noscript里留了正文。它们知道机器会来,只是没给机器留内容。文章后半段把无障碍树这一层也量了一遍,并记下一次尺子失效:把空壳页混进样本,无地标区域的比例会从3.6%虚高到22.9%。 先说一件反直觉的事。你打开一个独立站首页,满屏商品、导购文案、促销标语,看着热闹得很。同一个地址,我用命令行抓一次,得到2109539字节的HTML。把标签、脚本、样式全部剥掉,剩下的可读文字是:零。 不是少,是零。2兆的字节,一个字都没有。 这个站不是什么小作坊,是一个消费电子大牌。它的首页在浏览器里工作得很好,因为浏览器会执行那几十个脚本,然后把内容画出来。问题是,来读这个页面的不只有浏览器。 2026年8月,行业里有两条新闻在同一周出现,看着毫不相干。一条是内容分发网络的爬虫开关被一键关掉 (https://www.seroundtable.com/misconfigure-cloudflare-seo-41865.html),两周流量归零;另一条是一篇讲无障碍树的技术文章,说AI代理读网页读的不是你的视觉设计,而是浏览器构建的那棵语义树。保哥把这两条并排放了几天,发现它们说的其实是同一件事的两个方向:你以为你发布了内容,其实你只是发布了一份让浏览器去生成内容的说明书。 说明书这个比喻可以再往下走一步。你把说明书交给一个会照着做的人,他能做出一桌菜;交给一个只会念字的人,他念完只知道有这么一份说明书。这两个人拿到的是同一份东西,得到的结果差着一整桌菜。 过去十年,来读你页面的基本都是"会照着做"的那种。这两年名单变了,而且新加进来的那批,大多数只会念字。 这篇文章只干一件事:把"东西到底在不在"这个问题,从感觉变成可以数出来的数字。前面是211个站的实测明细,中间是无障碍树这一层的量法,后面是一次尺子失效的完整复盘——同一批数据,混进错误样本之后,某个结论虚高了6.4倍,另一个虚高了11倍。 需要先说明一句:这套测量只看服务端交付的那一份字节,不看渲染之后的结果。所以下面所有"没有"的准确含义都是"在交付的那一刻没有"。这个边界很重要,文中会反复提到它。 ## 抓下来的字节里,到底有多少字 先把测量方法交代清楚,因为这篇文章所有结论的可信度都挂在这一段上。方法说不明白,后面那些百分比就只是一堆漂亮的数字。 有些地址连head都没有,接口和feed拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)是相邻的盲区。 ## 测量口径怎么定的 样本是211个国际化独立站的域名,覆盖服饰、家居、消费电子、美妆、户外、母婴几个大类,绝大多数是有独立品牌、面向多国市场的品牌自营站。这批域名不是随机抓的,是按"有多语言版本、有独立品牌、体量在中大以上"三个条件筛出来的,所以它们代表的是行业里做得比较认真的那一批,不是平均水平。这一点在读后面的数字时要记住:这些不是随便找的小站,它们是很多人拿来当参照对象的站。 剥标签数字符这个动作,用现成的HTML转纯文本工具 (https://zhangwenbao.com/html-to-text-clean-content-extraction-guide.html)也能做,不必自己写脚本。 请求方式是最普通的一次GET,用桌面版Chrome的用户代理串,跟随跳转,开启压缩,超时30秒,不执行任何脚本。整个过程用二十条并发跑完,全部211个域名在同一个时间窗内完成,避免出现"这个站是早上抓的、那个是晚上抓的"这种时间偏差。 拿到HTML之后的处理只有三步:剥掉script和style的成对标签及其内容,剥掉noscript,然后去掉所有剩余标签,把连续空白压成一个空格。剩下的字符数,就是这一页"直接给出来的可读文字"。 这个口径故意定得很窄,窄到有点不近人情。它不认脚本里的JSON数据,不认结构化数据块,不认属性值里藏的文案,也不认注释里的东西。理由很简单:它模拟的不是浏览器,是一个只会读字节、不会执行代码的读者。这类读者今天有很多,而且这两年正在快速变多。 要给这个口径挑毛病也很容易。它会冤枉那种"内容在页面上但被写进了属性"的写法,也会把一些正当的懒加载算成缺失。但它有一个别的口径都没有的好处:任何人拿同样的三步,在任何一台机器上,都能得到同一个数字。做横向对比的时候,这个性质比精确更值钱。 ## 211个域名,最后剩下132个 211个域名里,返回200并且正文超过3000字节的有132个。其余的要么连不上,要么撞上人机验证页,要么直接403。这79个的去向本身是另一篇文章的题目,这里先按下不表——只强调一点:后面所有的百分比都算在这132个身上,因为只有它们证明了自己愿意对一次普通请求给出一个真页面。 用什么身份去请求会改变结果,这份爬虫识别与UA分类 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)把各家的串列全了。 这一步很重要,重要到值得多说两句。如果把连不上的站也算进分母,任何"缺失率"都会虚高,而且虚高的原因跟被测的东西毫无关系——一个站因为防护策略把我拒之门外,跟它首页有没有写标题是两回事。混在一起算,得到的数字既不能说明防护,也不能说明结构。 把基线定在数据内部、不从外面拍脑袋,是这一整套测量能站住的前提。这个原则在本文后半段还会再出现一次,而且那一次的教训要贵得多。 ## 为什么先量"有没有字",而不是先量结构 做技术审计的人有个通病,喜欢从精细的项目查起:结构化数据对不对、标题层级顺不顺、图片有没有替代文本。这些都该查,但顺序错了。 从粗到细的顺序,企业网站SEO审计框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)里也是这么排的,先抓取后内容。 顺序应该是从粗到细,而且每一层都是下一层的前提。正文都不在,讨论标题层级毫无意义,就像检查一个空信封的折叠是否规整。本文后面那次尺子失效,根子就在于第一遍跑的时候没把这个顺序摆对。 所以整套检查的第一个问题永远是同一个:这次交付的字节里,有没有字。答案是"有",才轮得到第二个问题。 ## 正文长度的分布长什么样 可读正文字符数 | 站点数 | 占132个的比例 | 0到99 | 18 | 13.6% | 100到499 | 7 | 5.3% | 500到1199 | 3 | 2.3% | 1200到2999 | 16 | 12.1% | 3000到5999 | 32 | 24.2% | 6000到11999 | 38 | 28.8% | 12000到24999 | 14 | 10.6% | 25000以上 | 4 | 3.0% | 正文字符和HTML字节是两件事,46个电商站的体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)量的是后一件。 这张表最刺眼的不是中间那一大坨,是最上面那一行:18个站的首页,可读正文不到100个字符。一百个字符是什么概念?大概就是这句话本身的长度。 把不到1200字符的都算成"空壳",一共28个,占132个的21.2%。这个1200的线不是随手划的,后面有一节专门讲它是怎么来的、以及划在别处会发生什么。 ## 另一头也值得看一眼 表的最下面两行是另一个极端:14个站正文超过12000字符,其中4个超过25000。 内容铺太多也有上限,Googlebot的2MB抓取限制 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)就卡在这里。 两万五千个字符的首页是什么样子?基本上是把整个商品目录、所有分类说明、全部页脚导航铺在一页上。这类页面在字节层面当然没有"内容不在"的问题,但它们有另一个问题:内容太多,重点在哪不清楚。 这就是为什么main标签和标题层级在后面会单独讲。当一页只有八百个字的时候,机器不用分区也能看明白;当一页有两万五千个字的时候,"哪一块是这页真正要说的事"就成了一个必须回答的问题,而回答它的方式只有语义标记。 内容太少和内容太多,需要的是同一套东西的两端:前者需要把内容交出来,后者需要把内容组织好。中间那一大坨表现正常的站,两件事都做对了,所以它们在后面的检查里通常也表现更好——这个相关性在数据里挺明显。 ## 五兆的HTML里一个字都没有,这可能吗? 可能,而且不止一个。把这28个站按可读字符数从少到多排开,前14个是同一个数字:0。 字节多少还牵着首字节时间,多层缓存对性能与抓取的双向影响 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)算过这笔账。 ## 零字符俱乐部的成员名单 域名 | HTML字节数 | 可读正文 | 结构化数据字节 | burrow.com | 5146465 | 0 | 710 | govee.com | 3198168 | 0 | 401 | quince.com | 2577494 | 0 | 363 | eufy.com | 2444733 | 0 | 415 | harrys.com | 2231979 | 0 | 725 | anker.com | 2109539 | 0 | 649 | soundcore.com | 1993145 | 0 | 736 | boohoo.com | 1936893 | 0 | 620 | nomadgoods.com | 1919826 | 0 | 596 | kotn.com | 1781118 | 0 | 241 | columbia.com | 1574364 | 0 | 1110 | prose.com | 47071 | 0 | 0 | sostrenegrene.com | 38027 | 0 | 0 | uniqlo.com | 6413 | 0 | 0 | 这批站多数跑现代前端框架,渲染模式选错就抓成空壳 (https://zhangwenbao.com/react-nextjs-framework-seo-rendering.html)讲的正是这个成因。 注意这张表里的两种零。上面11个是"很大的零":字节以兆计,内容为空。下面3个是"很小的零":整个文件才几万字节甚至6千字节,摆明了就是一个跳转壳或者加载器。 很小的零是诚实的,很大的零才是麻烦的。6413字节的文件,任何工具扫一眼都知道有问题;5兆的文件在体积报表里排在最前面,看上去像是个内容极其丰富的重量级页面,实际上一个字都读不出来。 打个不太恰当的比方:这就像收到一个巨大的包裹,拆开是十七层气泡膜,中间什么都没有。你不能说人家没发货,运单上的重量是实打实的。 ## 这五兆字节到底装了什么 既然不是文字,那总得是点什么。把这几个大文件拆开看,主要是三类东西:内联的样式表、内联的脚本代码、以及大段大段的状态数据——通常是一个巨大的JSON对象,里面装着这一页需要的所有商品信息,等着脚本把它渲染出来。 压缩只解决体积不解决内容,免插件压缩HTML的做法 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)能减掉一部分冗余。 内容在标签里还是在变量里差别很大,语义化HTML对抓取的实际影响 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)做过样本实测。 最后这类东西最有意思。商品名、价格、文案,其实全在这五兆字节里,只是它们被装在一个引号里,而不是装在一个标签里。一个不执行脚本的读者,理论上不是拿不到,是它没有义务去猜你那个JSON的结构。 这一点值得给做技术的同事说清楚,因为它经常引起争论。争论的焦点通常是"数据明明在HTML里"。数据确实在,但HTML是一个有语义的格式,标签就是语义。把内容放进一个属性值或者一个脚本变量,等于把它从有语义的部分挪进了无语义的部分。在有语义的地方它是内容,在无语义的地方它只是字符。 ## 体积和内容的关系被彻底切断了 把28个空壳页和104个正常页的HTML体积中位数放在一起比,结果是这样:空壳页335662字节,正常页586994字节。 想快速量体积,抓取体积检查器 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)能直接给出这一页有多大。 正常页确实更大,但只大了不到一倍。体积这个指标,在判断"有没有内容"这件事上,已经完全失效了。过去做技术优化,页面体积是个万能的粗筛指标——太大就是有问题。现在它只能告诉你传了多少字节,不能告诉你传的是什么。 保哥自己踩过这个坑。早年间审站,习惯先看一列体积排序,从大的往下看。这个习惯在服务端渲染的年代很好用,因为体积大基本等于内容多,排在最前面的往往就是那些堆了太多东西的页面。现在这个相关性断了,还按老习惯看,注意力会被系统性地引到错误的地方去。 更麻烦的是,体积这个指标还在各种报表里活得好好的,页面性能工具会报它,抓取诊断工具会报它,看板上通常有一格给它。一个已经失去解释力的指标,如果还挂在显眼的位置,比没有这个指标更糟——它会持续地把注意力吸走。 ## 顺手记一个细节:这些页面的响应都很快 抓取的时候顺带记了每个请求的耗时。有点意外的是,这28个空壳页的响应速度普遍不慢,有几个还比正常页快。 想想也合理。服务端不用查数据库、不用套模板、不用拼字符串,直接把一份构建好的静态文件甩出来,当然快。所有的活都推给了浏览器,而浏览器那边的耗时不会出现在服务器的响应时间里。 这条值得记一笔,因为它意味着响应时间这个指标同样不能用来判断内容有没有交出去——跟体积一样,又一个看着很相关、实际毫无解释力的指标。 ## 脚本数量也不站在你这边 还有一个更反直觉的对照:空壳页的script标签数中位数是22个,正常页是70个。 脚本多少还牵着首屏速度,关键渲染路径优化 (https://zhangwenbao.com/critical-rendering-path-render-blocking-css-optimization.html)把阻塞机制讲透了。 正常页的脚本反而多三倍。原因不难想——那些正常吐HTML的站大多跑在成熟的电商平台上,平台自带的追踪、客服、评价、推荐插件一堆,脚本自然多。而空壳页往往是自研的单页应用,脚本少但每一个都是重量级的:一个框架运行时,一个应用包,一个状态数据块,齐活。 所以"脚本多的站更可能是空壳"这个直觉,方向是反的。这类反直觉的地方特别值得记一笔,因为它们正是经验会骗人的位置。凭直觉排查,你会先去查那些脚本一大堆的平台店,而它们恰恰是这一项上表现最好的。 顺着这条线还能得到一个更实用的判断:用自研前端的站,出这个问题的概率明显高于用成熟电商平台的站。不是因为自研团队水平差,恰恰相反,是因为自研团队有能力选择渲染方式,而选择往往发生在没有人代表机器读者说话的那个会议上。 ## 这28个站是怎么走到这一步的 没有一个团队会在某次会上决定"我们不给爬虫留内容"。这件事是一步一步走过来的,每一步都很合理。 单页应用被AI爬不到的完整链路,SPA站被跳过的真相 (https://zhangwenbao.com/ai-search-skips-spa-rendering-passage-level.html)有四种渲染模式对比。 第一步,前端选了一个现代框架,因为它开发效率高、交互体验好、招人也容易。这个决定几乎没有争议。 第二步,框架默认是客户端渲染,服务端渲染需要额外搭一层服务、额外一套部署、额外的缓存策略。评估之后决定先不做,等有需要再说。这个决定当时也是对的,因为当时的"需要"确实还没出现。 第三步,站上线,搜索表现看着还行——因为主流搜索引擎会渲染。这一步进一步确认了第二步的判断。 第四步,两三年过去,读页面的程序名单变了。而没有人会在这个时候回头去复查第二步那个决定,因为那个决定当时被验证过是对的,而且验证的证据现在还在——搜索流量确实没出问题。 问题不在任何一步,问题在于没有一个环节负责在前提变化时重新审视旧结论。这个模式在技术决策里非常普遍,本文这28个站只是它一个特别容易量化的例子。 ## 空壳页到底给机器留了什么? 如果这28个站是完全不管机器的,事情反而简单——那就是一个纯粹的技术选型问题。但数据不是这么说的。 平台站的字段入口分散,Shopify的128种结构化数据类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)给了对照。 ## 先说清楚这张表是怎么比的 下面这张表把28个空壳页和104个正常页放在一起,逐项比"页面里有没有这样东西"。要注意的是,这里比的是有无,不是好坏——一个只写了三个字的标题也算有。 之所以这么比,是因为想回答的问题很具体:这些站是不是压根没考虑过机器读者。要回答这个,看有没有就够了,写得好不好是下一层的问题。 还有一点要说明:这几项全部位于HTML的头部,是服务端直接输出的,不受渲染方式影响。所以它们在两组之间的差距,反映的是意识差距,不是技术差距。这一点很关键,也是这张表能说明问题的前提。 ## 门面全在,正文全无 页面里有什么 | 28个空壳页 | 104个正常页 | 有title标签 | 26个(93%) | 102个(98%) | 有meta description | 23个(82%) | 96个(92%) | 有og标签 | 19个(68%) | 90个(87%) | 有结构化数据 | 16个(57%) | 77个(74%) | noscript里有文字 | 1个(4%) | 17个(16%) | 头部信息的完备度可以批量体检,Meta标签检测器的加权评分 (https://zhangwenbao.com/meta-checker-weighted-seo-audit-guide.html)一次跑完整页。 这张表是整篇文章里保哥最想让你盯着看的一张。 头部信息的完备度,空壳页和正常页几乎没差别。标题93%对98%,描述82%对92%,结构化数据57%对74%。这些东西全都写在head里,全都是静态输出的,一个都没落下。 只有一行例外,而且例外得非常干净:noscript里有文字的,空壳页28个里只有1个。 ## 这说明了什么 说明这些站完全知道有机器会来读它们。知道要给标题,知道要给描述,知道要给社交分享的卡片图,甚至知道要给结构化数据。这些工作没有一样是给人做的,全都是给机器做的。 中间那条缝要靠协作填,前端工程师SEO协作的7个动作点 (https://zhangwenbao.com/frontend-engineer-seo-collaboration-7-actions-semantic-cwv-render.html)给了具体分工。 然后,在"要不要给这些机器留一份能读的正文"这个问题上,它们的答案是不留。 这不是疏忽,这是一个默认值。前端框架默认就是这么工作的,没人主动选择过它。团队里做SEO的那个人负责了标题和描述,做前端的那个人负责了渲染方式,两件事各自都做得挺对,中间那条缝没有人的名字写在上面。 这个判断有一条很硬的旁证:头部信息的完备度跟正文有没有输出,几乎不相关。如果这些站是"不重视机器",那标题和描述也该一起烂掉。事实是它们的头部信息只比正常站低几个百分点,而正文的差距是从6539掉到14。一个指标掉了几百倍,相邻的指标纹丝不动,这只能说明它们由两拨人、两套流程负责。 ## noscript那一栏为什么是最关键的一栏 表里最后一行看着不起眼,其实是全表信息量最大的一行。 不执行脚本的读者拿到什么,CSR与SSR的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)给过一组对照数字。 noscript这个标签的作用就一个:告诉不执行脚本的读者,这里有一份备用内容。它存在的唯一理由就是照顾那类读者。一个站在noscript里写了正文,等于明确表过态:"我知道有人不执行脚本,这是给他们的。" 28个空壳页里,表过这个态的有1个。 而正常页里有17个(16%)写了noscript内容。有意思的是,正常页本来就不太需要它——正文已经在字节里了。该写的那批没写,不太需要写的那批反而写了。这个错位不是巧合,它说明noscript的使用跟"是否意识到有非浏览器读者"高度相关,而空壳页的团队恰恰是最没意识到这件事的那批。 ## 结构化数据比正文长92倍的那个站 有两个例子值得单独拿出来。awaytravel.com的首页可读正文是145个字符,同一份HTML里的结构化数据是13423字节。avocadogreenmattress.com正文36个字符,结构化数据5159字节。 结构化数据到底有多大用,Schema对AI搜索的官方说法加实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)说得比较克制。 这两个站给机器准备的专用数据块,比给所有人准备的正文长几十倍到近百倍。它们不是没为机器着想,它们只为机器准备了一份精装的名片,然后忘了带上要谈的事。 这个比例本身就是个很好的自查指标:把你首页的结构化数据字节数除以可读正文字符数,如果这个比值超过1,基本可以断定正文没有被服务端输出。这个指标的好处是不需要判断"多少字算够",它是个相对值,任何品类任何规模的站都能用。 还要多说一句,这种配比本身在规范上就有风险。结构化数据的通行要求是它描述的内容要在页面上真实存在、用户看得到。当结构化数据里写着商品名和价格,而同一份字节里的正文是空的,这个对应关系严格说是断的。实际执行中很少有人因此被处理,但把它当成一个可以长期依赖的做法,并不稳妥。 ## 为什么这种做法会流行起来 值得花两句话说说它的来路,因为理解来路才知道该怎么劝人改。 哪些类型值得做,Schema官方公开的全网使用数据 (https://zhangwenbao.com/schema-org-usage-statistics-priority-guide.html)比凭感觉堆类型靠谱。 过去几年,行业里关于结构化数据的讨论极其密集,各种指南、各种工具、各种检测器,都在告诉你"把这些字段填全"。填全之后工具会给你一个绿色的对勾,非常有成就感。而"页面上有没有正文"这件事,没有任何工具会给你一个红色的叉。 于是就形成了一个很自然的行为模式:大家都在做有反馈的那件事,没反馈的那件事没人做。这跟人的水平没关系,跟工具塑造的注意力有关系。 所以劝人改的时候,讲道理效果一般,给他看数字效果好得多。把他自己站的那个比值算出来——结构化数据多少字节,可读正文多少字符——这个数字一出来,通常不需要再多说什么。本次实测里那两个比值超过90倍的站,只要有人把这个数摆到会上,事情大概率就推动了。 ## 无障碍树是什么,它凭什么跟抓取有关? 到这里为止讲的都是"有没有字"。接下来这一层更细:字有了,但字和字之间的关系在不在。 先把测量框架想清楚,别急着埋事件 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)是同一个顺序问题。 ## 先把这棵树说清楚 浏览器拿到HTML之后会构建两棵树。一棵是文档对象模型,也就是常说的DOM,它管的是元素怎么排布、样式怎么套用。另一棵叫无障碍树 (https://developer.mozilla.org/en-US/docs/Glossary/Accessibility_tree),它管的是每个元素"是什么、叫什么、现在什么状态"。 智能体读的到底是什么,AI浏览器读无障碍树而不是页面截图 (https://zhangwenbao.com/ai-agent-accessibility-tree-not-pixels.html)这篇讲得更细。 读屏软件用的是第二棵。一个盲人用户用读屏软件浏览你的站,软件念给他听的不是DOM,是无障碍树上的节点:这是一个按钮,它叫"加入购物车",它现在可用。 这棵树的存在意义从一开始就跟搜索毫无关系。John McAlpin在2026年8月那篇讲无障碍树用例的文章里 (https://searchengineland.com/accessibility-tree-seo-use-cases-484338)专门用一整段强调了这件事:这棵树存在的目的是让残障人士能用网络,SEO上的好处只能当作把无障碍做对之后的副作用,不能反过来当成设计的驱动力。这句话保哥完全同意,而且觉得应该抄一遍贴在工位上。 ## 那为什么它跟机器读页面扯上了关系 因为一个不带眼睛的读者,和一个带眼睛但只能读结构的读者,需要的东西高度重合。 无障碍改造的完整清单,18个改动的实操指南 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)可以直接照着走。 读屏软件需要知道"这个圆形图标是干什么的",AI代理也需要知道。读屏软件需要知道"这一坨文字里哪块是主内容、哪块是导航",抓取程序同样需要知道。无障碍树本来就是一份"把视觉信息翻译成语义信息"的产物,而所有不靠视觉理解页面的读者,用的都是同一份翻译。 这也是为什么这套检查特别值得做:它同时服务两拨人,而且其中一拨是法律和道德意义上你本来就该服务的。 ## 状态那一层,很多人根本没意识到它存在 名字和角色比较好理解,状态这一项容易被忽略,但它在交互页面上出问题的概率最高。 折叠面板里的内容算不算数,内容折进标签页手风琴的处理 (https://zhangwenbao.com/hidden-content-tabs-accordions-seo.html)有官方口径。 举个具体的:一个折叠面板,点一下展开,再点一下收起。视觉上一目了然,因为箭头会转、内容会出来。而在无障碍树上,这个"现在是展开还是收起"是靠一个属性表达的——aria-expanded,值是true或false。 最常见的缺陷是这个属性写死了。初始状态写了false,面板打开时脚本没有把它改成true。视觉上一切正常,树上永远是"收起"。对读屏软件用户来说,他点了展开,系统告诉他还是收起的,内容就在那儿但没人通知他。 这一层没法从静态HTML里查,因为它的错误恰恰发生在"应该变而没变"这个动作上。要查它只能真的去点一下,然后看树。所以本文的量化部分完全没有覆盖这一层——这不是漏了,是这个方法从原理上就够不着。把方法的边界说清楚,比多给几个数字重要。 ## 可访问名是怎么算出来的 树上每个节点有三样东西:角色、名字、状态。角色是"这是个什么",比如按钮、链接、标题;状态是"它现在怎么样",比如展开还是收起、选中还是未选中;名字就是"它叫什么"。 名字来源里alt占很大比重,图片alt与属性的批量体检 (https://zhangwenbao.com/image-alt-checker-batch-audit-cls-accessibility-guide.html)能一次扫完整页。 名字这一项有一套明确的计算顺序,不是随便取的:先看aria-labelledby指向的内容,再看aria-label属性 (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-label),再看元素本身该用的原生属性(比如图片的alt、表单的关联label),再看元素内部的文字,最后才是title属性。 这个顺序有个很实用的推论:越靠前的方式优先级越高,也越容易把后面的盖掉。给一个已经有文字的按钮再加一个aria-label,实际生效的是aria-label,按钮上那行字反而不算数了。这是个常见的错误来源——两个人各写了一半,结果只有一半生效。 ## 怎么在没有浏览器的情况下量这一层 严格说,无障碍树只有浏览器能构建,因为它依赖渲染后的最终状态。但上面那套计算顺序里,绝大多数来源是HTML里静态写着的:aria-label、aria-labelledby、alt、label的for关联、元素内部的文字。这些东西在字节里就能看到。 字节和渲染后的差异,渲染对比器 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)能直接把两份结果摆在一起。 所以可以退一步:不去构建整棵树,只检查"这个元素有没有可能拿到名字"。一个button标签,里面没有文字,也没有aria-label,也没有aria-labelledby,也没有title,也没有带alt的图片子元素,那它渲染成什么样都不会有名字——除非脚本在运行时给它补一个。 "除非脚本补一个"这句是这套方法唯一的缺口,必须承认。所以下面所有数字的准确说法是:这些元素在服务端交付的那一刻是无名的。它们后来有没有被补上,只有真浏览器能回答。但对一个不执行脚本的读者来说,"后来"不存在。 本次量的是170份可解析首页快照。为了不让空壳页污染结果,先把它们剔掉了——这一步的重要性,后面有一整节专门讲,而且是这篇文章里最贵的一段教训。 ## 页面上那个按钮,在机器眼里叫什么名字? 剔掉空壳页之后剩110个站,下面所有比例都算在这110个身上。 弹窗上的关闭按钮尤其常见,侵入式插页的真相与豁免 (https://zhangwenbao.com/intrusive-interstitial-popup-ranking-penalty-myth.html)说明了什么情况会出问题。 ## 原生按钮的情况 110个站的首页一共有4876个button标签,其中401个(8.2%)拿不到任何名字。这401个分布在41个站上,也就是说每10个站里差不多有4个,首页上至少有一个按钮对机器来说是无名的。 这类结构短板可以批量扫,页面结构分析工具的六维体检 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)覆盖H1层级和语义标签。 最集中的几个:philips.com的58个按钮里46个无名,allbirds.com的79个里41个,peakperformance.com的121个里34个,ritual.com的65个里30个,chubbiesshorts.com的62个里30个,dreametech.com的60个里27个。 这些按钮在浏览器里当然有样子——它们是购物车、搜索、菜单、关闭、上一张下一张。人一眼就认得出,因为人认的是图形。机器认的是名字,而名字这个字段是空的。 ## 为什么偏偏是这几类按钮 把无名按钮挨个看过去,会发现它们高度集中在几个位置:轮播的左右箭头、弹窗的关闭叉、菜单的汉堡图标、搜索的放大镜、数量增减的加减号。 图标库的用法差别不小,Font Awesome各版本的语法与SVG渲染 (https://zhangwenbao.com/how-to-use-font-awesome-font-icons.html)影响的正是这一层。 这几个位置有一个共同点:它们的含义完全靠一个约定俗成的图形来传达,而这个约定只存在于人的经验里。一个向右的三角,全世界的人都知道是下一个,但这个知识不在HTML里,它在你脑子里。 还有一个共同点更现实:这些控件通常来自组件库,是同一份代码在页面上重复了几十次。所以一个站的无名按钮数量往往不是"错了几十次",而是"错了一次,用了几十次"。philips那46个,多半来自不到十种组件。 这是个好消息。它意味着修复成本跟数量不成正比。四十六个问题可能只对应五处改动,而且改完之后新写的页面自动就是对的。 ## 图标是重灾区 把内联的svg单独拎出来数:110个站里有3906个svg,既没有aria-label,也没有内嵌title,也没有被标记成装饰性元素。87个站有这个问题,占79.1%。 图标这件事从来不只一处,Favicon生成器给出的十个文件 (https://zhangwenbao.com/favicon-generator-transparency-crop-ico-html-coverage-guide.html)真正生效的只有一张。 这个数字大到有点吓人,但要说句公道话:svg没名字不一定是错。如果它外面包着一个有名字的按钮,那这个图标本来就该被标成装饰性的,不该有自己的名字。这3906个里有相当一部分属于这种情况。 真正确凿的问题是另一种:图标是唯一的内容,外面那层也没名字。本次数据里,纯图标且拿不到名字的链接有264条。这264条是硬伤,因为它们对机器来说就是264个"点这里",去哪里不知道。 ## 用div假装按钮的那批 还有一类:给div或者span加上role="button"来模拟按钮。110个站里有171处这种写法,分布在32个站上,其中13处连名字都没有。 该用什么标签有明确答案,8类语义标签对SEO的真实影响 (https://zhangwenbao.com/semantic-html-tags-seo.html)逐个做过拆解。 这个写法本身不算错,但它是一个信号。能用button标签的地方用了div,通常意味着这个团队在按视觉需求组织标签,而不是按语义需求。顺着这个信号往下查,一般还能查出别的。 更值得注意的是它的近亲:直接给div绑点击事件,连role都不加。这种写法110个站里有115处,分布在10个站上。加了role的至少还告诉了机器"这是个按钮",什么都不加的那种,在树上就是一段普通文字,只不过点它会有反应。键盘用户按Tab永远走不到它,读屏软件也不会提示它可以点。 ## 链接这一层的数字被一个站带偏了 链接的整体数字是这样:110个站一共28747条链接,其中2359条(8.2%)拿不到可访问名。 内链本身也能被标记,用结构化数据标注重要内链 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)是另一条思路。 但这个8.2%要打个折扣看,因为其中1855条来自同一个站。parachutehome.com的首页有2343条链接,其中1855条没有名字,占它自己的79%。一个站贡献了全样本无名链接的四分之三还多。 把它拿掉重算,剩下109个站的无名链接是504条,占比降到1.9%。两个数字都是真的,区别在于它们回答的问题不同:8.2%是"这批站的链接整体质量",1.9%是"一个典型的站大概是什么水平"。 遇到这种被单个样本主导的指标,最好的做法是两个数都给出来,并且说清楚差在哪。只给8.2%会让人以为这是普遍问题,只给1.9%又会漏掉那个真正出了大事的站。保哥见过太多报告在这种地方偷偷选一个对自己论点有利的口径,这是很不体面的做法。 顺便说一句,一个站首页放2343条链接本身也值得看一眼。这个数量远超样本中位数,多半是把整个商品目录铺在了首页上。 ## 一张图没有alt,和alt写成空字符串,差别在哪? 这是个特别容易被工具搞混的地方,而两者的含义正好相反。 同一份内容给人和给机器的写法可以不同,正文本地化而结构化数据写国际格式 (https://zhangwenbao.com/minor-language-structured-data-inlanguage-locale-schema.html)是个好例子。 ## 三种状态,三个意思 写法 | 机器怎么理解 | 数量 | 占9459张的比例 | alt里有文字 | 这张图有内容,内容是这些字 | 6814 | 72.0% | alt="" | 这张图是装饰,忽略它 | 2284 | 24.1% | 完全没有alt属性 | 不知道该怎么办 | 361 | 3.8% | alt写过头也有风险,图片alt关键词堆砌的新规解读 (https://zhangwenbao.com/2025-image-seo-alt-text-risk-optimization.html)附了处罚实例。 中间那一行是很多人误会的地方。alt=""不是"没写alt",它是一句明确的话:这张图不承载信息,跳过去。装饰性的分割线、渐变背景、纯视觉的图形,就该这么写,HTML标准里关于替代文本的那一章 (https://html.spec.whatwg.org/multipage/images.html)把什么时候该写空字符串讲得比多数教程都细。写空的alt是尽责,不是偷懒。 最后那一行才是问题。没有alt属性意味着没有人表过态——它可能是重要商品图,也可能是背景纹理,读的一方只能自己猜。本次样本里有361张,涉及36个站,占110个站的32.7%。 ## 72%这个数字该怎么看 72%的图有文字alt,听起来不算差。但这个数字是按图片张数算的,而首页上的图片张数分布极不均匀——一个站可能有200张,另一个只有15张。张数多的站会把整体比例拉向它自己的水平。 文件名、alt、WebP与懒加载怎么配合,图片SEO的完整落地 (https://zhangwenbao.com/website-photo-seo-optimization-techniques.html)讲得比较全。 所以更该看的是站的口径:110个站里有36个,首页上至少有一张图没有alt属性。这36个站不是alt写得不好,是这一项根本没进他们的检查流程。 这两个口径的差距,是所有横向审计都要面对的问题。个数口径回答"整体质量怎么样",站数口径回答"这个问题普不普遍"。汇报的时候用站数口径,排期的时候用个数口径。反过来用,要么把问题说得太轻,要么把工作量估得太大。 ## 那361张没有属性的图,都是些什么图 把这361张挨个看过去,来源比想象的集中。 最多的一类是脚本生成的图。购物车里的商品缩略图、推荐位里的商品图、评价区里的用户上传图,这些都是运行时插进来的,插的时候只带了地址没带说明。写这段脚本的人手上根本没有替代文本这个数据——后台的商品字段里没有这一栏。问题不在前端,在数据模型。 第二类是第三方嵌入的图。支付方式的标志、物流公司的标志、认证徽章、社交平台的图标,这些通常是从别人给的代码片段里复制过来的,原样贴上,没人会去改。这一类有个特点:它们往往集中在页脚,一排排挨着,缺一起缺。而支付方式那一排恰恰是转化路径上很关键的信任信号,读不出来等于这份信任没传达到。 第三类才是真正的疏忽:模板里手写的图,写的时候忘了。这一类数量最少,通常也最好改,因为它们就在模板文件里摆着,一个个补过去就行。 有意思的是,很多团队的注意力恰恰全放在第三类上——因为它最好找、最好改、改完最有成就感。而占比最大的第一类,因为要动后台字段、要拉上运营和产品,往往就一直挂在那儿。这个模式在技术优化里到处都是:先做完的总是最容易的那一件,不是最要紧的那一件。 知道来源之后,处理方式就清楚了:第一类要去后台加字段,第二类可以批量补上,第三类改模板。三件事的负责人不是同一个,工作量也差着量级。上来就说一句"我们有361张图缺替代文本",谁也不知道该干什么。 第一类值得多说一句,因为它是最容易被误判的。前端同事看到这个问题,第一反应通常是"我加个默认值就行",于是所有商品图的替代文本都变成了同一句"商品图片"。这确实让缺失率归零了,但信息量还是零,只是从"没表态"变成了"表了个没用的态"。真要解决,得让运营在上架时把那一栏填上,而那需要后台先有那一栏。 ## 那24%的空alt里,有多少是真的装饰图 这个问题没法用抓取的方式回答,必须人看。保哥随手抽了几个站翻了翻,感觉大体是对的——那些空alt多数落在分割线、渐变块、图标背景这类元素上。 alt是不是排名因素,这个说法的真相 (https://zhangwenbao.com/image-alt-text-ranking-factor-myth.html)跟很多人想的不一样。 但也确实见到写错的:有的商品列表里,商品主图的alt是空的,旁边一个装饰性的角标反而写了文字。这种颠倒比全部留空更麻烦,因为它会让读的一方得到一个错误的信息层次:装饰被当成了内容,内容被当成了装饰。 所以这一项没法完全自动化。能自动化的部分是"有没有表态",表得对不对,还得人看。好在需要人看的量不大——把首屏那十几张图看一遍就够了,剩下的多半是同一套模板出来的。 ## 写alt的一条实用判据 跟SEO没关系但很好用:如果这张图去掉之后,你需要用一句话补上它说的事,那句话就是alt。如果去掉之后什么都不用说,那就写空字符串。 非拉丁字母的站更麻烦,文件名和alt要用两套字母写同一个词 (https://zhangwenbao.com/minor-language-image-alt-text-non-latin-script-search.html)是实测结论。 这条判据的好处是它自然地控制了长度。补一句话通常十几到三十几个字符,不会写成一段。见过最离谱的alt是把整段商品描述塞进去,那不是替代文本,那是把正文藏进了属性里。而藏进属性里的文字,前面刚说过,在语义上是不算数的。 ## 表单里那个输入框,谁告诉机器它是干什么的? 表单这一项的数字,是整套检查里最糟糕的。 留邮箱那个框最典型,邮件弹窗的时机字段与合规 (https://zhangwenbao.com/email-popup-lead-capture-opt-in-conversion-guide.html)把这一步拆开讲了。 ## 四分之一的输入框没有标签 把隐藏域、提交按钮这类排除掉,110个站的首页一共有1192个真正需要用户输入的字段。其中291个(24.4%)拿不到任何形式的标签:没有label关联,没有aria-label,没有aria-labelledby,也没有title。 表单控件选错的代价,下拉框如何悄悄吃掉询盘 (https://zhangwenbao.com/form-dropdown-control-selection-conversion.html)是个很具体的例子。 受影响的站有44个,占40%。也就是说每5个站里有2个,首页上至少有一个输入框,机器不知道它要填什么。 ## 为什么偏偏是表单最差 因为占位符太好用了。 首屏那一块的设计取舍,导航、主Banner到分类区的排布 (https://zhangwenbao.com/homepage-above-the-fold-hero-conversion-design.html)决定了标签放不放得下。 设计稿上一个干干净净的输入框,框里灰色小字写着"请输入邮箱",视觉上非常清爽,不需要额外一行标签文字。前端照着实现,用placeholder属性,一切正常。 问题是placeholder不是标签。它是提示,是示例,是可以随时消失的东西——用户一开始打字它就没了。把它当标签用,等于把一块随时会掉的牌子挂在门上。 这件事的坏处不只在机器那边。用户填到第四格的时候想回头确认第二格填的是什么,看到的是一串已经输入的文字,但那一格要求填什么已经不在屏幕上了。这是个纯粹的可用性缺陷,跟搜索、跟AI、跟任何技术指标都没关系,它就是不好用。 本次数据里几个典型:ritual.com的22个输入框全部无标签,mejuri.com的14个全部无标签,allbirds.com的13个全部无标签,awaytravel.com的8个全部无标签。这种"全军覆没"的形态几乎可以断定是同一套组件出来的,改一处就能全好。 ## 视觉上不想要标签,该怎么办 这是个真实的设计诉求,不能光说"你得加标签"就完事。实际有三种做法,各有适用场景。 视觉隐藏靠的是样式类,CSS的美化压缩与性能账 (https://zhangwenbao.com/css-formatter-beautify-minify-frontend-performance-guide.html)顺带讲了这类工具链。 第一种,把标签留在HTML里但视觉上隐藏。用一个专门的样式类把它移出可视区域,而不是用display:none——后者会把它从无障碍树上一起拿掉,等于白写。这是最常用也最稳妥的做法,几乎所有成熟组件库都提供了这个类。 第二种,给输入框加aria-label,值就是那句标签文字。这种做法更简洁,适合搜索框这类只有一个输入框、上下文很明确的场景。 第三种,浮动标签——用户没输入时标签显示在框里,开始输入后缩小移到框上方。这种做法视觉效果好,标签也一直在,是这几年比较流行的方案。缺点是实现复杂,而且要注意别把标签做成一个纯视觉的div,那样又回到原点了。 三种做法的共同点是:标签这个东西一直存在,只是被安排到了不同的位置。而用placeholder代替,是让它彻底不存在。 ## 一个反例说明这不是做不到 casetify.com的首页有591个输入字段,是全样本最多的,多半是筛选器和批量表单撑起来的。其中无标签的是121个,比例20.5%,低于平均。同一份HTML里有375个带for属性的label。 筛选器多的站字段自然多,分面导航的抓取预算治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)是配套的另一半。 一个字段数量最多的站,标签覆盖率反而高于平均。这说明这件事跟站的复杂度没关系,只跟有没有把它写进组件规范有关。 反过来看那几个"全军覆没"的站,字段数都在十几到二十几个,规模小得多。不是因为难所以没做,是因为量小所以没人觉得需要立规矩。二十二个输入框,手写就手写了,等到有一天变成两百二十个,那套没有标签的写法已经复制了两百遍。 ## 邮件订阅框是第二个 排在搜索框后面的是邮件订阅框,理由类似但不完全一样。 它同样出现在几乎每一页的页脚,同样是一个明确的转化动作,同样极少有人给它配标签——因为设计上那一块通常就是一行输入框加一个按钮,加一行标签文字会显得很笨重。 不一样的地方在于后果。搜索框填错了,用户马上知道,因为结果不对。订阅框填错了,用户什么都不知道,他以为自己订阅成功了。本次样本里有几个站,页脚同时有订阅邮箱和搜索两个输入框,都没有标签,光看字节完全分不出哪个是哪个。 顺带说一句,这一块的按钮也常常是无名的——很多站的订阅按钮就是一个箭头图标。一个没有名字的输入框,配一个没有名字的按钮,这个组合在树上就是两个匿名节点并排站着。 ## 搜索框是最该优先修的那一个 如果只能改一个输入框,改搜索框。理由有三条。 搜索框值得单独设计,从入口到结果的四层拆解 (https://zhangwenbao.com/site-search-bar-ux-design-conversion.html)把这个高转化入口讲透了。 第一,它几乎在每一页上都有,一处改动全站受益。第二,它是站内转化路径上最短的一条——用户用搜索找东西,意图最明确、转化率通常最高。第三,它恰恰是最容易只写占位符的那一个,因为设计上大家都不想在搜索框旁边再摆一行"搜索"两个字。 本次样本里,无标签输入框里搜索框占了相当一部分。一个每页都出现、承担高价值动作、又系统性缺标签的控件,投入产出比高得不像话。这种机会在技术优化里不多见,通常一件事要么便宜要么有效,很少两者兼得。 ## 标题层级跳一级,机器会怎么理解? 标题这一层的结论比较微妙,需要分开说。 改标题会不会掉排名,改动本身不被罚改错内容才掉 (https://zhangwenbao.com/changing-title-tag-drop-ranking-myth.html)澄清了这个担心。 ## h1的分布 110个站里,首页没有h1的有28个(25.5%),有且只有一个的58个(52.7%),有多个的24个(21.8%)。 标题本身怎么写,10个技巧加5类高点击公式 (https://zhangwenbao.com/how-to-write-catchy-article-titles.html)是内容侧的功课。 关于h1数量的争论已经吵了十几年,这里不想再吵。只说一个事实:h1有几个不重要,重要的是有没有一个标题告诉读者这一页是关于什么的。那28个没有h1的站里,多数是有h2的,视觉上也确实有个大标题——只是那个大标题被写成了div加大字号。 ## 跳级的比例是45.5% 这个数字比想象的高。110个站里有50个,标题层级出现过跳级:h2下面直接接h4,或者h1下面直接接h3。 层级关系也体现在面包屑上,四种类型与结构化数据实操 (https://zhangwenbao.com/seo-breadcrumbs-types-schema-implementation.html)可以对照着看。 跳级的实际危害没有很多文章渲染的那么大,机器不会因为你跳了一级就读不懂。但它是一个非常好的信号:层级跳了,说明标题是按字号选的,不是按结构选的。而按字号选标题的页面,一般还会有别的结构问题。 保哥审站的时候有个偷懒办法:只把页面所有h标签的数字按顺序列成一串。本次实测里抓下来的几串长这样——一个站是"2322322233",另一个是"333333333333231222222232",还有一个是"41323232333333333334"。 第一串是正常的:二级下面挂三级,起伏有规律。第二串一看就不对:十二个三级排在最前面,一个上级都没有,说明这一大片内容在结构上是悬空的。第三串更乱,四级开头,然后一二三四轮着来,基本可以断定是几套模板拼在一起的。 这一串数字不需要任何工具,看一眼就知道这页的结构是设计出来的还是长出来的。保哥现在审站基本都是先看这一串,比跑任何评分工具都快,而且它给的是结构的形状,不是一个分数。 ## 那些被写成div的标题 110个站里有9个站用了role="heading",一共117处。这个属性的意思是"这个元素虽然不是h标签,但请把它当标题看"。 标题标签在AI时代的作用变了,8类骨架加实体信号的实战 (https://zhangwenbao.com/title-tag-ai-overviews-entity-dynamic-rendering.html)给了新的写法。 用它不算错,但它的存在本身说明了一件事:这9个站里有117个位置,视觉上是标题、标签上不是标题,只好用属性补一句。而这只是那些补了的。没补的有多少,从抓取数据里看不出来——一个被写成div加大字号的标题,在字节里跟一段普通文字长得一模一样。 这就是本文那句"视觉标题"问题的真实形态。它是所有结构问题里最难自动检测的一个,因为判断它需要同时知道"看起来像什么"和"标记成了什么",而抓取只能知道后者。目前唯一可靠的查法是人打开页面,把每个看起来像标题的东西点开看一眼标签。好在这活量不大,一页十几处顶天了。 ## 地标区域的情况 地标区域是给页面分区的:header、nav、main、footer这几个标签,或者对应的role属性。它们的作用是让不靠视觉的读者知道"从这里开始是正文"。 分区之上还有整站结构,架构搭错爬虫找不到产品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)讲的是更大的一层。 110个站里,四个齐全的76个(69.1%),有main的94个(85.5%),有nav的97个(88.2%),有footer的101个(91.8%),一个都没有的4个(3.6%)。 这一项的表现明显好于其他项,原因大概是这些标签写起来最省事——用header替代div不需要额外工作量,反而更短。凡是"做对不比做错麻烦"的事,行业整体表现就不会太差。这个规律在别的地方也成立,可以当成排优先级时的一条经验:那些需要额外动作才能做对的项,才是真正需要靠流程去保证的。 还有个细节:94个有main的站里,有7个不是用main标签,而是给一个div加了role="main"。这个写法完全有效,但它通常意味着这套模板的年纪比较大,是在语义标签普及之前写的,后来打了补丁。看到role属性替代原生标签,可以顺手估一下这套代码的年龄,往往能解释别处的一些奇怪写法。 ## 主动把内容藏起来的那几个站 还有一个属性值得单独说:aria-hidden。给一个元素加上这个属性并设为true,等于告诉所有不靠视觉的读者"这块跳过,别读"。 跳过渲染也可能藏掉内容,content-visibility的机制实战 (https://zhangwenbao.com/content-visibility-css-containment-render-skipping.html)说明了边界在哪。 它的正当用途很多——装饰图形、重复出现的图标、已经被别处描述过的内容,都该这么标。110个站里这个属性一共出现了4652次,绝大多数属于正当使用。 但有8个块不太一样:它们各自藏起了超过300个字符的纯文字。分布在5个站上。三百多个字符是什么概念?大概是一段完整的商品介绍,或者一条完整的促销说明。 这种情况通常有两个来源。一个是弹窗或者抽屉式导航——它在关闭状态下被整体标为隐藏,这是对的,但如果脚本在打开时忘了把这个属性改回来,那它就永远是隐藏的。另一个是某次为了解决读屏软件重复朗读的问题,粗暴地把一整块标了隐藏,把该读的一起带走了。 这一项特别值得查,因为它的性质跟别的都不一样:别的项是忘了给信息,这一项是明确下令不要读。一条主动发出的错误指令,比一个被动的遗漏危害大得多,而且它绝对不会出现在任何"缺失项"的报表里——从任何自动化工具的角度看,这块内容有标签、有文字、结构完整,一切正常。 ## main标签有一个被低估的用途 main这个标签除了给读屏软件分区,还有一个越来越重要的用途:它是"正文从哪开始"的最明确的一句声明。 让AI读得懂引得出,GEO技术端的抓取渲染提取三步 (https://zhangwenbao.com/geo-technical-optimization-crawl-render-extract-guide.html)把这条链讲全了。 任何一个想从你页面里提取内容的程序,都要先解决一个问题——满页的导航、页脚、推荐位、弹窗里,哪一块是这一页真正要说的事。没有main标签,它只能靠猜,常用的猜法是找文字最密集的那个块。有main标签,这个问题就没有了。 这是本文所有检查项里,成本最低、说明力最强的一个。加一个标签,把一个需要推断的问题变成一个可以直接读的事实。85.5%这个数字已经不低,剩下那16个站补上,是半天的活。 ## 那次尺子失效是怎么被发现的? 现在讲这篇文章里最该被记住的一段。上面所有关于无障碍树的数字,第一版全是错的。 样本边界决定结论边界,调研数据里没有非会员结论却写给非会员 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)是同一个病。 ## 第一版的数字 第一次跑完170个站,结果是这样:一个地标区域都没有的占22.9%,没有h1的占47.1%,连一个标题标签都没有的占30.6%。 没有对照组就会虚高,74%的差异补上对照后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)是同一类教训。 这三个数字,任何一个单独拿出来都够写一篇标题很吓人的文章了。三成的独立站首页连一个标题标签都没有,听着像行业末日。 ## 发现问题的过程 保哥的习惯是在写结论之前,把最极端的那批样本逐个打开看一眼。这次打开的是"一个标题标签都没有"那52个,第一个是aesop.com,第二个是aliexpress.com,第三个是anker.com。 翻明细是唯一的防线,Google抓取报告里五类问题URL的排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)也强调这一点。 看到第三个的时候就不对劲了。anker.com刚刚在前半篇里出现过——它是那个2兆HTML零个字符的站。它当然没有标题标签,它连一个字都没有。 再往下扫,52个里有一大半是同一批空壳页。 ## 问题出在哪 问题不在尺子的算法,算法是对的:这些页面确实没有h1,确实没有地标。问题在于这把尺子被用在了它不该量的对象上。 想知道谁真的来过,日志分析一步步挖真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)比任何推断都实在。 量一个页面的语义结构,前提是这个页面有内容。一个还没渲染的空壳,它的语义结构不是"差",是"还不存在"。把它算成"结构差",等于批评一张白纸排版难看。 这个错误跟以前踩过的坑都不一样。以前的失效都是判据本身写错了——词表分不清、基准没定好。这次判据完全正确,错的是样本边界。一把准确的尺子用在错误的对象上,产生的错误数据比一把不准的尺子更难发现,因为每一条记录单独看都是对的。 ## 三种尺子失效,三种不同的病 把这几年踩过的坑摆在一起,形态其实很清楚: 判断力比工具重要,只会蛮力的SEO为什么被淘汰 (https://zhangwenbao.com/seo-skills-gap-business-acumen-html.html)说的是同一件事。 失效形态 | 错在哪 | 怎么才能发现 | 判据写错 | 规则本身理解偏了 | 回原文核对措辞 | 基准缺失 | 用了绝对判断,而规则是相对的 | 问一句"多出来的,是相对什么多" | 样本越界 | 判据对,但对象不该被量 | 翻最极端的那十几条明细 | 三种病的共同点是它们都让问题看起来更严重,从来没有一次是让问题看起来更轻的。这个方向性很值得琢磨。 保哥后来想明白了:因为尺子是奔着"找问题"做的,它的每一处模糊地带,默认都会倒向"这是个问题"。写规则的时候没有人会故意留一条"拿不准就算通过"的分支,于是所有拿不准的情况都堆到了"不通过"那一边。 所以有一条实用的自查:跑完一把新尺子,先看它有没有弃权的能力。一把只会说"通过"和"不通过"的尺子,一定在某个地方虚高。一把在没把握的时候会说"这个我判断不了"的尺子,才可能是诚实的。本次这把改完之后,空壳页就是它的弃权区——不是判它差,是判它不适用。 ## 修正之后的对比 结论 | 混入空壳页(170个) | 剔除空壳页(110个) | 虚高倍数 | 一个地标区域都没有 | 22.9% | 3.6% | 6.4倍 | 连一个标题标签都没有 | 30.6% | 2.7% | 11.3倍 | 首页没有h1 | 47.1% | 25.5% | 1.8倍 | 四个地标区域齐全 | 45.3% | 69.1% | 被压低 | 被广泛相信的数字未必成立,重复内容惩罚这个说法 (https://zhangwenbao.com/duplicate-content-penalty-myth.html)其实从来不存在。 最夸张的一条虚高了11倍。而且注意最后一行:好的结论被同样的机制压低了,方向相反,幅度也不小。 ## 那一版差点就发出去了 说句实话:那三个虚高的数字,当时已经写进初稿了,而且写得挺顺手——三成的独立站首页连一个标题标签都没有,这句话既有冲击力又有数据支撑,读起来毫无破绽。 拦下它的不是任何工具,也不是复核流程,是一个习惯:在写结论之前,把最极端的那一批样本逐个打开看一眼。这个习惯很笨,很花时间,一次要看十几二十个页面,而且绝大多数时候什么问题都看不出来。 但它是唯一有效的。所有自动化的检查,检查的都是"计算过程对不对",而这类错误发生在计算开始之前——发生在决定"哪些东西进入这次计算"的那一步。没有任何一个程序会质疑你给它的输入名单,它只会认认真真地把错误的输入算得一丝不苟。 这也是为什么保哥每次量完东西,都要留一节专门讲量的过程。不是为了显得严谨,是因为一篇只给结论不给口径的文章,读者没有任何办法判断它有没有犯这个错。而这个错,从数字表面是绝对看不出来的。 ## 为什么这类错误特别难被发现 因为它没有任何异常特征。 看着整齐的高比例最该警惕,76%改写率那个数字 (https://zhangwenbao.com/google-ai-headline-rewrite-seo.html)也得看它怎么算出来的。 一把算错的尺子,通常会露马脚:某个站的数字大得离谱,某个分类一条都没有,某两项互相矛盾。这些都是可以被察觉的。而这次的每一条记录单独看都完美无缺——anker.com的地标数量确实是零,这个记录没有一个字段是错的。 错误不在任何一条记录里,错误在"这条记录该不该出现在这张表里"。而这个问题,表本身回答不了。 更麻烦的是,这类错误的方向是系统性的,不是随机的。随机误差会互相抵消,越多样本越准。系统性偏差不会——空壳页在每一项上都会算成"最差",样本越多,偏差越稳定地把结论往一个方向推。看到一个特别整齐、特别符合预期、特别适合当标题的数字,反而应该警惕。 ## 这条教训该怎么用 提炼成一句可操作的:在跑任何结构类审计之前,先问一句"这批样本里,有多少个根本不该被这把尺子量"。 回到基本盘,抓取、索引、排名三步 (https://zhangwenbao.com/how-search-engines-work-crawl-index-rank.html)是判断任何前提的起点。 判断方法也简单,跟这篇文章前半段是同一个动作:先量每个页面的可读正文长度,把明显不到线的挑出来单独成一组。它们不该被算成"结构差的站",它们该被算成"另一个问题的站"。 再往上提一层,这其实是一条通用的经验:任何一把尺子都有一个默认前提,而这个前提一般不写在文档里。量结构的尺子默认页面有内容,量转化率的尺子默认流量是真人,量停留时长的尺子默认用户没开着标签页去吃饭。用尺子之前把这个默认前提找出来,然后去数有多少样本不满足它——这个动作花不了十分钟,但它是保哥吃过好几次亏之后唯一留下的防线。 ## 那条1200字符的线是怎么划的? 上面反复用到"空壳"这个分类,判据是可读正文小于1200字符。这个数怎么来的,得交代一下,不然整篇文章的地基是虚的。 首页铺太多也会牵出URL问题,筛选器URL不爆炸的系统方案 (https://zhangwenbao.com/faceted-navigation-filter-url-seo-crawl-trap.html)给了八步做法。 ## 先看数据自己怎么说 把132个站的正文字符数排序,会看到一个非常明显的双峰:一堆挤在0到500之间,另一堆从1200往上一直铺到两万多,中间500到1200这一段只有3个站。 分布怎么看,服务器日志分析工具 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)给了现成的分桶方式。 这条线不是我划的,是数据自己裂开的地方。1200这个数落在那道缝里,往左移到500或者往右移到2000,被分类的站只会变动两三个。一个稳健的阈值就该是这样——挪一挪结果不怎么变。 ## 边界上那几个站 紧挨着线右边的几个:joolz.com正文1262字符,ecoflow.com 1464,nespresso.com 1503,peakdesign.com 1682。 边界情况最容易漏,抓取速率被调低却一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这么发生的。 这几个都被算成了"正常页",但说实话它们也没正常到哪去。1262个字符对一个电商首页来说,大概就是导航加页脚的量,商品区多半还是靠脚本画的。 所以这条线的正确读法不是"过线就没事",而是"过线之后要看的是别的问题"。分类的作用是把不同性质的问题分开处理,不是发及格证。 ## 如果换一个口径 值得说一句:如果不用字符数,改用"首屏商品名有没有出现在HTML里"这类内容级判据,分类结果会更贴近实际,但可复现性会大幅下降——不同品类的首页放什么根本不一样,一个家具站和一个美妆站的首屏完全没有可比的元素。 口径要能复现,一个尾逗号就让整页结构化数据失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)说明细节有多要紧。 字符数这个口径粗,但它对所有站一视同仁,而且任何人拿同样的方法都能复现出同样的数字。在做横向对比的时候,可复现性比精确性重要。 这条原则值得展开一句,因为它经常被误解成"糙一点没关系"。不是的。它说的是:当你要比较很多个对象的时候,一把所有人都能拿到同样读数的粗尺子,胜过一把只有你能用好的精细尺子。因为横向对比的价值全在"可比"这两个字上,尺子一旦因人而异,所有排名都失去意义。 换成自己站的纵向监测,结论就反过来了:这时候没有可比性问题,用越贴近业务的判据越好。横向用粗尺子,纵向用细尺子,这是两种完全不同的测量任务,经常被混为一谈。 ## 把这条线用在自己站上 如果你要照着这套方法量自己的站,1200这个数不要直接搬。它是从这批国际化独立站首页的分布里长出来的,换一批样本,那道缝的位置会变。 一个站两套技术栈很常见,插件和主题冒出两套标记怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同源问题。 正确的做法是:把你自己站上各类页面各抓十几个,量出正文字符数,画一下分布。如果分布是连续的,说明你的站在这件事上是一致的,那就不需要分类;如果出现明显的双峰,那道缝就是你的线。 多数站的结果是第一种——同一套模板出来的页面,输出方式是一样的。出现双峰通常意味着站上有两套技术栈,比如商品页是服务端渲染的老系统,而某个新做的活动频道是纯前端的。这种情况在做过几次改版的站上很常见,而且往往没人记得还有这么一块。 ## 怎么判断一个缺失是真缺,还是只是没渲染? 这是整篇文章最实用的一节,因为两种情况的修法完全不同。 有一整类抓取器规则不同,Google不看robots.txt的那类抓取器 (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)值得单独了解。 ## 三步判断法 第一步,把页面用命令行抓下来,看可读正文有多少。这一步决定了后面所有检查有没有意义。如果正文接近零,别的都不用查了,先解决输出问题。 抓取和渲染分几步,看懂才知道哪里丢内容 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)把流程拆开了讲。 第二步,如果正文正常,那就在字节里找那个具体的东西。找按钮的名字,找图片的alt,找main标签。找得到就是有,找不到就是没有,不需要争论。 第三步,只有在字节里找不到、但你确信页面上有的时候,才需要区分"是不是渲染后才有"。这时候打开浏览器的开发者工具,在元素面板里找无障碍相关的那个窗格,把整页的无障碍树打开看,重点看这个节点在树上叫什么。 ## 第三步的三种结果 第三步会得到三种结果,对应三种完全不同的处理方式。 调试这类问题的工具链,JSON格式化与结构化数据调试 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)是常用的一环。 第一种,树上有名字。那说明脚本在运行时补上了。这种情况下,问题只对不执行脚本的读者存在,要不要处理取决于那类读者对你重不重要。这是唯一一种可以"知情之后选择不处理"的情况。 第二种,树上也没有名字。那就是确凿的缺陷,跟渲染没关系,读屏软件用户此刻正在遭遇它。这种要修,而且优先级不低。 第三种最有意思:树上有名字,但名字是错的。比如按钮上明明写着"加入购物车",树上的名字却是"button-4",或者是一串组件生成的编号。这种情况多半是有人给元素加了aria-label,而那个值是从代码里带出来的、不是给人看的。这一类比没有名字更糟——没有名字至少还能靠周围的上下文猜,一个错误的名字会把猜的路也堵死。 ## 两种情况的修法是相反的 如果字节里就没有,那是内容交付问题,要动的是渲染方式——服务端渲染、预渲染、或者至少给一份能读的降级内容。这件事的成本按项目算,不按页面算。 JS渲染抓不到该从哪查起,这几种情况的排查顺序 (https://zhangwenbao.com/javascript-rendering-seo-csr-ssr-debugging.html)是现成的路线。 如果字节里有、渲染后反而没了,那是脚本把它改坏了,要动的是那段脚本。这件事的成本按缺陷算,通常改一处就好。 把这两件事搞混,最典型的后果是拿改缺陷的力气去解决交付问题,改了三个月发现指标一动不动。 反过来搞混也很常见,而且更浪费:把一个几行代码就能修的缺陷,当成架构问题上报,于是它进了一个需要评审、需要排期、需要跨部门协调的流程,半年之后还在待办列表里。判断成本高低的第一个动作,就是先分清它是哪一类。 ## 一个具体的分诊例子 假设你发现商品页上的"加入购物车"按钮,在抓下来的HTML里找不到名字。接下来怎么走? 分诊之后怎么排优先级,从AI爬虫到无障碍的42步实战 (https://zhangwenbao.com/technical-seo-audit-five-new-layers-ai-era.html)给了一份完整清单。 先看同一份HTML里有没有商品名和价格。如果有,说明这一页整体是服务端输出的,只有这个按钮出了问题——那就是个组件缺陷,去找那个组件,加一个名字,改动量大概一行。 如果连商品名都找不到,那这个按钮没有名字只是表象,真正的问题是整页都没输出。这时候去改按钮组件是白费力气,因为改完之后那个按钮照样不在字节里。 同一个现象,同一句"按钮没名字",背后是两个成本差三个数量级的问题。区分它们只需要多看一眼旁边有没有商品名,十秒钟的事。这十秒钟省下来的力气,比这篇文章里任何一条建议都多。 ## 关于执行脚本这件事的现状 需要说清楚一个事实边界:主流搜索引擎的抓取程序是会执行脚本的,这一点官方文档写得很明确,只是执行有排队、有资源上限,不保证每次都完整。而当下大量新出现的读取程序——各类AI训练与检索用的抓取器——多数不执行脚本,只读原始字节。 要不要拦这些程序,robots加UA加WAF的三层选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)给了决策路径。 读你页面的名单变了多少,AI爬虫抓取量已超Googlebot 3.6倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)有实测数据。 所以同一个空壳首页,对不同读者是两个完全不同的结论。这不是"要不要为SEO做服务端渲染"的老问题,这是"你的读者名单变长了"的新问题。名单变长的部分,恰好都是不执行脚本的那种。 这个变化的时间点很值得注意。服务端渲染这个话题在2016年前后吵得最凶,那时候的结论大致是"搜索引擎已经能渲染了,不必过度紧张",这个结论在当时是对的。之后这件事就淡出了很多团队的检查清单,新一批前端工程师入行时,它已经不是一个需要讨论的问题了。 结论没变,前提变了。当年那个结论成立的前提是"读你页面的只有会渲染的搜索引擎",这个前提在最近两年悄悄失效了,而失效的过程没有任何一次公告。这就是为什么值得重新量一遍——不是因为出了新规则,是因为老结论的地基被换掉了。 ## 有个说法要澄清一下 经常听到一种说法:既然那些程序不执行脚本,那它们本来也读不好网页,不用太在意。 这个说法把因果搞反了。它们不执行脚本,不是因为技术做不到,是因为不划算。执行一整套前端脚本的成本,是纯读字节的几十倍,还要维护一整套浏览器环境。当抓取量以亿为单位的时候,这个差价决定了谁能活下来。 换句话说,这不是一个会随时间自动改善的问题。成本结构不变,行为就不会变。指望对方升级,比自己多输出一份HTML要难得多。 还有一种说法是"重要的内容它们会想办法拿到"。这个也不太站得住。对一个批量抓取的程序来说,判断哪一页重要本身就需要先读懂这一页,而读不懂的页面连进入这个判断的资格都没有。它不是把你排在后面,是根本没把你放进队列。 ## 怎么估自己站受影响的程度 不用猜,日志里有答案。把最近一个月的访问日志按用户代理串分组,把那些明确自报家门的抓取程序挑出来,看它们各自的请求量占比。 日志里怎么分类,8类UA实测与22周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)给了可照搬的方法。 然后做一个简单的判断:这些程序里,有多少是会执行脚本的。搜索引擎的主抓取程序会,绝大多数其他的不会。把不会的那部分请求量加起来,除以总抓取量,就是你这个空壳问题的实际影响面。 这个比例在不同行业差别很大。内容型站点通常高,因为它们的文字更容易被这类程序盯上;商品型站点低一些,但也在涨。关键是这个数字你自己算得出来,不需要相信任何人的估计。 ## 如果短期内改不了渲染方式 把整站改成服务端渲染,是一个按季度算的工程,很多团队短期内确实做不了。这种情况下有几件成本低得多的事可以先做,效果不如根治,但比什么都不做强很多。 预渲染这条路怎么走,Speculation Rules API的机制实战 (https://zhangwenbao.com/speculation-rules-api-prerender-prefetch-instant-navigation.html)是相邻的技术选项。 第一件,把最重要的那几类页面单独做预渲染。首页、主要分类页、销量最高的那批商品页,加起来可能就几百个地址。预渲染只需要在构建时把这些页面跑一遍存成静态文件,不需要改运行时架构。这件事通常是一两周的量。 第二件,用noscript留一份精简正文。这个做法有点土,但它诚实、有效、几乎零成本。里面不需要放完整页面,放清楚"这一页是什么、有哪些主要内容、去哪能看到"就够了。本次样本里只有1个空壳站这么做了,说明这条路基本没人走——不是因为不好用,是因为没人想起来。 第三件,检查一下你的站点地图和结构化数据有没有把这些空壳页当成正常页在推。如果一个页面在字节层面是空的,把它推给更多程序去抓,只是让更多程序确认了它是空的。先把内容补上,再谈推广。 这三件事有个共同点:都不需要动前端架构,都可以由做技术优化的人独立推动。在等待架构排期的那几个月里,它们能把损失控制在一个可接受的范围内。 ## 这套自查要花多久,从哪一步开始? 把上面所有东西收成一个能在一个下午跑完的清单。 批量打开页面手工看一眼,网址批量打开工具的实测 (https://zhangwenbao.com/batch-url-opener-popup-blocking-manual-audit-workflow-guide.html)说明了它能和不能做什么。 ## 第一个动作:三分钟 用命令行抓一次你自己的首页,把标签剥掉数字符。如果这个数小于1200,后面的检查全部暂停,先去开会讨论渲染方式。 把HTML转成可读文本,Markdown与HTML双向转换 (https://zhangwenbao.com/markdown-converter-html-bidirectional-conversion-guide.html)也能顺手完成这一步。 如果这个数正常,顺手再抓一个商品页和一个分类页。首页往往是全站最特殊的一页,别拿它代表全站。这个教训保哥在别的检查里反复吃过。 ## 第二个动作:十分钟 在HTML里数四样东西:有没有main标签,h标签的数字序列长什么样,有多少img没有alt属性,有多少input拿不到标签。 同一趟还能顺手查结构化数据,一次扒清五种格式的字段缺漏 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)省一遍功夫。 这四样都能用最朴素的方式数出来,不需要任何工具。数出来之后跟本文的数字对一下,下面这张表可以直接当参照: 检查项 | 本次110个站的水平 | 你比它差就该做 | 四个地标区域齐全 | 69.1%的站做到了 | 缺哪个补哪个,半小时 | 有main标签 | 85.5%的站做到了 | 优先补,成本最低 | 首页至少有一张图缺alt属性 | 32.7%的站中招 | 按模板批量补 | 首页至少有一个输入框无标签 | 40.0%的站中招 | 查组件,一处全好 | 首页至少有一个按钮无名字 | 37.3%的站中招 | 查图标类组件 | 标题层级出现跳级 | 45.5%的站中招 | 危害小,改版时顺手 | 你比这几个数好,说明这一项不是你的优先项;比它差,说明这是个能低成本拉平的地方。注意这批站是行业里做得比较认真的一批,所以这些数字更像是及格线而不是优秀线。 ## 第三个动作:半小时 打开浏览器开发者工具,把首页的完整无障碍树导出来看一遍。重点看四个位置:主要的行动按钮有没有描述性的名字,导航有没有被包在导航地标里,主内容区在树上是不是可读的文本,以及有没有大块内容被标成了隐藏。 想边改边看效果,三栏实时预览的HTML编辑器 (https://zhangwenbao.com/html-editor-html-css-js-live-preview-guide.html)比来回刷新快得多。 这一步是唯一需要真浏览器的,也是唯一能看到"渲染后真相"的。前两步可以排除大部分问题,这一步用来确认剩下的。 看的时候有个小技巧:不要顺着树从上往下读,那样很容易被结构带着走。换个方式——先在页面上挑五个你最不想让用户点错的元素,比如加入购物车、结算、提交、切换规格、关闭弹窗,然后逐个到树上去找它们叫什么。五个都对,这一页基本没大问题;有一个叫不出名字,那多半是一整类组件的问题。 ## 如果要把它变成常态检查 上面三个动作是一次性的排查,做完能知道现状。要让它不再退化,得挑一两项做成自动的。 常态检查还该包含链接健康,改版后全站404与重定向链的排查 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)是配套项。 推荐做成自动的只有两项:关键页面的可读正文字符数,和关键控件的可访问名。前者用一个定时抓取加字符统计就够,掉到阈值以下告警。后者需要在自动化测试里加一条断言,把首页的无障碍树快照存下来,之后每次改动跟它比一下,有节点丢了名字就报出来。 其余各项不建议做成自动检查。它们的误报率高到会让人很快学会忽略告警,而一个被忽略的告警比没有告警更糟——它会让所有人以为这件事已经被监控了。 ## 一个容易被跳过的动作:换个身份再抓一次 上面三个动作都是用普通浏览器的身份去请求的。有一件事值得顺手做:把请求的身份换成一个抓取程序的标识,再抓一次,看两次拿到的字节是不是一样。 这个动作的成本几乎为零,就是加一个参数。但它能查出一类前三步完全看不见的问题:你的服务器或者前面那层防护,可能对不同身份给出了不同的答案。本次实测里确实有站是这样,而且差异大到不可能是偶然。 如果两次结果不一样,接下来要判断的是哪一边不对。给浏览器的多、给程序的少,那是内容没交出去;反过来给程序的多、给浏览器的少,那通常是某种为抓取做的特殊处理,风险更大一些。 这件事跟本文主题只沾了一半的边——它查的不是"东西在不在",而是"东西有没有被送到",那是另一层问题。但既然抓都抓了,多抓一次几乎不费什么事,顺手排除掉一整类可能性。 ## 把这次的数字存下来 做完前三步,一定要把结果存成一份带日期的记录,哪怕就是一个表格文件。这一步经常被跳过,但它决定了这次排查有没有长期价值。 记录要带时间,从sitemap的lastmod到结构化数据日期 (https://zhangwenbao.com/timestamp-converter-unix-epoch-sitemap-lastmod-guide.html)都得靠时间戳对齐。 原因很实际:这些指标的绝对值意义有限,变化才有意义。你的首页正文有5800个字符,这个数好不好?不知道。但如果三个月后变成了1200,那就是一件必须立刻查清楚的事,而且几乎可以肯定跟某次改版有关。 存的时候记得连口径一起存——用了什么用户代理串、哪一天抓的、剥标签的规则是什么。半年后重跑一次,如果口径变了,两次的数字就没法比,这份记录也就白存了。保哥吃过这个亏,翻出一份两年前的审计表,数字都在,但当时怎么算的一个字都没写,只能从头再来。 还有一个小建议:把行业参照值也记在同一份表里。这样下次看的时候,不用再去翻文章找那几个百分比。 ## 把结果说给不同的人听 这套检查跑完,会得到三堆完全不同性质的问题,而它们需要说给三拨人听,说法还不能一样。 沟通方式也是能力的一部分,给SEO人的个人审计五步法 (https://zhangwenbao.com/seo-health-zhang-xuefeng-insight.html)里有相关的提醒。 正文输出问题要说给做技术决策的人听,因为它涉及架构选择和排期,说法应该是"我们有多少页面对不执行脚本的读者是空白的,这些读者占抓取量的多少"。不要说"我们没做服务端渲染",那是手段不是问题。 组件层的问题——按钮名字、表单标签——要说给做前端的人听,说法应该是具体的组件名和具体的改法。这类问题的沟通成本最低,因为它们是明确的、可验证的、改完立刻能确认的。 内容层的问题——图片替代文本写得对不对——要说给做内容和设计的人听,而且要给判据不要给清单。给清单会得到一堆敷衍的填空,给判据才会得到能用的文字。 ## 不建议做的事 不建议一上来就跑一个综合评分工具,然后照着分数改。这类工具会把上面说的三层问题混在一起给一个总分,而三层的修法完全不同、成本差几个数量级。先分类,再打分,顺序反了会浪费很多力气。 综合评分工具的局限,AMP验证器的八大类规则 (https://zhangwenbao.com/amp-validator-mobile-amp-html-compliance-guide.html)是个可对照的例子。 也不建议把这些检查项变成一张需要人工填写的上线检查表。人工检查表的寿命通常是三个月,之后它会变成一个所有人都勾但没人看的仪式。能自动检测的就自动检测,检测不了的就写进组件默认值,两条路都走不通的才写进检查表。本文这些项里,前两类能覆盖绝大部分。 ## 把无障碍当成SEO手段,这条线该画在哪 最后必须说一段立场,因为前面全篇都在用"机器读不读得到"当理由,这个理由本身是有边界的。 动机和后果要分开谈,AI写的内容会被惩罚吗 (https://zhangwenbao.com/ai-generated-content-google-penalty-myth.html)也是在澄清因果。 ## 顺序不能颠倒 无障碍这套东西的存在理由是残障人士的使用权,这一点跟搜索、跟AI、跟流量都没关系。它在很多国家和地区是法律要求,在所有地方都是基本的产品责任。 无障碍不止网页,PDF的标签结构与阅读顺序 (https://zhangwenbao.com/pdf-accessibility-tagged-reading-order-pdfa-archiving-compliance.html)是同一套思路在另一种格式上。 因为机器读得到所以去做无障碍,这个动机会在某一天失效——某天机器变强了,能靠视觉理解页面了,按这个逻辑就该不做了。而那一天到来的时候,需要读屏软件的人一个都没有减少。 ## 那这篇文章的立场是什么 是这样:这些检查项你本来就该做,做了之后顺带会让机器也读得懂。顺序是"做对了,所以机器也能读",不是"机器要读,所以做一下"。 把内容当结构来生产,内容工程这套新手艺 (https://zhangwenbao.com/content-engineering-structured-content-ai-search.html)说的是流程而不是清单。 实际操作上这两个顺序的产出会不一样。按第一个顺序做,会把整个流程改掉,组件规范里加上标签要求,以后新写的页面自动就是对的。按第二个顺序做,会挑几个重要页面手工补一遍,三个月后新上的页面又是老样子。 差别的根源在于覆盖范围。为机器做,只需要覆盖那些机器会去的页面;为人做,得覆盖所有页面。前者的终点是一份清单,后者的终点是一套默认值。而只有默认值才不会退化。 ## 顺便说一个容易被忽略的事实 需要无障碍支持的人,比多数人想象的多得多,而且不只是完全失明的用户。 看不见的流失最难发现,那排标签让用户没法把两块信息放进同一屏 (https://zhangwenbao.com/product-page-horizontal-tabs-adjacency-requirement.html)也是这一类。 视力低下需要放大、色觉有差异需要靠文字而非颜色区分、手部不便只能用键盘、在嘈杂环境里只能看不能听、临时性的比如手上打着石膏或者抱着孩子只能单手操作——这些人在任何一个电商站的日活里都占着相当可观的一块,而且他们中的绝大多数不会告诉你他们遇到了困难,他们只会离开。 一个没有名字的按钮不会产生任何一条报错,也不会出现在任何一张转化漏斗的报表上。它只会表现为某一小撮用户在那一步的流失率略高一点,而那一点会被淹没在噪声里。这可能是本文所有内容里,唯一一条跟机器完全无关、但比所有机器相关的理由都更该被听见的。 ## 一个现实的建议 如果你在一个把商业指标看得很重的团队里,很难只靠"这是应该做的"推动这件事,那么本文这些数字可以当成一个补充论据,不是唯一论据。用它去争取排期,别用它去定义目标。 排期时需要一份完整的说法,GEO从AI搜索到结构化数据的实施策略 (https://zhangwenbao.com/geo-strategy.html)可以当框架用。 这两者的区别在验收的时候会显出来。用它定义目标,验收标准会变成"无名按钮数降到多少以下",团队会去做那些数字上最划算的改动,而真正影响用户的那几个控件可能一个都没动。用它争取排期,验收标准还是"这些控件能不能被读屏软件正常使用",数字只是排期时的说服材料。 如果站点规模大,或者所在行业有明确的无障碍法规要求,请找专业的无障碍顾问,别拿这篇文章当验收标准。这篇文章量的只是那些能从字节里看出来的部分,它离一次真正的无障碍审计还差很远——真正的审计要看键盘能不能走通全流程、对比度够不够、动效能不能关掉、读屏软件实际念出来是什么,这些都不是抓一次HTML能回答的。 ## 最后回到那个五兆的页面 写到这里,可以把开头那个例子的完整含义说清楚了。 把地基打对,实体主页与品牌身份的搭法 (https://zhangwenbao.com/entity-home-seo-ai-brand-guide-html.html)是这套思路的另一面。 那个站传了两兆多字节,一个字都读不出来,同时它写了标题、写了描述、放了结构化数据。这不是一个不专业的站,恰恰相反,它每一样单独看都做得挺规范。 问题出在没有人问过那个最笨的问题:我们发出去的东西里,到底有没有字。所有人都在检查各自负责的那一项,没有人负责检查这些项加起来是不是构成了一个能读的页面。 这篇文章从头到尾其实只在推荐一个动作:抓一次,剥掉标签,数一下。三分钟,不需要工具,不需要权限,不需要跟任何人商量。三分钟之后你会知道,接下来该讨论的是哪一层的问题。 ## 常见问题解答 ## 我的站是单页应用,是不是一定有问题? 不一定,关键看有没有做服务端渲染或者预渲染。单页应用只是描述前端架构,不决定输出什么字节。本次样本里跑单页框架但正常输出HTML的站不少,也有用传统模板引擎却把内容全塞进脚本的。架构名词说明不了任何事,字节能。判断方法只有一个:抓一次,数字符。这个动作三分钟,比在群里讨论半小时有用得多。 PWA也有类似问题,8类抓取与索引影响的实战 (https://zhangwenbao.com/pwa-seo-service-worker-crawl-indexing-impact-mechanism.html)可以对照判断。 ## Google能渲染脚本,那我是不是不用管? 如果你的目标只有搜索引擎,风险确实小一些,但也不是零——官方明确说过渲染有排队、有资源限制,不保证每一页都能完整执行。页面越多、更新越频繁的站,排到的概率越不确定。 渲染要排队,抓取预算优化的12项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)解释了资源是怎么分配的。 而现在来读你页面的不止搜索引擎,各类AI检索与训练用的抓取器大多不执行脚本。所以这个问题的答案在这两年变了:以前是"影响有限",现在是"影响取决于你在乎哪些读者"。要把这个问题变成一个可以决策的问题,去日志里数一下不执行脚本的那类请求占多少。 ## 那我把内容塞进结构化数据是不是就行了? 不行,这是本次数据里最明显的一个误区。有几个站的结构化数据比正文长几十倍,看起来很努力,但结构化数据的作用是描述实体和关系,不是承载正文。它是目录,不是书。 结构化数据该怎么配合,Schema的落地方式与常见避坑 (https://zhangwenbao.com/seo-schema-guide.html)说得比较清楚。 而且这么做在规范上是有风险的:结构化数据描述的内容通常要求在页面上真实可见。当结构化数据里写着商品名和价格,同一份字节里的正文却是空的,这个对应关系严格说是断的。实际执行中很少有人因此被处理,但把它当成长期依赖的做法并不稳妥。 ## alt到底该写多长? 写到"这张图去掉之后你需要补的那句话"为止,通常十几个到三十几个字符。太短的问题是没信息量,比如写"图片"、"banner"、"product";太长的问题是变成了正文,那些话该写在正文里。 文字进图片这件事也有坑,OG图生成器把emoji切成方块 (https://zhangwenbao.com/og-image-maker-linebreak-surrogate-square-crop-guide.html)是个具体教训。 装饰性的图直接写空字符串,这是明确表态,不是偷懒。本次数据里24.1%的图是空alt,这个比例本身很健康。需要警惕的是另一种情况:商品主图空着、旁边的装饰角标反而写了字,那是信息层次被写反了。 ## placeholder能不能代替label? 不能。placeholder在用户开始输入的那一刻就消失了,它是提示不是标签。用户填到第三个字段忘了这一格填什么,只能全部删掉重看一眼——这个体验问题跟机器读不读得到无关,它本身就是个缺陷。 这类细节的收益常被低估,被低估的9个反直觉杠杆 (https://zhangwenbao.com/counterintuitive-ui-design-conversion-levers.html)收集了不少类似的。 如果设计上确实不想显示标签文字,正确做法是保留label但在视觉上隐藏它,或者给输入框加aria-label。本次样本里有好几个站是整套表单组件全部无标签,ritual.com的22个、mejuri.com的14个、allbirds.com的13个都是这种形态。整齐的全军覆没说明它是组件层面的选择,改一处就能全好。 ## 首页测完了,其他页面要不要都测? 不用全测,但一定要测不同类型的各一个:商品页、分类页、内容页各取一个。首页在很多站上是最特殊的一页,用的模板跟别的页面完全不同,往往还是改版时最先被重做的那一个。 分类页最容易被忽略,用户点进来那一屏没有一个字写着他在哪 (https://zhangwenbao.com/category-navigation-scope-custody.html)就是实例。 更值得测的是那些"不太起眼但流量不小"的页面:搜索结果页、筛选后的分类页、专题活动页。这几类最容易由不同的人在不同的时期用不同的方式做出来,也最容易游离在所有检查流程之外。 ## 为什么无名按钮的比例只有8.2%,但受影响的站有37%? 因为分母不同。8.2%是按按钮个数算的,37.3%是按站算的——只要一个站有一个无名按钮就计入。这两个数不矛盾,它们回答的是两个问题:整体质量怎么样,和这个问题普不普遍。 口径这件事在别处也一样,13种Schema类型该怎么选 (https://zhangwenbao.com/schema-generator-jsonld-13-types-guide.html)同样要先分清对象。 用哪个口径取决于你要干什么。做横向对比、判断一件事值不值得关注,看站的口径;给自己的站排改进优先级,看个数的口径。本文所有指标都同时给了两个口径,就是因为这两个问题经常被混在一起问。 ## svg没名字算不算错? 要看它在哪。如果外面包着一个有名字的按钮或者链接,那这个svg本来就该被标成装饰性的,没名字是对的,甚至可以说是正确做法——图标和它所在的控件不该各有一个名字,那会被读两遍。 图形处理的基本功,8种按比例缩放的前端方案 (https://zhangwenbao.com/image-scaling-code.html)是相邻的实务。 如果它是唯一的内容、外层也没名字,那就是硬伤。本次数据把这两类分开数过:前一类数量很大(3906个)但多数无害,后一类264条是确凿的问题。汇报的时候只报后一类,报前一类会被技术同事当场问倒,而且他们是对的。 ## 这套检查多久做一次? 触发式比定期式实用。换模板、上新的组件库、大改导航、迁移前端框架,这四件事之后各做一次。它们是结构问题最容易被批量引入的时机——一次组件改动能同时影响几十个页面上的几百个元素。 配置每次都通过不代表没事,每8次抓取有1次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同类的隐形退化。 如果一定要个周期,配合改版节奏走就行,为它单独排期通常排不上。更省事的办法是把最粗的那一项——正文字符数——做成一个定时任务,掉到线以下就告警,剩下的靠触发。 ## 团队里这件事该归谁? 这是本次数据背后最真实的一个问题。标题和描述归做搜索的人,渲染方式归做前端的人,两边各自都做得对,中间那条缝没人负责。本次那张头部信息完备度的表,实际上就是这条缝的照片。 设计侧也有对应的动作点,从IA到Figma落地的7个协作动作 (https://zhangwenbao.com/web-designer-seo-collaboration-7-actions-ia-figma-typography-image-cta.html)能补上另一半。 比较务实的做法是把几条检查写进组件规范和自动化检测,让它变成默认行为,而不是靠某个人记得去查。靠人记得的事,撑不过一次人员变动。 ## 我该先修哪一项? 按成本和影响排:正文输出问题排第一,它决定别的检查有没有意义;表单标签排第二,因为它一般是组件级的、改一处全好,而且直接影响真实用户;图片alt排第三,工作量大但可以分批做,而且可以跟内容更新一起做;标题层级和地标排最后,它们的实际危害最小,通常在改版时顺手就修了。 排优先级要看影响面,URL结构与slug的9个细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)也是这么权衡的。 如果只有半天时间,就做两件事:给搜索框加标签,给页面加main标签。这两件加起来不到一小时,覆盖的是所有页面。 ## 权威参考资料 ## favicon要上广告位,211个站有152个拿不出图标 - URL:https://zhangwenbao.com/favicon-site-name-platform-picks-one.html - 分类:技术SEO - 发布:2026-08-13 | 更新:2026-08-13 - 摘要:广告位开始显示广告主的名称和图标,可这两样东西广告后台里都没有输入框。系统去你的站上取,取不到就用默认图标和你的域名顶上。 - 关键词:网站图标,Google Ads,结构化数据,站点名称 > **TLDR**:摘要:把211个国际化电商域名的图标全部抓了一遍。兜底路径 /favicon.ico只有59个能返回一张真图标,其余要么是空的,要么返回一整张网页——最夸张的一个返回了4.5 MB的HTML,状态码还是404。页面里主动声明图标的有133个站,平均每站声明3.4个,最多的声明了22个,而Google明说每个站只用一个。名字那一半同样乱:98个有三个以上名字来源的站里,只有22个的四个来源完全一致。 > 摘要:把211个国际化电商域名的图标全部抓了一遍。兜底路径 /favicon.ico只有59个能返回一张真图标,其余要么是空的,要么返回一整张网页——最夸张的一个返回了4.5 MB的HTML,状态码还是404。页面里主动声明图标的有133个站,平均每站声明3.4个,最多的声明了22个,而Google明说每个站只用一个。名字那一半同样乱:98个有三个以上名字来源的站里,只有22个的四个来源完全一致。 2026年8月11日,有人拍到Google搜索结果里的赞助位在做一个新测试:广告上方多出一条摘要行,里面放着广告主的名称和它的网站图标。同一周,本地包和Discover的广告位上也出现了新的标识。 这类变化的共同点是,展示层多出来的东西不是你填的,是系统替你取的。你在广告后台里找不到一个字段叫“广告主名称”,也找不到一个上传入口叫“图标”。它去你的站上拿。 那就有一个很自然的问题:它能拿到吗,拿到的是哪一个。保哥把手上那批国际化电商站的图标和名字全量抓了一遍,答案比预想的难看不少。光是那个最基本的兜底路径,211个域名里就有152个拿不到一张能用的图。 这篇文章的前半段讲机制:这类“平台替你决定”的规则长什么样、你手上还剩下什么牌。后半段是实测:图标那一半和名字那一半各自出了什么问题,以及一份能在半小时内跑完的收敛清单。 ## 广告位上多出来的那一行是什么? 先把这次变化本身说清楚,因为它决定了后面所有排查的优先级。 广告产品的形态变化通常先在小范围测试,Google砍掉Lead Form五万美元门槛的机会 (https://zhangwenbao.com/google-ads-lead-form-50k-threshold-removed.html)是另一次改动。 ## 被拍到的那个测试 被拍到的那个测试形态 (https://www.seroundtable.com/google-ads-sponsored-results-ad-summary-header-41851.html)是:在赞助结果的上方,加一条摘要行,左边是广告主的网站图标,右边是广告主的名称。它看起来很像自然结果里早就有的那一行——搜索结果的标题上方,一直有站点名称加图标的组合。 广告位的展示形态变了,出价目标那套账并不会跟着变,目标ROAS到底该定多少的四步算法 (https://zhangwenbao.com/google-ads-target-roas-cpa-break-even.html)还是老规矩。 换句话说,广告位正在向自然结果的展示形态靠拢。这件事对投放的直接影响是,你的品牌识别度第一次开始影响广告位的点击率,而这部分识别度不是由你的广告文案决定的,是由你的站决定的。 对投放团队来说这是个陌生的位置。以往广告位上的每一个像素都能在后台找到对应的输入框:标题、描述、显示网址、附加信息、素材。这条摘要行是第一个例外——它长在广告位上,配置却不在广告后台里。 ## 为什么这个测试值得当回事 单看一次界面测试,确实没必要紧张,Google每年做几百个这样的试验,多数不会全量。但这一条有两个特别之处。 上一篇量的是同一批站的名字字段,商家名称禁令当尺子量出来的那份结果 (https://zhangwenbao.com/business-name-single-form-structured-data-audit.html)可以接着这一篇一起看。 第一,它复用的是已经成熟的能力。搜索结果里的图标行和站点名称行早就上线好几年了,机制稳定、覆盖面完整。把一个成熟能力搬到另一个位置,落地阻力很小。 第二,它改变的是归属感。广告位上出现你的图标和名字,等于把“这是谁投的”这件事前置了。对认知度高的品牌是加分,对认知度低的是减分,而对图标或名字取不到的站,是直接的空白。 ## 同一周还有另一条相关变化 本地包和Discover的广告位上也开始出现新的标识行 (https://www.seroundtable.com/google-ads-ai-labels-local-pack-discover-41841.html)。这两条放在一起看,指向同一个趋势:展示层的信息密度在增加,而新增的那部分信息全部来自平台自己的抓取,不来自你的投放设置。 展示层多出来的文案同样来自抓取,广告系列自动升级后文案原料全在落地页上 (https://zhangwenbao.com/ad-landing-page-copy-source-robots-template.html)讲的是同一个机制。 这就是为什么值得现在就排查一遍。等到这个测试全量上线,你再去改图标,中间还隔着几天到几周的重新抓取时间。这类事情没法临时抱佛脚,只能提前把料备好。 ## 它跟自然结果里的那一行是同一套数据吗 官方没有明说,但从形态判断,大概率共用同一套。自然结果里的图标行,走的是搜索的图标抓取机制;站点名称行,走的是站点名称系统。两者都只认主机名,也都只取一个结果。 自然结果与广告位共用的是同一份身份数据,实体主页怎么搭才算把品牌身份立住 (https://zhangwenbao.com/entity-home-seo-ai-brand-guide-html.html)里有这套数据的全貌。 这个判断有一个很实际的推论:你为自然结果做的图标和名字优化,会顺带影响广告位;反过来也一样。所以这不是一件属于投放团队或者SEO团队某一方的活,它属于谁维护站点的模板,谁就得管。 这个归属问题在实际团队里挺麻烦的。投放的人看到广告位出了问题,第一反应是去广告后台找原因,找不到就报给平台;做SEO的人不看广告位,不会主动去查。结果就是一个明明五分钟能修的问题,在两个团队之间来回传了两周。 保哥去过一个做家用医疗器械的客户,他们的搜索结果里一直显示一个灰色的默认图标,投放和SEO各自查了一轮都说不归自己管。最后是前端同学随口一句“那个文件上次发版好像被清了”,问题当场定位。展示层的问题,根子往往在构建流程上。 ## 为什么这类事你在后台找不到开关? 找不到开关,不是功能没上线,是它压根不以开关的形式存在。这一类规则值得单独归一类。 后台里找不到的设置往往是被合并进了别处,本地服务广告并进Performance Max之后 (https://zhangwenbao.com/local-services-ads-google-ads-performance-max.html)就是一次入口消失。 ## 平台介入的第二种方式 上一篇讲过第一种:禁止型,平台立规矩,你只能删,违反了要挨罚。这一篇讲第二种,可以叫代劳型——平台自己算出一个结果并展示,你只能影响输入,不能指定输出。 平台代劳的比例这两年明显在升高,GEO到底怎么落地的实施策略 (https://zhangwenbao.com/geo-strategy.html)里对这个趋势有更完整的判断。 类型 | 谁动手 | 你能做的动作 | 做过头的表现 | 禁止型 | 平台立规矩,你只能删 | 把多出来的部分拿掉 | 当成优化反复打磨 | 代劳型 | 平台自己算,你只能摆原料 | 把候选收敛到一个 | 满后台找开关 | 亲自型 | 只有你能做,平台只建议 | 全部,也没人替你兜底 | 等平台来提醒你 | ## 三十秒的判据 判断一件事是不是代劳型,只需要问一个问题:后台里有没有一个字段,能把这个结果直接写死。 官方措辞的细微差别决定了规则的效力,robots规则的星号对某些爬虫无效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)就是一次典型的误读。 有,那就不是代劳型,照着填就行。没有,那就是——而且你会发现官方文档在描述这类功能时,措辞非常一致。站点名称那份文档的原话是“要表明你的站点名称偏好,请在首页添加WebSite结构化数据”,用的词是偏好。图标那份文档 (https://developers.google.com/search/docs/appearance/favicon-in-search)说的是“把图标链接添加到首页”,然后紧跟一句“搜索只按主机名定义一个站点,也只支持一个图标”。 偏好、支持、考虑——这三个词一出现,基本可以确定你面对的是一台会自己做决定的机器。 ## 代劳型的投入曲线是钝的 禁止型是阶跃:过线之前收益为零,过线之后不再增长。代劳型不一样,它是一条很快就平掉的曲线。 标题被系统重写也是代劳型的典型,Google用AI重写标题的改写率与应对 (https://zhangwenbao.com/google-ai-headline-rewrite-seo.html)给出了具体比例。 前半段很陡:从“候选一团乱”到“候选收敛成一个”,系统挑错的概率大幅下降。后半段几乎是平的:你把那一个候选做得再精致,也改变不了它有可能被拒绝、被替换、被截断的事实。 所以这一类事情的正确姿势是把候选收敛到一个,确认那一个是好的,然后停手。本次实测里出问题的站,绝大多数不是候选做得不够好,是候选太多、且其中一部分是坏的。 ## 代劳型和禁止型的处理顺序不一样 禁止型规则要先做,因为它的下行是断崖式的。代劳型排第二,理由是它的收益虽然有上限,但相当确定:候选收敛之后,系统挑对的概率立刻上去,不需要等算法更新,也不需要积累权重。 短平快的活该排在前面,新网站前十二周的技术地基清单 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)里的排期逻辑就是这么定的。 还有一个实际考虑:代劳型的活通常很短。本文后面那张核对表,一个人一下午能把一个站跑完。一下午能做完、收益确定、不需要跨部门审批的活,在任何排期里都该排在前面。 ## 怎么判断自己是不是已经收敛了 有个很省事的自测:把你觉得系统会用的那个答案写下来,然后去源码里找证据。如果你能指着某一行说“就是这个”,那你收敛了;如果你得说“大概是这几个里的一个”,那你没有。 能不能指着一行说就是它,是个很好的自测,Schema对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)里也用了同一种验证方式。 本次样本里七成七的站属于后者。不是他们填错了,是他们填了好几个,然后默认系统会挑对那个。 ## Google对图标的硬要求一共有几条? 要判断一个站的图标能不能被取到,得先知道判据。官方文档写得比大多数人以为的短。 官方要求逐条摆出来才好逐条核对,Shopify博客多级面包屑的三种方案 (https://zhangwenbao.com/shopify-blog-breadcrumb.html)也是按这个结构写的。 ## 逐条摆出来 要求 | 官方原话的意思 | 常见误解 | 形状 | 必须是正方形,长宽比1:1 | 以为长方形也行 | 下限尺寸 | 至少8×8像素 | 以为有很高的门槛 | 推荐尺寸 | 建议大于48×48 | 误传成必须是48的倍数 | 格式 | 任何有效的图标格式都支持 | 以为只认ICO | 位置 | 链接写在首页的head里 | 以为放根目录就够 | 数量 | 按主机名定义站点,只支持一个图标 | 以为声明越多越保险 | rel取值 | icon、shortcut icon、apple-touch-icon及其precomposed变体 | 以为随便写 | 抓取周期 | 几天到几周不等 | 以为改完立刻生效 | 内容 | 不当内容会被替换成默认图标 | 很少有人知道这条 | 图标和名字都属于展示层的结构化声明,结构化数据怎么配合SEO落地的完整指南 (https://zhangwenbao.com/seo-schema-guide.html)里有整套字段的配法。 ## 最容易被误传的那一条 网上流传最广的一个说法是“图标必须是48的倍数”。查了原文,这条不成立。原文写的是必须是正方形、至少8×8,然后建议使用大于48×48的图标以获得更好的效果。 被广泛转述的数字往往对不上原文,最佳实践清单里九条查得到出处八条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)就是一次系统核对。 这个区别很重要,因为它把两件事分开了:一条是硬门槛(正方形、8×8),不满足就用不了;一条是效果建议(大于48×48),不满足只是不够清晰。前者决定有没有,后者决定好不好看。 顺带说一句,保哥在动手之前也以为是48的倍数,是查原文的时候才发现记错了。这类被广泛转述的“硬要求”,动手前一定要回原文核一遍。因为你的整套判据都会建立在它上面,判据错了,后面所有数字都得推翻。 这次幸好是在写代码之前查的。如果按48倍数那个口径跑完,得出的结论会是“128个站里只有59个合格”,一个听起来很惊人、实际上完全错误的数字。误传的判据不会让你的数据变脏,它会让你的数据变得毫无意义——每一条记录都算对了,只是拿错了尺子。 这一类风险有个共同特征:它发生在动手之前,所有事后检查都抓不到。你可以复查代码、复查样本、复查统计口径,但如果最初那条规则记错了,这些复查一次都不会亮红灯。唯一的防线是回原文。 ## 顺手核了另外两条流传的说法 既然回了原文,就把另外两条常听到的说法一起核一遍。 核对原文之外也可以借工具看别人怎么配,十款网站技术栈检测扩展的实测对比 (https://zhangwenbao.com/seo-website-technology-stack.html)里有能直接看head的。 一条是“图标必须是ICO格式”。原文说的是任何有效的图标格式都受支持,并给了一个格式清单的外部链接。所以PNG、SVG、GIF都行。本次样本里PNG占了345个,是绝对主力,ICO只有41个——如果这条传言是真的,那市面上绝大多数站的图标都该是无效的,显然不是。 另一条是“图标必须放在根目录”。原文说的是把图标链接添加到首页的head里,并没有要求物理位置。本次样本里56个站的图标托管在站外主机上,包括大量电商平台自带的CDN,这个做法本身没有问题。 两条传言的共同来源大概是十几年前的浏览器行为——那时候确实只认根目录下的ICO。技术传言的保质期通常比技术本身短得多。 ## “只支持一个”这句话的分量 这是整份文档里最有信息量的一句,可惜它写得太轻描淡写。原文的意思是:搜索按主机名来定义一个站点,一个站点只支持一个图标。 按主机名收敛这件事在多语言场景下更明显,hreflang备用网址被当成规范页别名 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)是另一次收敛。 把它翻译成人话:不管你在页面里声明了几个图标、多少种尺寸、多少种格式,最后被用的只有一个,而挑哪一个是系统的事。你能做的是让它的选择空间尽可能小,且每一个选项都不出错。 这句话还有一层含义容易被忽略:既然一个站只有一个图标,那么你没法给不同栏目、不同语言目录配不同的图标。整个主机名共用一个,这是一个比多数人以为的更强的约束。有些团队想给博客目录换个图标区分内容类型,这条路是不通的。 “按主机名定义站点”这半句也值得留意。它意味着www和裸域、主域和二级域,在这套机制里是不同的站——各自有各自的那一个图标。如果你的站有多个可访问的主机名,每一个都得单独准备。这一点在做多国站的时候特别容易漏:de.example.com和example.com是两个站,它们的图标是两回事。 ## 那条关于内容的规则很少有人知道 文档末尾还有一条:Google不会展示任何它认为不适宜的图标,包括色情内容和仇恨符号,遇到这类会替换成默认图标。 不做什么的清单常常藏在文档末尾,AI内容披露里那份不做什么的清单 (https://zhangwenbao.com/ai-usage-disclosure-negative-list.html)也是这么被翻出来的。 对正经品牌来说这条基本用不上,但它透露了一个信息:这套机制里存在一个审核环节,也就是说你的图标不是被机械地取走,它会被看一眼。这也解释了为什么抓取周期是几天到几周,而不是几小时。 ## 133个站声明了451个图标,可最后用得上几个? 知道了判据,就可以看实测了。先看声明这一层。 堆数量不解决问题,这在商品侧同样成立,用Performance Max给零流量商品再来一次机会 (https://zhangwenbao.com/zombie-sku-revival-performance-max.html)是另一种解法。 ## 声明数量的分布 170个可解析首页里,133个声明了图标,37个一个都没声明,占21.8%。声明的那133个站一共给出451个文件,平均每站3.4个。 声明越多越保险这个直觉在很多地方都不成立,Googlebot抓取2MB限制的八步优化 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)是另一个例子。 声明个数 | 站数 | 1个 | 71 | 2到4个 | 30 | 5到9个 | 19 | 10到14个 | 7 | 16个及以上 | 4 | 一多半的站只声明一个,这是最健康的做法。但另一头也很显眼:有两个站各声明了22个图标。22个文件,系统只用一个,剩下21个的唯一作用是给浏览器和移动端设备用——这本身没错,错的是很多团队以为多声明几个能提高被正确抓到的概率。 ## 那些rel值都是干什么的 451个声明按rel拆开,分布是这样的:icon 207个、apple-touch-icon 171个、shortcut icon 59个、apple-touch-icon-precomposed 38个、mask-icon 15个。 link和rel这层标记同时服务于无障碍,网站无障碍访问怎么做的十八个改动 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)里有相关的取值说明。 这几个取值的含义在 HTML规范里link元素与rel的定义 (https://html.spec.whatwg.org/multipage/links.html)那一节有正式说明,而各取值在实际浏览器里的行为差异,可以对照 rel属性各取值的说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/rel)。其中真正被搜索用到的是前四类。apple-touch-icon系列加起来209个,比标准的icon还多。这说明大量声明其实是为iOS主屏图标准备的,跟搜索结果里的展示是两回事,只是恰好也在候选池里。 mask-icon那15个是Safari固定标签页用的单色矢量图,跟搜索完全无关。它们在候选池里的唯一作用是增加噪声。 还有一个细节值得注意:shortcut icon这个写法有59个站在用。它是历史遗留——早年的IE只认这个写法,官方文档里说明保留支持是出于历史原因。今天写它没有坏处,但也没有必要,纯标准的icon就够了。 把这几类的用途列成一张表,你就知道自己该留哪几个了。 rel取值 | 本次出现次数 | 真正的用途 | 该不该留 | icon | 207 | 浏览器标签页与搜索结果 | 必留 | apple-touch-icon | 171 | iOS主屏图标 | 建议留一个 | shortcut icon | 59 | 老版IE的历史写法 | 可删 | apple-touch-icon-precomposed | 38 | 旧版iOS的免加工变体 | 可删 | mask-icon | 15 | Safari固定标签页单色图 | 看需求 | 按这张表清一遍,多数站的图标声明能从五六个降到两三个。这不是为了省几行代码,是为了让剩下的那几行有人真的会去检查。 ## 还有一类声明本次没统计 除了link标签,现在还有一条路可以声明图标:网页应用清单文件。它是一个单独的JSON,里面可以列一组不同尺寸的图标,主要服务于把网站装到桌面或手机主屏的场景。 多处声明无人统一是个通用病,网址用扁平还是层级在SEO上到底差在哪 (https://zhangwenbao.com/flat-urls-vs-hierarchical-urls-for-ecommerce-sites.html)里也有一份同源的取舍。 本次没有统计这一类,原因是它需要多请求一个文件、再解析里面的图标列表,工作量翻一倍,而它对搜索结果里的图标展示影响不明。写在这里是提醒你:如果你的站配了这个清单,那它也是一处需要保持同步的声明位置。 实际见过的坑是这样的:团队换了图标,把head里那几行都改了,唯独忘了清单文件里那一组。结果浏览器标签页上是新标志,装到主屏上是旧标志。这类不一致跟本文讲的其它问题同源——多处声明、无人统一。 顺着这条线索还能想到别的地方:邮件模板里的品牌图标、社交平台的头像、应用商店的图标、后台登录页的标志。这些位置各自独立、各自维护,而它们对外呈现的是同一个品牌。没有哪一个系统会替你检查它们是不是一致,唯一的办法是自己列一张清单,改标志的时候照着过一遍。 这张清单的价值不在技术层面,在于它把一件本来分散在四五个人手上的事,变成了一张有人负责的表。身份这件事的所有麻烦,归根到底都是同一件:说的地方太多,管的人太少。本文量的两样东西,图标和名字,正好是这句话最典型的两个样本——平均每站声明三点四个图标,四个来源里只有两成二说的是同一个名字。这两个数字都不是能力问题,是没有任何一个岗位的职责说明书里写着“确保这几处对得上”。补上这一句职责,比补任何一个文件都管用。而且这句职责挂在谁头上其实不重要,重要的是它得有人认领——本次样本里做得最好的那批站,共同点从来不是技术更强,而是有人把这件事当成了自己的活。 ## 声明多了到底有没有害 直说结论:声明多本身无害,声明多而其中有坏的才有害。本次数据里11个站的声明里含取不到或者不是图片的文件,其中5个站的所有声明全部不可用。 候选多了没人逐个检查,这跟报表口径打架是同一类管理问题,商品页推荐位两套报表打架的复盘 (https://zhangwenbao.com/product-page-recommendation-attribution-mismatch.html)值得对照。 换个角度看这件事:如果你只声明一个,你会盯着它;声明22个,你不会去检查每一个。候选数量和检查密度是反比关系,这才是多声明的真实代价。 ## 那37个一个都没声明的站怎么办 它们不是没有图标,是把这件事完全交给了兜底路径。这个做法在十年前很安全——那时候所有站的根目录下都真的躺着一个favicon.ico文件。 建站方式直接决定了静态资源放哪,SaaS托管自建与纯代码的选型全拆解 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)里有各类栈的差别。 现在不一样了。现代的建站方式里,静态资源往往走独立的构建目录或者CDN,根目录下什么都没有,请求会掉进前端路由。那个曾经最可靠的兜底,正是今天最不可靠的一环。下一节的数据会把这一点量出来。 ## 格式混用的34个站 还有一个数字顺手记一下:34个站在自己的图标声明里混用了多种格式,比如同时给PNG和ICO,或者同时给PNG和SVG。最热闹的一个站一口气用了四种:PNG、GIF、SVG、ICO。 多种格式并存最怕不同步,Shopify图片SEO从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)里有统一产出的做法。 混用本身不违规,官方明说任何有效格式都支持。但它会带来一个隐蔽的后果:不同格式的文件往往由不同的流程产出,它们很容易在某次改版之后变得不一致。你换了PNG那一版的设计,ICO那一版还是老图,而系统可能恰好用了ICO那个。 所以混用的前提是有人负责让它们保持同图。做不到的话,宁可只留一种。 ## 兜底路径那个文件,211个域名里只剩59个还在 就算你一个都不声明,浏览器和抓取程序也会去试根目录下的那个默认文件。这是最后一道兜底,它的可用率决定了那37个不声明的站还有没有救。 主机名与静态资源的路由规则挨得很近,多域名301跳转到主域名的完整配置 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)里有对应的写法。 ## 结果比预想的差 返回的东西 | 域名数 | 占比 | ICO格式的真图标 | 53 | 25.1% | PNG格式的真图标 | 6 | 2.8% | 空的或者连不上 | 89 | 42.2% | 一整张HTML网页 | 50 | 23.7% | 其它无法识别的内容 | 13 | 6.2% | 同一批电商站的另一项体检也是七成不合格,四十六个电商站的页面体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)可以并排看。 211个域名里,只有59个能从这个路径拿到一张真图标,占28%。剩下152个,兜底这条路是断的。 ## 先说清楚这批数字怎么来的 做法很直接:对211个域名逐个请求根路径下那个默认文件,跟随跳转,记录状态码、返回字节数和内容类型,然后把文件下载下来读它的头几个字节判断真实格式。 读原始响应比读报表可靠,日志分析一步步挖出AI爬虫真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)用的是同一种从底层数据反推的路子。 判断格式用的是文件签名而不是响应头声明的内容类型,因为后者不可信——本次就有一批响应声称自己是图片,实际返回的是HTML。凡是能从文件本身读出来的东西,就别信别人怎么说。 这一步还有个小坑:ICO文件的宽高字段只有一个字节,256这个尺寸被编码成0。不处理这一条的话,256×256的图标会被读成0×0,然后当成解析失败扔掉。这类编码约定造成的“假缺失”,在数据处理里比真缺失更危险,因为它不会引起任何怀疑。 ## 那50个返回网页的最有意思 返回HTML,说明这个路径命中了站点的通用路由,被当成一个普通页面处理了。绝大多数返回的是404页面,少数几个甚至返回200。 该返回空的地方返回了正常页面,四十个电商站的站内搜索页实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)记录的是同一类假成功。 按字节数排一下,前几名相当惊人: 域名 | 状态码 | 返回大小 | burrow.com | 404 | 4541 KB | mejuri.com | 404 | 704 KB | pullandbear.com | 404 | 696 KB | quince.com | 404 | 562 KB | babybjorn.com | 404 | 536 KB | ruggable.com | 404 | 400 KB | swarovski.com | 200 | 365 KB | deuter.com | 200 | 176 KB | 最上面那个值得念一遍:请求一个几KB的图标文件,收到4.5 MB的HTML,而且状态码是404。这意味着每一个访问过这个站、或者抓取过这个站的客户端,只要去试一次那个路径,就要为一张不存在的图片下载四兆多的网页。 ## 返回200的那两个更麻烦 swarovski.com和deuter.com的兜底路径返回的是200加一整张网页。404至少还诚实地说了“没有”,200是在说“有,就是它”。 状态码说的话和事实不符会带来一连串误判,已收录页面加noindex后多久消失的实测 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)里有类似的观察。 这属于软404的一个变种,只是发生在一个几乎没人检查的路径上。任何一个按内容类型判断的程序,拿到一个声称成功、实际是HTML的响应,都只能自己去猜发生了什么。 软404这件事本身在SEO圈里被讲了很多年,但讨论几乎全部集中在内容页上——商品下架了返回200空白页、分类页没有商品还照样返回200。没有人去查静态资源路径上的软404,因为那不是内容,不影响收录。 可现在它开始影响展示了。图标是展示层的一部分,而展示层的抓取同样要判断“这个地址给的到底是不是我要的东西”。一个在收录这件事上完全无害的问题,换个场景就变成了有害的。 ## 按服务器类型看这条路的通过率 把211个域名按响应头里的服务器标识分组,通过率的差异非常明显。传统的nginx、Apache这类直接托管静态文件的,兜底路径可用率明显更高;而各类现代托管平台和前端框架的默认部署,可用率显著偏低。 服务器配置差异对SEO的影响面比想象中大,服务器配置对SEO影响的二十项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)逐项列过。 这不是说哪种技术更好。差别的根源是“根目录下有没有一个物理文件”,跟性能、安全、开发体验都没关系。传统栈天然有,现代栈天然没有,除非你专门放一个。 这条观察的实用价值是:如果你的站是这几年新建的、跑在现代托管平台上,那么你的兜底路径大概率是断的,不用查也能猜个八九不离十。去查一下,然后花五分钟补上。 补的方式有两种,选一种就行。一种是在构建输出目录的根下真的放一个物理文件,这样请求会命中静态资源,不进路由。另一种是在服务器或者托管平台的路由规则里,给这个路径单独加一条,让它直接返回文件或者返回一个干净的404。第二种更彻底,因为它顺带把“返回4.5 MB网页”这个副作用也消掉了。 ## 怎么快速自查这一条 一条命令就够:请求你自己的 /favicon.ico,看三样东西——状态码是不是200、内容类型是不是图片、字节数是不是几KB到几十KB。三样里有任何一样不对,这条兜底路径就是断的。 批量检测地址可用性有现成的做法,网站死链怎么批量查出来的一条龙流程 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接改来用。 把这三样连起来判断很重要。只看状态码会漏掉那50个返回200或404却给了HTML的;只看内容类型会漏掉那些声称是图片实际不是的;只看字节数会把一张几百KB的设计稿当成正常。三样一起看,才是一次可靠的判断。 如果你想更省事,可以只看字节数这一项做初筛。一个正常的图标文件通常在1 KB到50 KB之间,超过100 KB基本可以断定出事了。本次样本里返回超过50 KB的那14个,无一例外全是网页。 断了要不要修,取决于你有没有正确声明。如果head里的声明是好的,兜底断了影响有限;如果你什么都没声明,那这条路断了就等于没有图标。本次样本里37个站属于后者。 ## 为什么这条路会断得这么普遍 把返回情况按站点技术栈分一下就能看出规律。返回真图标的那批,绝大多数是传统服务器直接托管静态文件的站;返回HTML的那批,几乎全部是走前端框架加通配路由的站。 前端路由接管一切是现代栈的默认行为,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)解释了它带来的连锁反应。 成因是这样的:现代前端框架的路由规则通常是“任何没匹配到静态资源的路径,都交给应用处理”。而根目录下如果没有那个物理文件,请求就落进了这条规则,应用当然只会渲染一个页面出来。这不是谁写错了配置,这是默认行为撞上了一个历史约定。 知道成因,修法就明确了:在构建输出的根目录里真的放一个文件,或者在服务器层给这个路径加一条专门的规则。两种都行,成本都是几分钟。 ## 一个容易被忽略的连带影响 兜底路径返回一整张网页,除了图标拿不到之外,还有个副作用:浏览器每打开一个标签页就会去请求一次这个地址。 为不存在的资源反复付带宽是抓取预算里的老问题,抓取预算优化的十二项实操指南 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)里有对应的排查。 对那个返回4.5 MB的站来说,这笔账值得算一下。假设一天有十万次页面访问,浏览器缓存不命中的比例哪怕只有百分之一,那也是一千次4.5 MB的传输,接近4.4 GB。为一张不存在的图付这么多带宽,而且没有任何监控会告诉你这件事正在发生。 这个估算是粗的,实际数字取决于缓存策略和客户端行为,但量级足以说明问题。 ## 你声明的那些图标,有多少其实是坏的? 声明得对不对,比声明得多不多重要得多。这一节量的是那451个文件里,有多少根本取不回来。 素材层的坑往往不在策略上而在文件上,PMax六个月实战避坑的信号源与素材 (https://zhangwenbao.com/dtc-google-pmax-real-world-pitfalls.html)记过一批类似的。 ## 坏文件的分布 451个文件里,24个取不到或者返回的不是图片,涉及11个站。乍看比例不高,但按站看就不一样了:其中5个站的所有声明全都不可用。 按站看和按文件看得出的结论可以差很远,阿里国际站五百九十万页面被清零的复盘 (https://zhangwenbao.com/alibaba-aigc-google-deindex-dtc-seo-guide.html)也是这个道理。 域名 | 坏的比例 | 具体情况 | stokke.com | 4个全坏 | 四个文件全部返回410已删除 | mango.com | 5个全坏 | 五个文件全部返回HTML | notino.com | 4个全坏 | 四个文件内容无法识别 | swarovski.com | 3个全坏 | 返回200但内容是网页 | arcteryx.com | 1个全坏 | 唯一声明的文件返回网页 | chewy.com | 1 / 6 | 兜底路径那个是空的 | rothys.com | 1 / 2 | 一个文件404 | soundcore.com | 2 / 3 | 两个文件内容无法识别 | ## stokke那四个410值得单独说 410这个状态码的含义是“这个资源曾经存在,现在被永久删除了”,它比404更明确。四个图标文件全部返回410,说明这些文件确实曾经在那儿,后来被清理掉了,而首页里的声明没跟着改。 构建产物路径与模板写死的链接容易撞车,自建站谷歌SEO开发期的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)里列了要盯的位置。 从路径能看出成因:那几个地址里带着一段版本号一样的数字。这是典型的构建产物路径——每次发版生成一个新目录,旧目录被清掉,而head里的链接指向的还是旧目录。 这类问题在做前端发布流程的时候特别常见,而且它不会影响页面显示,因为浏览器拿不到图标只是不显示而已,不会报错。一个不报错的失败,可以安静地存在很多年。 再往下想一层:410是一个需要服务端主动配置才会返回的状态码,默认行为通常是404。这说明那个站的运维是认真做过资源清理的——他们知道这些文件被删了,也告诉了客户端。问题不在删得对不对,在于删的人和写head的人不是同一拨。 这个案例的可迁移之处在于,构建产物路径带版本号是现代前端的标配,而head里的图标链接往往写死在某个模板里,不参与构建。一边每次发版都换路径,一边永远不变,撞车只是时间问题。解法是让那几行链接也走构建变量,或者干脆把图标放到一个不带版本号的固定路径下。 ## mango那五个返回HTML的成因不一样 mango.com的五个图标地址全部返回HTML。看路径能发现,它们都带着构建工具生成的哈希段。这类地址通常是有效的,返回HTML说明请求根本没落到静态资源服务上,而是被前端路由接管了。 同一个地址对不同客户端返回不同东西是常见设计,用内容协商给AI交付Markdown的实操 (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)讲了它的正确用法。 更可能的解释是这些地址需要特定的请求头或者会话才能命中真实资源,直接请求会掉进兜底页面。对抓取程序来说,结果是一样的:它拿不到图。 ## notino那四个又是另一种情况 notino.com的四个图标全部返回了无法识别的内容——状态码200,但文件头既不是PNG也不是ICO,读不出来是什么。 中间层悄悄改写内容这件事不止一次出现,浏览器自动翻译把选项改掉而问卷看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是另一个版本。 这种形态最可能的解释是响应经过了某层加工:可能是被压缩了但没声明编码,可能是被某个安全或加速服务包装过,也可能是内容协商出了岔子返回了一个占位。对客户端来说,结果和拿到一张坏图没有区别。 它跟前面几个的区别在于排查难度。410和HTML都很好定位——一看状态码或者一看开头几个字节就明白了。而这种“是200、有内容、但内容认不出来”的情况,只有真的去读文件头才会暴露,任何只看状态码的检查都会放行。 ## 五个站全坏这件事说明了什么 把arcteryx、mango、notino、stokke、swarovski这五个站放在一起看,有个共同点:它们都是有一定体量的品牌,站做得不差,页面显示一切正常。 没有报错的失败最难被发现,用户扫完一整屏一个都没点开这件事 (https://zhangwenbao.com/product-list-item-attributes-silent-rejection.html)也是一次静默流失。 坏掉的只有那几个不影响显示的地址。浏览器拿不到图标,只是标签页上少一个小图;没有报错,没有控制台警告,没有任何一个监控会告诉你这件事。 这类问题的分布特征很有意思:它跟团队水平几乎没有相关性,跟“有没有人专门检查过这几个地址”高度相关。而“有没有人检查过”这件事,在绝大多数团队的流程里根本没有位置。 ## 自查的口径要定在哪 不要只看状态码。本次样本里,返回200却不是图片的有一批,返回图片却是空文件的也有。正确的判据是三件事同时成立:状态码200、文件头是已知的图片格式、能解析出宽高。 判据定得松,结论就没意义,三百个站实测出来的收录速度指标怎么读 (https://zhangwenbao.com/seo-kpi-guide.html)里有口径设计的思路。 最后那条最关键。有些文件状态码正常、内容类型也写着image,但文件本身是截断的,解析不出尺寸。这种情况只有真的去读文件头才能发现。 ## 怎么读ICO文件的真实尺寸 顺手记一个技术细节,因为它在这次测量里踩过坑。常见的图片处理函数大多不支持ICO格式,直接调用会返回失败,容易被误判成“文件坏了”。 读字节而不是读声明,这条原则在识别请求来源时同样适用,五种代码识别搜索引擎蜘蛛的实战 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)里有对照。 ICO的头部结构其实很简单:开头四个字节是固定标记,接着两个字节写明这个文件里打包了几张图,然后每张图各占十六个字节的目录项,其中头两个字节就是宽和高。有一个反直觉的地方:宽高字段只有一个字节,所以256这个尺寸被记成0。不知道这条的话,一张256×256的图会被读成0×0。 这个坑很典型:一个看起来是“数据缺失”的值,实际上是编码约定。本次统计里有几个256×256的图标,如果没处理这一条,它们会被当成解析失败扔掉,结果就是尺寸分布的高位档被少算。 ## SVG的尺寸怎么算 SVG是矢量图,严格说没有固定尺寸。本次的处理办法是读它的viewBox属性,取里面的宽高值当作名义尺寸;读不到就只记录它是SVG,不参与尺寸统计。 测不出就标测不出,比编一个数字强,测试赢了上线却掉的那二十六天 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)也是靠承认边界找到原因的。 这个处理在官方口径下是安全的,因为文档明说SVG这类矢量格式不受具体尺寸限制。把测不出的东西诚实地标成测不出,比给它编一个数字强。本次451个文件里有32个SVG,它们在尺寸那张表里全部被排除。 ## 尺寸这一关,多少站过不去? 拿到了文件,接下来看它够不够格。判据是官方那两条:正方形,至少8×8,建议大于48×48。 图片资源的呈现细节很容易被长期忽略,那几张没露出来的商品图 (https://zhangwenbao.com/product-gallery-truncated-thumbnail-signposting.html)是同一类问题。 ## 整体尺寸分布 451个文件里能解析出宽高的,按尺寸出现次数排,前几名是32×32出现95次、16×16出现61次、180×180出现39次、48×48出现29次、192×192出现23次、96×96出现22次。 尺寸与格式的取舍在图片SEO里是老话题,图片SEO的文件名与WebP懒加载怎么落地 (https://zhangwenbao.com/website-photo-seo-optimization-techniques.html)可以顺带过一遍。 32和16加起来占了大头,这是历史习惯——早年的浏览器标签页图标就是这两个尺寸。180×180那一档是iOS主屏图标的标准尺寸。真正为搜索结果准备的尺寸,反而不多。 这个分布本身讲了一个故事:这些图标当初是为浏览器和手机做的,不是为搜索结果做的。16和32这两个尺寸的存在理由,是十几年前浏览器标签页的物理像素;180的存在理由是iOS主屏。而搜索结果里的图标展示尺寸,在高分屏上远超这两档。 所以那47.7% 不是懒惰的结果,是历史的结果。这批文件当年做得完全正确,只是使用场景后来变了,而没有人回头重做过。这类问题的特征是:不做任何改动,它会随着时间自动变糟。 ## 48×48那29次出现值得看一眼 尺寸分布里,48×48出现了29次,排第四。这个尺寸既不是浏览器标签页的传统尺寸,也不是iOS主屏的标准尺寸——它出现在这里,说明有一批站是照着搜索的建议来做的。 照着建议做和刚好卡在线上是两回事,FAQPage结构化数据的八步实战 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)里也强调过留余量。 但48×48只是官方所说的“大于48×48”那条线上的临界点,严格说它并没有超过。如果你要照建议做,直接给一张96或者192更稳妥,不多花什么成本。 另外提一句,图标这件事上没必要追求极致清晰。它最终显示成一个十几到几十像素的小方块,源文件超过512像素之后再往上加,肉眼看不出任何差别,只是白白多传几十KB。够用就停,这也是代劳型规则那条钝曲线的具体表现。 本次样本里超过256像素的有19个站,这一档在任何屏幕上都够用。文件大小也不是问题——一张192×192的PNG通常只有几KB到十几KB。没有理由为了这点体积去用一张16像素的图。 ## 那9个只有16像素的站 brooklinen、hellotushy、innisfree、nespresso、stanley1913、untuckit、uniqlo、zalando、weber——这九个站声明的所有图标里,最大的一张只有16×16。 品牌体量和执行细节之间没什么相关性,品牌权威度与域名权重的区别 (https://zhangwenbao.com/moz-ba-brand-authority-seo.html)里有类似的观察。 看这份名单就知道这跟品牌体量无关。里面有全球快时尚巨头,有百年厨具品牌,有欧洲最大的时尚电商平台之一。它们的图标不是做得差,是做于很多年前,从此再没动过。 16像素在2010年前后是完全正确的选择——那时候标签页图标就是这么大,多做也没用。今天的高分屏上,同样一张图会被放大好几倍来显示,结果就是一团马赛克。这不是一次错误的决定,这是一次正确的决定过期了。 顺带说,这一类问题的修复成本可能是全文最低的:让设计部门重新导一张192或者512的PNG,替换文件,改一行sizes。半小时的活,而且不需要任何人做决策。 ## 按站看最大边长 该站最大的图标边长 | 站数 | 不超过16 px | 9 | 17到32 px | 43 | 33到48 px | 9 | 49到128 px | 12 | 129到256 px | 36 | 超过256 px | 19 | 分档统计要先想清楚档位怎么划,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)记录过一次分档带来的误导。 把前三行加起来:128个有可测文件的站里,61个的最大图标不超过48像素,占47.7%。它们全部满足硬门槛,但全部没到官方建议的那一档。 最极端的是9个最大只有16像素的站,里面不乏一线品牌。16像素在今天任何一块屏幕上都是一个模糊的小方块。它能用,只是好不到哪去。 ## 那11个不是正方形的文件 正方形是硬要求,不是建议。本次抓到11个非正方形的文件,分布在10个站上。 差一点点也是不合格,判据不该模糊,调研数据里没有一个非会员却写给非会员看 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)就是判据松了的后果。 域名 | 实际尺寸 | 偏差 | mejuri.com | 1587×1123 | 宽高比接近1.41 | fahertybrand.com | 152×96 | 宽高比1.58 | harrys.com | 27×21 | 又小又不方 | hellotushy.com | 16×20 | 竖着的长方形 | brooklynbedding.com | 46×35 | 差11像素 | casper.com | 180×167 | 差13像素 | materialkitchen.com | 32×26 | 差6像素 | framebridge.com | 32×31 | 只差1像素 | 最有教学价值的是最后两个。32×31只差一个像素,但它已经不是正方形了。这种偏差几乎肯定来自一次自动裁剪或者压缩,没有任何人是故意把图导成32×31的。 而mejuri那个1587×1123完全是另一回事——那大概率是一张设计稿或者宣传图,被误当成图标挂了上去。一百多万像素的文件,为的是显示成一个十几像素的小方块。 ## 为什么会差那么一两个像素 32×31、46×35、180×167这几个,共同点是差得很小但确实差了。这种偏差有三个常见来源。 自动化流程产出的东西最容易在细节上跑偏,Shopify的一百二十八种结构化数据类型怎么挑 (https://zhangwenbao.com/shopify-schema-seo-guide.html)里也提过同类问题。 一是设计稿的画板本身就不是正方形,导出的时候按内容边界裁剪,边缘留白不对称就差了一两像素。二是走了自动压缩或者格式转换,某些工具会在转换时按内容裁掉透明边。三是从一张大图缩放而来,缩放比例不是整数,取整之后宽高各自舍入到了不同的值。 三种成因的共同点是没有人做过决定。这跟上一篇里名字被机器改坏的那几个案例是同一类问题:语法完全合法、页面显示正常、没有任何报错,只有真的去读文件才能发现。 ## 正方形这条到底会不会被严格执行 官方把它列成了要求而不是建议,所以合理的假设是会被执行。但具体是直接弃用、还是自动补边裁成正方形,文档没说。 不对称的赌局不值得参与,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)讲的就是怎么判断值不值得试。 保守的做法是别去赌。把图标导成严格的正方形,成本是一次导出;赌错了的成本是展示位上一个灰色的默认图标,而且你还不会收到任何通知。这类不对称的赌局,不值得参与。 ## 声明的尺寸和文件的真身对得上吗? 声明里的sizes属性写的是这个文件多大,抓取程序会拿它做初筛。如果它跟文件真身对不上,初筛就是错的。 声明与实际对不上会一路污染下游,微软广告改UTM自动打标之后的归因影响 (https://zhangwenbao.com/microsoft-ads-utm-auto-tagging-channel-attribution.html)是另一个例子。 ## 9条对不上的记录 域名 | 声明 | 实际 | nike.com | 128×128 | 192×192 | nike.com | 192×192 | 120×120 | typology.com | 76×76与120×120 | 512×512 | typology.com | 16×16、32×32、96×96 | 196×196 | chewy.com | 152×152 | 114×114 | deuter.com | 96×96 | 192×192 | traeger.com | 180×180 | 152×152 | shopify.com | 114×114 | 144×144 | fahertybrand.com | 180×180 | 180×171 | 声明与实物对不上在商品数据里同样高发,跨境电商GTIN怎么申请与收录 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)里有核对的办法。 ## nike那两条是互相错位的 看清楚这两行:声明128的那个文件实际是192,声明192的那个文件实际是120。两条声明像是被交换过,而且交换之后两条都不对。 两条记录被调换过的痕迹很有诊断价值,五个渠道加起来一百五十九个百分点 (https://zhangwenbao.com/comparison-shopping-co-presence-join-key.html)也是靠痕迹反推的。 这种形态说明什么?说明这两个link标签的href或者sizes在某次改动里被挪动过,改的人只调了顺序没核对内容。它不是一次疏忽,是一次操作留下的痕迹。 ## typology那两条是最离谱的 一个文件声明自己有76和120两档,实际是512×512;另一个声明自己有16、32、96三档,实际是196×196。声明和真身差了四倍以上。 换了内容不换标记是通病,用SignificantLink和RelatedLink表达页面关系 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)里有维护的建议。 这种情况通常出现在换图但不换声明的时候:设计师给了一套高清图,工程师换了文件,head里那几行sizes原封不动。文件是新的,标签是旧的。 ## sizes写错到底有多严重 说实话,不算致命。抓取程序拿到文件之后可以自己读真实尺寸,声明只是一个提示。但它有两个真实代价。 指标要分清是结果还是信号,埋点之前先把测量框架设计清楚 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)讲了这两类的区别。 第一,浏览器和设备会按声明去挑,挑错了就会拿一张不合适的图去缩放,显示效果打折。第二,也是更重要的一条:sizes对不上是一个信号,说明这个站的图标声明缺乏维护。本次数据里,sizes出错的站,往往同时还有别的问题——比如fahertybrand那个既写错尺寸又不是正方形。 ## 把它当成一个探针来用 这一条其实是本次实测里最好用的一个诊断指标,价值不在它本身,在它的相关性。 低代价字段当高信号探针,这套思路在共识层排查里同样好用,共识层六信号的九十天实战指南 (https://zhangwenbao.com/seo-consensus-layer-ai-search.html)有更多例子。 逻辑是这样的:sizes属性是纯声明,写错了没有任何直接惩罚,没有报错,没有告警,页面显示也完全正常。一个错了完全没有代价的字段,如果它是对的,说明有人真的核对过;如果它是错的,说明这一块从来没人管。 所以拿它当探针非常合适:三十秒就能查,查出问题基本可以断定这个站的图标链路缺乏维护,值得整体过一遍。反过来,如果一个站的sizes全部准确,那它的其它环节大概率也没问题。 这类“低代价字段当高信号探针”的思路,在很多排查场景里都成立。找那些错了没人管的地方,它们最诚实。 ## 要不要干脆不写sizes 可以。sizes不是必填的,不写的话抓取程序和浏览器会自己读文件。对于只声明一两个图标的站,不写反而更省事,因为少了一处需要同步维护的地方。 能少维护一处就少一处,新网站SEO目标管理的三个里程碑 (https://zhangwenbao.com/new-website-seo-goal-management.html)里有怎么砍任务的判据。 什么时候该写:当你声明了多个不同尺寸、希望设备按需挑选的时候。这时候sizes是有价值的,但前提是它必须准。要么准,要么不写,最差的选择是写一个错的。 ## 名字那一半,系统到底从哪几个来源里挑? 图标讲完了,回到广告位上那一行的另一半。名字这件事的机制和图标几乎一样,只是候选来源更多。 同一套系统在别处也是自己改写你的输入,品牌词和非品牌词那条线画在哪 (https://zhangwenbao.com/brand-nonbrand-split-grounding-query.html)记录了改写的全过程。 ## 官方说它会看哪几处 站点名称那份文档 (https://developers.google.com/search/docs/appearance/site-names)写得很明确:要表明你的偏好,在首页加WebSite结构化数据;系统同时也会考虑og:site_name、标题、标题类元素以及首页上的其它文本;其中结构化数据最重要。 多来源汇总成一个实体是整套语义体系的基本动作,实体SEO的五阶段构建方法 (https://zhangwenbao.com/entity-seo-guide.html)讲得更系统。 还有一句更该被记住:如果系统对你提供的名字不够有把握,它可能会用其它来源生成一个站点名,或者直接显示你的域名甚至子域名。 把这两句连起来读,整个机制就清楚了:你给的是候选,它做的是选择题,而且它保留了交白卷的权利——交白卷的答案是你的域名。 还有一个层级关系不能忽略:文档明说WebSite结构化数据最重要。这意味着四个来源不是平权的,而是有优先级的。如果你只想改一处,改那一处。本次样本里,恰恰是这一处的完成率最低——大量站有og:site_name、有标题,就是没有WebSite结构化数据。 ## 为什么会有四个来源这么怪的设计 站在系统的角度想一下就明白了。它要给互联网上每一个站都算出一个名字,而绝大多数站不会主动声明任何东西。如果只认结构化数据,那么绝大多数站的名字栏都会是空的。 降级链路的存在解释了很多看似奇怪的展示结果,AI搜索可见性的五维度深层策略 (https://zhangwenbao.com/ai-search-visibility-deep-seo-strategy.html)里有相关分析。 所以它必须有一套降级链路:最好的情况读结构化数据,读不到就看og标签,再读不到就从标题和正文里猜,全都猜不出就用域名。这套设计对整个互联网是合理的,对认真填了字段的站却有个副作用——你的正确声明,要和那些兜底来源一起参与竞争。 竞争的结果取决于系统对每个来源的把握。如果你的结构化数据写了A,标题尾段写了B,og写了C,那么它面对的是三个互相矛盾的信号,把握自然低。这就回到那句话:不是你说得不够,是你说了三种不同的话。 ## 四个来源实测对不对得上 本次把每个站的四个名字来源抠出来对比:域名主体、标题尾段、og:site_name、结构化数据里的组织名。归一化处理是统一转小写、去掉所有非字母数字字符,这样大小写和标点差异不会算成不一致。 同一批国际站还被用来量过网址结构,一万个电商站的网址结构实测结论 (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)是另一次大样本抓取。 在至少三个来源有值的98个站里,四者归一后完全一致的只有22个,占22.4%;不一致的76个,占77.6%。 这个比例值得停一下。七成七的站,在“我叫什么”这个问题上,给出了不止一个答案。而这还是在忽略了大小写和标点差异之后的结果。 ## 22个完全一致的站有什么共同点 先看好的那一批。22个四来源完全一致的站,共同点相当明显:它们的品牌名短、只有一个词、而且域名就是这个词加后缀。 起名时的选择会一路影响到展示层,独立站起名的命名策略与SEO避坑 (https://zhangwenbao.com/domain-generator-naming-strategy-tld-seo-guide.html)里有前置的判断。 这不是因为它们更用心,而是因为它们没有分叉的空间。当品牌名等于域名主体的时候,模板默认值填出来的东西恰好就是对的;标题尾段随手写品牌名,也自动一致。一致性在这批站上是免费的。 这条观察有个实际推论:如果你的品牌名和域名天然一致,这件事你大概率不用管;如果不一致,那就得主动管,而且没人会提醒你。这套机制对起名幸运的人是白送的,对起名不幸的人是要交作业的。 ## 不一致都长什么样 翻了一遍具体记录,形态可以归成四类。 第一类是标题尾段写的不是名字,是一句卖点。aloyoga.com的标题尾段是一整句“从工作室到街头的瑜伽服饰与配件”,avocadogreenmattress.com是“有机无毒床垫”,cotopaxi.com更直接,是“订单满99免运费”。把促销信息放在标题尾段,等于往名字候选池里扔了一句广告。 cotopaxi那条尤其值得说,因为它是有时效的。免运费门槛会变,大促期间会调整,甚至可能某天取消。一个会变的字符串,被放进了一个需要长期稳定的位置。而站点名称这件事的价值几乎全部来自稳定——系统要能反复确认“这个站还是那个站”。 公平地说,标题尾段放卖点在点击率上是有道理的,这是几十年的老做法。问题在于它现在多担了一个职责。解法不是把卖点删掉,是把结构化数据填上——让系统有一个明确的、优先级更高的来源可以读,标题尾段爱写什么写什么。 第二类是og和结构化数据各说各的。casper.com的og:site_name是Casper Sleep,结构化数据里是Casper;baseus.com的og是Baseus US,结构化数据也是Baseus US,但域名是baseus;cybex-online.com的结构化数据是CYBEX Online Shop,og是空的。 这一类的成因在上一篇里分析过:结构化数据通常来自SEO插件或专门的开发任务,og标签通常来自社交分享需求、由市场部门提。两条链路、两个部门、两次各自的填写,天然容易不一致。 casper那个还有一层:Casper Sleep是公司的正式名,Casper是品牌名。两个都对,只是该出现在不同的字段里。正式名进legalName,品牌名进name和og:site_name,这样两边都能说自己填的是对的,而系统只会看到一个答案。 第三类是把网址写进了名字。traeger.com的og:site_name直接是完整网址,nike.com的og:site_name写的是Nike.com——带着域名后缀。 这两个案例的性质不太一样。写完整网址那个几乎肯定是模板默认值没改,属于纯事故。写Nike.com的那个更可能是有意为之——早年的品牌传播里,把域名后缀带上是一种做法,用来提示“我们有网站”。这个习惯在今天成了负担:它让你的名字里多了一段跟名字无关的字符。 顺便说,这两条都会被上一篇提到的商家资料禁令直接判违规,那一条叫“电话号码或网址”。同一个写法,在有执法的地方会被处罚,在这里只会让系统多一次犹豫。 第四类最普遍,也最值得单独用一节讲:域名本身跟品牌名不是一回事。 ## 归一化口径先说清楚 这个77.6% 是在做了相当宽容的归一化之后得出的。具体做法是:全部转小写、删掉所有非字母数字的字符,然后比对。 口径放宽还是收紧直接决定数字大小,用正则从GSC里挖AI搜索提问的五步实战 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)里也先花了篇幅交代匹配口径。 也就是说,Boll & Branch和bollbranch会被算成一致,Ice-Watch和icewatch会被算成一致,Béis和beis也会被算成一致。大小写、空格、连字符、重音符号造成的差异,全部不计入不一致。 这个口径是刻意放宽的,因为那些差异对系统来说通常不构成障碍。放宽之后还剩七成七不一致,说明剩下的都是真正意义上不同的字符串,不是格式问题。这一步值得强调,因为如果不做归一化,比例会高得没有信息量。 ## 另外还有一个统计口径要交代 只有至少三个来源都有值的站才进入这次比对,一共98个。为什么不是四个都要有?因为要求四个全有会把样本砍掉一大半——很多站压根没有结构化数据或者没填og:site_name。 汇报数据的时候先讲口径,SEO汇报怎么让不同部门看到同一份事实 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)里有现成的模板。 放宽到三个的代价是:缺失最多的那一档站没有被统计,而它们大概率问题更多。所以77.6% 这个数字,更可能是低估而不是高估。 ## 兜底显示的那个域名,往往不是你的名字 官方说得很清楚,把握不足时它会显示域名。那就得问一句:你的域名,配当你的名字吗。 域名与品牌名之间的缝隙也会被别人利用,品牌被仿冒抢排名的五步应对实战 (https://zhangwenbao.com/brand-domain-impostor-seo-nanoclaw-protection.html)记录过一次。 ## 先确认一下这条兜底真的会发生 这不是推测。站点名称那份文档的原话就是:如果系统对你提供的名字信心不足,它有时会用其它来源生成站点名,或者显示域名或子域名。域名兜底是官方写明的行为,不是极端情况。 域名本身携带的识别信号有多重,GitHub Pages寄生SEO的借力实战 (https://zhangwenbao.com/github-pages-seo-parasite-seo-strategy.html)是个极端一点的例子。 那什么叫信心不足?文档给了几个原因:结构化数据有错误、没有遵循指南、首页无法被抓取,以及名字过于通用。前三条是技术问题,最后一条是命名问题。而本节要说的是第五种情况——技术没错、名字也不通用,但四个来源各说各的。 ## 一批对不上的样本 域名 | 品牌真正的名字 | 域名里多出来的部分 | drinkolipop.com | OLIPOP | 一个动词drink | getquip.com | quip | 一个动词get | hellotushy.com | TUSHY | 一句招呼hello | fromourplace.com | Our Place | 一个介词from | awaytravel.com | Away | 一个品类词travel | beistravel.com | Béis | 品类词加去掉的重音符 | avocadogreenmattress.com | Avocado | 两个修饰词 | chubbiesshorts.com | Chubbies | 一个品类词 | 域名形态带来的连带成本值得单独算一笔,带连字符的域名到底伤不伤SEO (https://zhangwenbao.com/hyphenated-domain-name-seo-impact-overseas-site-decision.html)是同一类问题。 ## 这批域名是怎么变成这样的 原因几乎都一样:品牌名本身太短、太常见,对应的域名早就被注册走了。OLIPOP拿不到olipop.com,就在前面加个drink;quip拿不到quip.com,就加个get。这是DTC品牌起名的常规操作,本身没什么问题。 域名策略从来不只是选个好听的,建一个大站还是多个小站的取舍 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)里有更长期的账。 问题出在下游。当系统对你的名字没把握、退回去显示域名的时候,用户在广告位上看到的是drinkolipop.com,而你的品牌叫OLIPOP。这一步不是名字被写错了,是名字压根没被采用。 而且这个损失是双向的。一方面,看到广告的人可能认不出这是他知道的那个品牌;另一方面,那些搜索品牌名而来的人,看到的展示信息里没有出现他刚才输入的那个词。品牌词搜索的转化率之所以高,很大程度上依赖那一瞬间的确认感,而域名替代品牌名,正好把这份确认感抽掉了。 ## 顺手数一下这批站有多少 在211个域名里粗略过一遍,域名主体明显不等于品牌名的至少有二三十个,形态基本就是那几种:前面加动词、加招呼语、加介词,后面加品类词。这个比例在DTC品牌里明显高于传统企业,原因也不难理解——DTC品牌普遍起名晚,好域名早就被占完了。 名字与定位的清晰度是同一件事的两面,AI搜索时代品牌定位清晰度的四个动作 (https://zhangwenbao.com/brand-positioning-clarity-ai-search.html)讲了怎么收敛。 这条观察对正在起名的团队有直接价值:如果你不得不用一个带修饰的域名,那么从第一天起就要把品牌名在结构化数据里写清楚。这不是可选项,是这个起名决定带来的连带成本。 ## 所以这批站更该把名字说清楚 结论有点反直觉:域名和品牌名差得越远的站,越不能让系统去猜。 品牌词流量值不值得单独拆开看,GSC品牌词过滤器的五步使用指南 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)给了方法。 因为对于域名等于品牌名的站,猜错的代价很小——猜到域名也差不多对。而对于drinkolipop这类站,猜错就是把一个不存在的品牌名摆到用户面前。 具体动作是把WebSite结构化数据填上,名字写OLIPOP,然后确保og:site_name和标题尾段说的是同一个词。这三处一致之后,系统就没有理由退回去用域名了。 ## 还有一个更麻烦的变体 比域名多几个词更麻烦的,是域名和品牌名之间隔着一次重音符号。beistravel.com的品牌名写作Béis,带一个尖音符;域名里当然没有这个符号,写作beis。 别名与变体写法都该主动登记,五大策略让AI搜索主动推荐品牌 (https://zhangwenbao.com/geo-strategies-ai-brand-recommendation.html)里有对应的动作。 这一类在欧洲品牌里很常见。前面提过的归一化会把它们算成一致,但那是我为了让统计有意义而做的宽容处理,系统那边未必这么想。一个带重音的名字和一个不带重音的域名,在字符层面是两个不同的字符串。 处理办法是把不带重音的写法也登记进别名字段。这样两种写法都有明牌,无论用户怎么搜、系统怎么读,指向的都是同一个实体。 ## 通用名那一条也别忽略 官方文档里有一句提醒:避免使用通用名称,它举的例子是“爱荷华州最好的牙医”这类,说这样的名字不太可能被选中。 通用词品牌名的识别负担只能靠周边信号补,把品牌当权重的四大战略 (https://zhangwenbao.com/seo-without-brand-building.html)讲了这笔投入怎么算。 这条对独立站的意义在于,你的名字如果听起来像一个品类描述,系统会倾向于不采用它。上一篇量到的那几个把组织名写成“优质厨具”“选购刀具与厨房用具”的站,正好撞在这条上——它们不但没帮上忙,还把系统推向了退回域名那条路。 判断自己的名字算不算通用,有个粗糙但好用的办法:把它放进搜索框,看结果里出现的是不是你。如果出来的是一整页别人家的商品,那这个名字对系统来说没有识别价值。 这里有个两难:很多DTC品牌的名字本来就是常用词——On、Away、Native、Purple、Ritual、Quince、Seed。这些名字在品牌传播上很有优势,好记好念;在机器识别上却是负担,因为它们跟无数普通语句撞车。起名时的优点,在这一层变成了缺点。 这类品牌能做的,是把周边信号补齐:结构化数据里把组织的地址、成立时间、社交资料链接都填上,让系统有更多依据把这个常用词跟一个具体实体绑起来。名字本身不能改,但它周围的证据可以加。 ## 名字和图标该保持什么关系 最后补一条容易被忽略的:这两样东西会一起显示,所以它们该讲同一个故事。 视觉一致性最终服务于识别效率,电商网站UI设计七条经验法则背后的认知逻辑 (https://zhangwenbao.com/ecommerce-ui-ux-design-principles.html)里有原理。 实际操作里最常见的脱节是图标用的是简写标志、名字用的是全称,两者放在一起用户认不出是一家。这不是技术问题,是品牌资产管理的问题,但它的表现落在技术层面:图标文件是设计部门给的,名字是运营在后台填的,两边各自更新,从来没有并排看过。 这件事在改版之后尤其容易脱节。品牌换了新标志,官网首页的logo换了,社交账号的头像换了,唯独那几个图标文件因为藏在head里没人想起来。结果就是搜索结果和广告位上还挂着上一版的旧标志,而且可能一挂就是几年。 做一次核对的成本极低:把图标缩到16像素,跟名字并排放在一起,看一眼像不像同一个品牌。这一步花三十秒,但它是整套排查里唯一一个真的在看用户会看到什么的动作。 ## 把候选收敛到一个,需要几个动作? 代劳型规则的落地方式只有一条主线:减少候选,确保剩下的那个是对的。下面是可以照着做的顺序。 收敛完之后要不要上监控,二十款GEO与AEO监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)可以按预算挑。 ## 图标那一半的四步 第一步,数一数你的首页head里有几个图标声明。超过四个的话,先问自己每一个是给谁用的——搜索、浏览器标签、iOS主屏、Safari固定标签,超出这四个用途的可以删。 把流程写成可照做的步骤比讲道理有用,七步GEO实战的写作流程 (https://zhangwenbao.com/seo-article-writing-tips.html)也是同一种编排方式。 第二步,逐个请求这些地址,检查三件事:状态码200、文件头是已知图片格式、能解析出宽高。任何一条不成立,这个声明就是坏的,先修再说。 第三步,确认形状和尺寸。正方形是硬要求,本次样本里有站因为一像素的偏差不合格。尺寸建议至少准备一张大于48×48的。 第四步,把兜底路径修好。请求你的 /favicon.ico,如果它返回的是网页,那这条路是断的——它不一定致命,但没有理由让它坏着。 ## 名字那一半的三步 第一步,在首页加WebSite结构化数据,把名字填上。官方明说这个来源最重要,而这一步在本次样本里的完成率并不高。 结构化数据的注入方式决定了改起来方不方便,Schema聚合的五步接入方法 (https://zhangwenbao.com/yoast-schema-aggregation-agentic-web-seo.html)可以先看这一步。 第二步,把og:site_name和标题尾段调成同一个词。特别注意标题尾段——那是最容易被塞进卖点和促销语的位置。 第三步,如果你的域名和品牌名对不上,把这件事当成高优先级。域名不像名字的站,是这套机制里最吃亏的一批。 ## 这两半活加起来要多久 按本次跑数据的经验估一下。图标那四步,一个站二十分钟——大头在逐个请求那些地址并读文件头,如果你会写点脚本,一分钟就跑完了。名字那三步,十分钟,主要是查源码和改模板。 半小时能做完的活该怎么排进优先级,信息词流量过大的六大危害与破局 (https://zhangwenbao.com/informational-keywords-traffic-dtc-ecommerce-seo-strategy.html)里有排期的思路。 这个估算里没算的是沟通成本,而在多数团队里这才是大头。查出来的问题往往横跨设计、前端、运维三方,光是把结论讲清楚、把工单派到对的人手上,就可能比排查本身更花时间。所以查完之后最好直接给出可执行的动作,而不是给一份问题清单。 可执行的意思是:不写“图标尺寸不合规”,写“把这个地址的文件换成一张192×192的正方形PNG,同时把head第14行的sizes改成192x192”。前者会被讨论一周,后者半小时就上线了。 加起来半小时,还不算修的时间。修的时间取决于问题的性质:改一个sizes是一分钟,改构建流程里的图标路径可能要半天。但至少你能在半小时内知道自己要修什么。 如果有多个语言版本或者多个主机名,把这半小时乘以主机名数量。这也是为什么本文一直建议把主机名收敛——每多一个可独立访问的主机名,这套活就多跑一遍。 ## 做完之后怎么记录 建议留一份很简单的记录:每个主机名一行,写清楚它的图标文件地址、尺寸、名字字段的值。这份记录的作用不是给别人看,是下次发版之后,你有一个可以对照的基准。 留基准和留凭证是同一种习惯,SEO服务合同里的达标定义与纠纷案例 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)讲的是更正式的一版。 没有基准的话,你只能每次都从头查一遍,而且查完也不知道跟上次比有没有变。有了基准,比对一遍是几十秒的事。 ## 这套动作和上一篇的名字盘点是同一张表 如果你上一篇的名字盘点已经做过了,这一篇的名字那三步其实是重合的——同一批字段、同一张表,只是这次多看一栏图标。 同一批模板输出的东西该一次改完,类目导航改版三轮之后仍然没写清楚用户在哪 (https://zhangwenbao.com/category-navigation-scope-custody.html)也是模板层的活。 这不是巧合。名字和图标是同一套身份声明的两个字段,它们由同一批模板输出、在同一个位置被消费、出问题的时点也一样(发版、换主题、开新市场)。把它们分开做两次,纯属浪费。 所以实际操作里,建议把这两篇的核对表合成一张:每个主机名一行,横向依次是组织名、og:site_name、标题尾段、图标地址、图标尺寸。一行填完,两件事一起收工。 ## 为什么第一步是数数量而不是看质量 这个顺序是本次数据教的。如果先看质量,你会盯着那张主图反复调尺寸调清晰度,而真正让站出问题的是那些你根本没在看的声明。 先看结构再看细节,跟先定北极星再看分指标是同一个次序,砍掉虚荣指标只盯真信号 (https://zhangwenbao.com/vanity-metrics-north-star-omtm-ecommerce.html)讲了这套逻辑。 那5个所有声明全部不可用的站就是例子。它们的问题不是图不好看,是没有一个能被取到。而这件事只要把地址列出来逐个请求一遍,五分钟就能发现。 同样的逻辑也适用于名字:先数你在几个地方声明了名字,再看每处写的是什么。数量问题是结构问题,质量问题是细节问题,结构错了,细节做得再好也白搭。 ## 删的时候要注意什么 收敛候选主要靠删,但有几处不能乱删。apple-touch-icon删掉之后,iOS用户把你的站加到主屏会拿到一张自动截图,视觉上很难看;mask-icon删掉之后,Safari固定标签页里会显示一个字母缩写。 删东西之前先问它是给谁用的,页脚不是杂物抽屉该怎么设计 (https://zhangwenbao.com/ecommerce-footer-design-trust-conversion.html)用的是同一条判据。 所以正确的做法不是删到只剩一个,而是每个用途留一个,删掉重复的和没用途的。一个站合理的图标声明大概是这样:一个标准icon、一个apple-touch-icon,加上根目录那个物理文件。三个足够覆盖绝大多数场景。 超出这三个的,问自己一句“这个是给谁用的”,答不上来就可以删。本次样本里那些声明十几二十个的站,绝大多数是历史累积——每次适配一个新设备就加一行,从来没有人回头清理过。 ## 一张可以直接抄的核对表 检查项 | 怎么查 | 合格标准 | 图标声明数 | 数首页head里的link标签 | 四个以内,每个有明确用途 | 每个声明可用 | 逐个请求并读文件头 | 200、是图片、能读出宽高 | 形状 | 看解析出的宽高 | 严格相等 | 尺寸 | 看最大的那张 | 至少有一张大于48×48 | sizes属性 | 跟真实宽高比对 | 完全一致或干脆不写 | 兜底路径 | 请求 /favicon.ico | 不返回HTML | WebSite结构化数据 | 查看源码 | 存在且name正确 | og:site_name | 查看源码 | 与结构化数据一致 | 标题尾段 | 看首页title | 是名字,不是卖点 | 把核对表挂进发布流程比靠记忆可靠,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)里也是一张逐项核对的表。 ## 代劳型规则上最容易犯的错是什么? 最后收一下,把这一类事情的常见误区列清楚,比再多列几个数字有用。 平台替你决定的比例还会继续升高,AI Agent时代品牌信任取代排名的四条策略 (https://zhangwenbao.com/ai-agent-brand-trust-new-ranking-factor.html)讲了应对方向。 ## 三个最常见的误判 第一个是找开关。团队会花好几天翻后台、翻文档,想找一个能把展示结果写死的设置项,找不到之后得出结论说这个功能还没做好。它不是没做好,它就不打算给你开关。 找不到开关就以为功能没做好,这类误判在汇报时特别费口舌,流量下降不等于SEO失败的八维度实战 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)有应对说法。 第二个是靠数量取胜。声明二十个图标、在五个地方写名字,以为覆盖面越广越保险。实际效果相反:候选越多,你越不可能逐个检查,坏掉的那个就越可能被选中。 第三个是改完立刻验收。图标的重新抓取,官方明说要几天到几周。改完当天去搜自己的品牌,看到没变就再改一次,这是最坏的做法——反复改会让系统一直处在低把握状态,而低把握的默认行为就是退回去用域名。 ## 还有一个常见的误判:把它当成设计问题 图标这两个字容易让人联想到视觉,于是排查的时候第一反应是找设计部门要一张新图。但本次数据里,真正让站出问题的几乎全是工程问题:文件被清理了、路径写死了、路由把请求吃了、尺寸导出的时候差一像素。 设计与技术的协作边界值得提前划清,网页设计师SEO协作的七个动作点 (https://zhangwenbao.com/web-designer-seo-collaboration-7-actions-ia-figma-typography-image-cta.html)里有一份分工清单。 设计能解决的只有“图好不好看”,而绝大多数站卡在的是“图取不取得到”。这两件事在流程上归属完全不同,找错人就会白等一轮。 正确的顺序是:先由懂技术的人确认那几个地址都能返回可解析的图片,再由设计确认尺寸和视觉。顺序反了,你会拿到一张很漂亮的、但依然取不到的图。 ## 三个反直觉的判断 第一,兜底路径的可用率只有28%,可这件事对大多数站并不致命——因为它们的head里有正确声明。一个指标难看,不代表它是瓶颈;判断瓶颈要看链路上有没有别的路可走。 反直觉的杠杆往往藏在没人看的地方,被低估的九个反直觉UI设计杠杆 (https://zhangwenbao.com/counterintuitive-ui-design-conversion-levers.html)是另一组同类观察。 第二,出问题最狠的不是那些什么都没做的站,是那些做了很多的站。声明22个图标的站,比只声明1个的站更可能有坏文件。投入和正确率之间不是单调关系。 第三,这一类规则最值钱的动作是删,不是加。删掉多余的声明、删掉标题尾段的促销语、删掉名字里的地区后缀——你在替系统减少选择题的选项,而它的正确率跟选项数量成反比。 ## 把三类规则的处理方式并排放一次 | 禁止型 | 代劳型 | 亲自型 | 本篇的例子 | 商家名称禁令 | 图标与站点名称 | 服务端条件请求 | 官方措辞 | 不被允许、可能导致 | 偏好、支持、会考虑 | 我们建议、请支持 | 有没有开关 | 不适用 | 没有 | 不需要,全在你手上 | 核心动作 | 删 | 收敛到一个 | 实现并自测 | 什么时候停 | 过线就停 | 候选剩一个就停 | 不该停 | 失败怎么被发现 | 收到处罚通知 | 看展示结果不对 | 永远不会被通知 | 平台介入方式的差别在专利文本里也能看出痕迹,从专利与专家访谈还原的GEO五步原理 (https://zhangwenbao.com/google-microsoft-patents-geo-guide.html)提供了另一个角度。 最后一行是三类里差别最大的一栏。禁止型有通知,代劳型至少还能肉眼看出来,亲自型从头到尾没有任何反馈。下一篇讲的就是第三类,它量的是同一批站的服务器在被问“变了没有”的时候,答不答得上来。 ## 顺带回答一个可能有人想问的问题 有人会问:既然平台迟早会替我算,那我索性什么都不做,等它算出来再说,行不行。 不做也是一种选择,只是你得接受默认值,答案引擎优化怎么让内容被优先引用 (https://zhangwenbao.com/aeo-answer-engine-optimization-guide.html)里有同样的取舍讨论。 行,但你要接受它的默认答案。图标那边的默认是灰色的通用图标,名字那边的默认是你的域名。对于域名就是品牌名、图标一直没问题的站,这个策略确实没什么损失。 问题在于你并不知道自己属不属于这一类。本次数据里,那5个所有图标声明全部不可用的站,团队大概率都以为自己是有图标的。“不做”和“做了但不知道坏了”,在结果上一样,但后者会让你误以为这件事已经完成了。 ## 这一批数据最让我意外的一条 不是那个4.5 MB的404,也不是四个410。最意外的是兜底路径的可用率只有28%,而这件事居然没有造成任何可见的后果。 容错好的系统会把中间状态的失败全部藏起来,日志里带人来的其实是另一批入口 (https://zhangwenbao.com/ai-referral-source-domestic-entries-gap.html)也是一次被藏住的缺口。 七成的站在这条路上是断的,可它们的搜索结果里照样有图标、广告位上照样有图标——因为head里的声明救了它们。这说明这套机制的容错做得相当好,一条路断了还有别的路。 但容错好也有副作用:它让所有中间状态的失败都不可见。你不知道自己是靠第一条路走通的,还是靠第三条路勉强兜住的,直到某一天最后那条路也断了,你才发现前面几条早就没了。 这正是代劳型规则最难受的地方。禁止型至少会给你一封通知,亲自型至少你自己心里有数,而代劳型是你在一个多路径容错的系统里,永远不知道自己现在靠的是哪一条。 ## 所以最后落到一句话 图标和名字这两件事,做对的成本是半小时,做错的成本是展示层上一个灰方块加一串域名,而且没人会告诉你。 便宜且确定的活该先做,把旧内容更新成AI可信来源的十二步 (https://zhangwenbao.com/revise-old-content-for-aeo-ai-search-optimization.html)里有一批同样便宜的动作。 这个不对称本身就足够构成理由。不是因为它多重要,是因为它太便宜了。在一份排期表里,凡是半小时能做完、收益确定、不需要审批的事,都该排在最前面——哪怕它看起来一点都不性感。 下一篇讲第三类,也就是亲自型:平台只会建议、没有任何工具告诉你做到没有、而这件事完全发生在你自己的服务器上。量的还是同一批站,问题是它们在被问“这个页面变了没有”的时候,答不答得上来。那一篇的数字比这一篇更难看,因为那一层连兜底路径都没有。 ## 如果只做一件事 逐个请求你首页head里声明的每一个图标地址,看它们是不是都返回了一张能读出宽高的图片。就这一件。 一次性排查完就能安心很久,让内容被主动引用的五个维度 (https://zhangwenbao.com/ai-search-content-writing-machine-readable-playbook.html)里也有这类一次到位的动作。 它能一次性排除本文里最严重的那一类问题——声明存在但文件不可用。本次样本里5个站的所有声明全部不可用,这5个站在展示层上的表现,跟一个图标都没声明是一样的,甚至更差,因为它们的兜底路径同样是坏的。 ## 这批数据还有哪些没量 把没做的部分写出来,读者才知道哪些结论可以引用、哪些还得自己验。 抓取路径被挡住这类风险值得单独排查,GEO投毒的三条攻击路径与三层防御 (https://zhangwenbao.com/geo-ai-poisoning-315-deep-analysis.html)里有相关的检查项。 第一,没有比对同一个站的多个图标是不是同一个图案。理论上可以做图像相似度,但那需要另一套处理流程,本次没做。所以“多个候选长得不一样”这个风险,本文只能定性提,给不出比例。 第二,没有测这些图标地址会不会被robots规则挡住。如果一个图标放在被禁止抓取的目录下,它对浏览器可用、对抓取程序不可用,而这种差异本次的抓法看不出来。 第三,也是最实际的一条:没办法知道系统实际选了哪一个。官方没有公开这个信息,搜索结果里也只显示最终结果。所以本文能给的是“候选池干不干净”,给不了“它到底选了谁”。 这一层限制其实正是代劳型规则的本质:你能观察输入,能观察输出,但中间那一步永远是黑的。所以最优策略只能是把输入收敛到唯一,这样输入等于输出。 第四,本次的抓取是从单一网络环境发起的,没有做多地区对照。有些站会按访问来源返回不同的资源路径,理论上图标也可能不同。上一批做多语言实测的时候就撞到过按IP换内容的情况,所以这条不是空担心。如果你的站有地区分流逻辑,这套排查得在每个地区各跑一遍。 第五,样本本身是有偏的。211个域名全部是有一定规模的国际化电商与DTC品牌,不包含小站、不包含内容站、不包含B2B。所以本文所有比例只能代表这一类站,不能外推到整个互联网。但对读这篇文章的人来说,这个偏差方向大概率是有利的——你的同行就在这个样本里。 ## 把限制写出来有什么用 有人会问,把这么多做不到的事写出来,不是在削弱自己的结论吗。恰恰相反。 交代口径的内容更容易被引用,七万五千条答案实证的引用偏好 (https://zhangwenbao.com/ai-search-citation-content-types-geo-strategy.html)给出了数据支持。 一份数据的可信度,不取决于它覆盖了多少,取决于它有没有诚实交代自己没覆盖什么。本文那些能站住的结论——五个站的图标全坏、六成一的站兜底路径断了、四成八的站图标不到48像素——都是在明确的边界内测出来的,边界之外的部分我一句都没说。 反过来,那些不写限制的调研,你根本没法判断哪句能用。看到一份没有交代口径和缺口的数据,正确的态度不是相信,是先问它没量什么。 ## 常见问题解答 ## 图标必须是48的倍数吗? 不是。这是一个流传很广的误传。官方原文写的是必须是正方形、至少8×8像素,然后建议使用大于48×48的图标以获得更好的效果。硬门槛是正方形和8×8,48×48是效果建议。本次实测里有61个站的最大图标不超过48像素,它们全部满足硬门槛,只是清晰度不够。顺带提醒,另外两条常听到的说法也是误传:图标不必是ICO格式,任何有效图标格式都受支持;也不必放在根目录,链接写在首页head里就行。 ## 我声明了好几个图标,系统会选哪一个? 官方没有公布挑选规则,只明说了按主机名定义站点、每个站只支持一个图标。可以确定的是,你无法指定它选哪个。可控的部分是让候选变少、让每一个候选都可用、并保证它们视觉上是同一个图案。本次样本里平均每站声明3.4个,最多的两个站各声明了22个。合理的配置大概是三个:一个标准icon、一个apple-touch-icon,加上根目录那个物理文件。 ## www和裸域需要各配一套吗? 需要。官方说的是按主机名定义站点,所以www和裸域在这套机制里是两个站,各有各的那一个图标。多国站用二级域名分市场的,每个二级域名同理。实际操作中如果你已经做了统一跳转,这个问题会自动消解,因为访问哪个最终都落到同一个主机名上。但如果两个主机名都能独立访问并各自返回内容,那就得各自准备。 ## 同一个站的几个图标必须长得一样吗? 官方没有这条要求,但强烈建议一致。因为你无法指定系统选哪一个,如果几个候选的图案不同,那用户在不同位置看到的可能就是不同的标志。本次实测没有做图像相似度比对,所以给不出这一项的比例,但从格式混用的34个站来看,风险是存在的——不同格式的文件往往由不同流程产出,容易在某次改版之后不同步。 ## /favicon.ico返回404要紧吗? 如果你的首页head里有正确的图标声明,影响有限,因为抓取程序会优先用声明。但如果你什么都没声明,这条兜底路径就是唯一入口,断了等于没有图标。本次样本里37个站没有任何声明,而211个域名里152个的兜底路径拿不到真图标。更需要注意的是返回一整张网页的那50个站,其中最大的一次返回了4.5 MB。 ## 换了图标之后多久生效? 官方的说法是几天到几周不等,取决于系统判断你的内容更新频率。这期间最重要的一条是不要反复改。每次改动都会让系统重新评估,而在它没把握的时候,默认行为是使用其它来源或者直接显示域名。改完之后确认文件本身可用,然后等。 ## 标题尾段写卖点会影响站点名称吗? 会。官方明说系统会考虑标题、标题类元素以及首页上的其它文本。标题尾段是名字的候选来源之一,写成一句促销语或者品类描述,等于往候选池里扔了一个不是名字的选项。本次样本里有站的标题尾段是订单满多少免运费,也有站是一整句产品描述。 ## 为什么我的品牌名不显示,显示的是域名? 最可能的原因是系统对你提供的名字把握不足。官方文档明确写了这种情况下它会用其它来源生成,或者直接显示域名甚至子域名。排查顺序是:先确认首页有没有WebSite结构化数据,再确认og:site_name和标题尾段跟它一致,最后检查是不是用了过于通用的名字。本次样本里有大量域名和品牌名并不相同的站,这一批最容易被显示成域名。 ## 非正方形的图标会被直接拒绝吗? 正方形是官方列出的硬要求,不满足就有被弃用的风险。本次抓到11个非正方形文件,最典型的是一个32×31的——只差一个像素,几乎肯定来自一次自动裁剪。还有一个16×20的竖长方形,以及一个1587×1123的大图。检查方法是读文件真实宽高,不要相信声明里的sizes。 ## 把图标放在CDN上有问题吗? 本次样本里56个站的图标托管在站外主机上,其中绝大多数是电商平台自带的CDN。这本身不是问题,只要那个地址稳定可达。需要注意的是两点:一是那个地址不要被robots规则挡住,二是发版换目录的时候别忘了同步更新head里的链接。本次有一个站的四个图标全部返回410已删除,路径里带着构建版本号,正是这个原因。 ## apple-touch-icon和搜索里的图标是一回事吗? 不完全是。apple-touch-icon主要给iOS主屏用,但它也在官方列出的受支持rel取值里,所以同样是候选之一。本次统计里apple-touch-icon系列一共209个声明,比标准的icon还多。这说明大量声明其实是为移动端准备的,只是顺带进了候选池。至于mask-icon,那是Safari固定标签页用的单色矢量图,跟搜索没关系。 ## 这套排查多久做一次? 跟发布流程绑定比定期做更有效。每次前端发版、每次换主题或模板、每次调整站点名称设置,跑一遍那几个地址就行。本次数据里最典型的两类问题——文件被清理而声明没改、换了图但sizes没改——都发生在发版这个时点上。如果一定要一个周期,季度一次足够,但前提是这个季度里没动过前端。 ## 广告位这个测试还没全量,现在做是不是太早? 不早。原因有两条。第一,同一套数据早就在自然结果里被使用了,你现在做的任何改动,在自然结果里立刻有价值,广告位只是顺带。第二,图标的重新抓取需要几天到几周,等测试全量再动手,中间那段时间就是空白。这类事情的成本是固定的、收益是持续的,越早做越划算。 ## 我的sizes写错了,需要马上修吗? 单看这一项不算紧急,抓取程序会自己读文件真实尺寸。但它是个很好的信号:sizes写错了完全没有惩罚,所以它如果是错的,基本可以断定这个站的图标链路很久没人维护过。建议把它当探针用——发现sizes对不上,就把整条链路都过一遍。本次数据里sizes出错的站,往往同时还有别的问题。 ## 图标和名字这两件事归谁管? 归谁维护站点模板,谁就得管。这在实际团队里是个真问题:投放的人看到广告位不对会去广告后台找原因,做SEO的人不看广告位,而根子往往在前端构建流程上。最省事的做法是把本文那张核对表挂到发布检查清单里,让发版的人顺手跑一遍,不需要任何一方专门立项。 ## 权威参考资料 ## Google商家名称禁双语重复,112个独立站里17个在犯 - URL:https://zhangwenbao.com/business-name-single-form-structured-data-audit.html - 分类:技术SEO - 发布:2026-08-12 | 更新:2026-08-12 - 摘要:同一个品牌,在五个语言版本上给出了五个不同的组织名。这件事在商家资料那边会被判违规,在独立站这边没人管,可两边面对的是同一套实体识别系统。 - 关键词:结构化数据,国际SEO,独立站建站,品牌命名 > **TLDR**:摘要:把170个国际化独立站的首页和297个语言版本页面拉下来,从里面抠出结构化数据和og标签里的品牌名,一共162个不重样的写法,覆盖112个域名。用Google商家资料那张名称禁令清单当尺子量了一遍,第一版量出38个域名有问题,换了个量法之后只剩17个,虚高了2.2倍。真正扎实的结论是另外两条:能装第二个名字的那个字段,90个站里只有7个用了;而112个域名里有86个从头到尾只给出一个名字形态,尺子对它们根本无话可说。 > 摘要:把170个国际化独立站的首页和297个语言版本页面拉下来,从里面抠出结构化数据和og标签里的品牌名,一共162个不重样的写法,覆盖112个域名。用Google商家资料那张名称禁令清单当尺子量了一遍,第一版量出38个域名有问题,换了个量法之后只剩17个,虚高了2.2倍。真正扎实的结论是另外两条:能装第二个名字的那个字段,90个站里只有7个用了;而112个域名里有86个从头到尾只给出一个名字形态,尺子对它们根本无话可说。 2026年8月10日,Google在商家资料的呈现指南里加了一条新规矩,位置在“名称”那一节,写得很短:不允许把同一个商家名用多种文字或多种语言重复写一遍。它给的反面例子是Kafiex/カフィエクス 和Burger King バーガーキング,正面例子就是把后半截删掉,只留Kafiex和Burger King。 这条规则真正扎人的地方在后半句:就算你的实体店招牌上确实是这么写的,也不行。过去很多店主拿门头照片去申诉,理由是我招牌上就这么印的,这条路从这一天起走不通了。 看到这条更新的时候,保哥的第一反应不是去改客户的商家资料,而是打开了自己手上那批国际化独立站的抓取数据。因为这条禁令背后那张完整的清单,可以当成一把现成的尺子,去量一件完全不同的事:你的独立站,到底对外声明了自己叫什么名字,声明了几个。 量完的结果比我预想的复杂。它不只是一个百分比,中间还塞进了一次尺子失效——第一版结论把问题放大了两倍多,而失效的原因不是数据脏,是这把尺子分不清一个词是名字的一部分,还是被加到名字上去的。 这篇文章讲三件事。前面讲禁止型规则长什么样、怎么一眼认出来;中间是那把尺子和它失效的全过程;后面是112个域名的实测明细,以及一份能在发布前跑完的名字盘点动作。 ## Google这次到底禁掉了什么? 先把新规原文的位置和分量说清楚,因为它写在哪一节,决定了你该用什么态度对待它。 不做什么的清单往往比做什么的更好核查,AI内容披露里那份不做什么的清单 (https://zhangwenbao.com/ai-usage-disclosure-negative-list.html)是同一种表达方式。 ## 新增的那一行写在哪 这条更新出现在商家资料呈现指南的名称一节 (https://support.google.com/business/answer/3038177),与它并列的是另外六类被明令禁止的成分。整节的总原则写在最前面:你的名称应当反映商家在现实世界中的真实名号,也就是你门店上用的、网站上用的、信纸上用的、顾客口口相传的那一个。 名称字段属于结构化数据体系的一部分,整套配法可以对照结构化数据怎么配合SEO落地的完整指南 (https://zhangwenbao.com/seo-schema-guide.html)看,里面有各类型的取舍。 这句总原则里有一个词特别关键,叫“一致地使用”。它的意思不是你有一个名字就行,而是你在所有这些场合用的是同一个。规则要的不是名字正确,是名字唯一。这一点后面会反复被验证——本次实测里绝大多数问题,都不是某个名字写错了,而是同时存在好几个都不算错的名字。 新增那一条的完整表述是“重复双语名称/文字音译”,括号里的解释是:把同一个商家名用多种文字或语言重复书写,即便实体店招牌上就是这么呈现的,也不允许。这条更新最早由Barry Schwartz记录下来 (https://www.seroundtable.com/google-business-profiles-disallows-repeated-bilingual-names-41839.html),他还引了日本本地搜索从业者的一段补充:例子虽然用的是日语,但这条规则对任何多文字并用的市场都成立,阿拉伯语、中文、西里尔文一样受管。 ## 为什么招牌照片这条路被堵死了 过去申诉名称问题,最常用的证据就是门头照片。逻辑很朴素:我招牌上印的就是这两行字,我照抄有什么错。审核那边通常也认这个证据,因为“真实名号”的定义本来就指向线下。 线下招牌与线上身份的分工,本质上是实体主页那一套地基问题,实体主页怎么搭才算把品牌身份立住 (https://zhangwenbao.com/entity-home-seo-ai-brand-guide-html.html)里有更完整的拆解。 这次更新把这条路明确堵上了。原文里“即便它在实体店招牌上是这样呈现的”这半句,是专门写给这类申诉的。它等于宣布:招牌是招牌,字段是字段,两者不必一一对应。 这个变化的道理其实站得住。招牌是给站在门口的人看的,它同时承担识别、装饰、告知三重功能,两行字并排是排版选择;名称字段是给一台机器读的,它只承担识别一种功能,第二行字对识别没有增量,只增加歧义。同一段文字,在两个媒介上的职责根本不一样。 顺带说一句,这条规则对中国出海做本地业务的团队影响不小。中英并列的店名在国内是常态,很多人第一次做海外本地资料的时候会习惯性照搬,而这类写法从这次更新起属于明确违规。 ## 那张完整的禁令清单 把这一节里所有“不允许”的成分列成一张表,你会发现它们的共同点非常清晰:凡是加在真实名号之外的信息,一律不许进名称字段。 七条禁令的底层逻辑是实体识别,想把这套语义网络理清楚可以看实体SEO的五阶段构建方法 (https://zhangwenbao.com/entity-seo-guide.html)。 被禁的成分 | 官方给的例子 | 它本质上是什么 | 营销标语 | TD Bank, America's Most Convenient Bank | 广告语 | 地点信息 | Holiday Inn (I-93 at Exit 2) | 该放在地址字段的东西 | 营业时间 | Regal Pizzeria Open 24 hours | 该放在营业时间字段的东西 | 电话或网址 | Airport Direct 1-888-557-8953 | 该放在联系方式字段的东西 | 特殊字符与无关法律术语 | 百分号、美元号、斜杠、LLC、LTD、INC | 工商登记信息与排版符号 | 产品或服务信息 | Verizon Wireless 4G LTE | 该放在品类与服务字段的东西 | 重复双语名称与音译 | Kafiex/カフィエクス | 同一个名字的第二个书写形态 | 看出规律了吗。这七条没有一条在说“你不能有这些信息”,它们说的都是“这些信息不该待在名称字段里”。名称字段只装名字,别的信息各回各家。这是一条关于字段职责的规则,不是一条关于内容的规则。 把最右边那一列竖着读一遍,你会发现每一条被禁的成分,在这套资料体系里都有一个专属的容身之处:地址有地址字段,营业时间有营业时间字段,电话有联系方式字段,品类有类目字段,法人信息有单独的认证流程。七条禁令背后是七个已经存在的字段,规则不是在剥夺你表达的机会,是在拒绝你把它们全挤进同一个格子。 这个视角很重要,因为它决定了你的改法。如果你以为规则在禁止某类信息,你会纠结“那我怎么让用户知道我在这个城市”;如果你知道规则只是在指定位置,你就只需要把那段文字挪个地方。删掉不等于丢掉。 ## 违规的后果不是排名下降 这一节的结尾有一句话,比前面七条加起来还重要:在商家名称里包含不必要的信息是不被允许的,并且可能导致你的商家资料被暂停。 资料被暂停之外,品牌名还有另一类下行风险,品牌被仿冒抢排名的五步应对实战 (https://zhangwenbao.com/brand-domain-impostor-seo-nanoclaw-protection.html)记录过一次完整的处置过程。 请注意这个词,暂停。不是排名下降,不是展示机会减少,不是效果打折。是这份资料整个从系统里下线,你得走申诉流程才能拿回来。而申诉需要材料、需要时间,中间那段空窗期你在地图上就是不存在的。 这个后果的形状跟你熟悉的那些SEO后果完全不同。排名下降是连续的,你可以看着它一点点掉,可以边观察边调整,最坏情况也还有流量。暂停是二值的,前一天还在,后一天整条不见,中间没有过渡。连续的风险你可以管理,二值的风险你只能规避。 更麻烦的是这类处罚的触发时机。它不跟着算法更新走,而是跟着审核走——可能是一次用户举报,可能是一次例行复查,也可能是你自己动了某个无关字段触发了重审。所以“已经这么写了三年都没事”这句话,在禁止型规则面前完全没有说服力。没被抓到不是通过了,只是还没轮到你。 ## 什么样的规则算禁止型规则? 把这条新规看成一次孤立的政策更新,你能做的只有改一次名字。把它看成某一类规则的样本,你才能在下一条更新出来的时候,第一时间知道该拿多大力气去应对。 同一份文档里不同段落的效力差别很大,robots规则的星号对某些爬虫无效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)就是一次误读官方措辞的代价。 ## 平台介入你这件事,一共有三种方式 翻遍这些年的官方文档,你会发现平台跟你之间的每一条规则,背后都藏着一个没写出来的主语:这件事到底谁动手。答案只有三个。 这三类介入方式在AI搜索时代表现得更明显,GEO到底怎么落地的实施策略 (https://zhangwenbao.com/geo-strategy.html)里能看到平台代劳的比例在变高。 类型 | 谁动手 | 你能做的动作 | 违反或不做的后果 | 禁止型 | 平台立规矩,你只能删 | 把多出来的那部分拿掉 | 处罚,比如资料被暂停 | 代劳型 | 平台自己算,你只能摆原料 | 把候选收敛到一个 | 它挑了一个你不想要的 | 亲自型 | 只有你能做,平台只会建议 | 全部,也没人替你兜底 | 效率损失,而且没人通知你 | 这条商家名称规则是标准的禁止型。判据只有一个:违反它的后果是处罚,而不是效果差。效果差是一根连续的曲线,你可以选择投入多少;处罚是一条线,过线和不过线之间没有中间态。 这个三分法不是我发明的分类癖。它的实用价值在于回答一个每天都要回答的问题:这条新出的规则,我该派几个人、花几天、做到什么程度算完。三种类型给出的答案完全不同,而把类型认错,代价就是把力气花在收益为零的地方。 ## 三十秒就能分辨的两个信号 不用把整份文档读完,看两个地方就够。 官方文档的措辞差异同样体现在结构化数据上,Schema对AI搜索到底有没有用的官方说法与实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)对照过两种表述。 第一个信号是这段话住在哪一栏。写在“政策”“指南”“要求”下面的,通常是禁止型;写在“最佳实践”“建议”“提示”下面的,通常不是。Google的文档结构对这一点相当讲究,同一件事写在两个位置,力度完全不同。举个具体的:结构化数据那套文档里,“必需属性”和“推荐属性”是分开列的两张表,前者缺了整段结构化数据作废,后者缺了只是少一点信息量。 第二个信号是措辞。禁止型规则会出现“不被允许”“不得”“可能导致”这类词,而且后面往往紧跟一个具体的后果名词,比如暂停、拒绝、移除。只要看到一个具体的处罚名词,基本可以断定是禁止型。建议型的措辞则是“我们推荐”“考虑使用”“有助于”,后面跟的是收益不是后果。 还有一个更省事的土办法:搜这段文档里有没有出现“申诉”这个词。有申诉流程,说明有处罚;有处罚,说明是禁止型。建议型规则不需要申诉,因为没人罚你。 ## 把三类规则各举一个你熟悉的例子 禁止型:商家名称不许加地区词,违反会被暂停。你唯一能做的动作是删。 代劳型最典型的另一个例子是多语言别名,hreflang备用网址被当成规范页别名这件事 (https://zhangwenbao.com/hreflang-alternate-url-alias-not-indexed.html)就是系统自己决定的。 代劳型:搜索结果里显示的站点名称。官方文档写得明明白白,它会参考结构化数据、og:site_name、标题以及首页上的其它文本,最后由系统挑一个。你没有一个字段可以把它写死,你只能让候选变少、变一致。 亲自型:服务器该不该支持条件请求以省下抓取预算。这件事百分之百发生在你的机器上,平台只能建议,而且没有任何一个官方工具会告诉你你做到了没有。做与不做,只有你自己知道。 ## 禁止型规则的性价比长什么样 这是最容易被误判的一层。很多团队把合规当成优化在做,投入了大量工时想“做到最好”,可禁止型规则根本没有最好这一档。 把合规动作排进上线流程比事后补更省事,新网站前十二周的技术地基清单 (https://zhangwenbao.com/new-website-seo-optimization-checklist.html)里有可以直接抄的排期。 合规不是优化,它没有上不封顶的收益,只有一条及格线。过了线,多做一分钱的收益都没有;没过线,前面做的所有优化一次归零。所以它的正确姿势是尽快过线,然后把力气挪走,而不是在这里精雕细琢。 保哥去年带过一个做户外装备的客户,团队在商家资料上花了三周,反复打磨描述文案、补图片、调品类,唯独名称字段里那个多出来的城市名一直没动,因为“大家都这么写”。结果资料被暂停,申诉走了十一天。那三周的打磨,在那十一天里一分价值都没产生。 这件事之后我们换了个做法:任何一批优化动工之前,先花两小时把所有禁止型的点位过一遍,确认没有一个踩线的,再开始做别的。这两小时不产生任何可见收益,它买的是后面那三周不会归零。 ## 为什么“大家都这么写”是最贵的一句话 禁止型规则里有一类特别隐蔽的风险,就是行业惯例跟规则本身冲突。名称里加城市名这件事,在很多品类里是几十年的老习惯,同行都这么写,看起来风险很低。 行业惯例撞上平台清理是什么后果,阿里国际站五百九十万页面被清零那次的复盘 (https://zhangwenbao.com/alibaba-aigc-google-deindex-dtc-seo-guide.html)是个规模足够大的样本。 但禁止型规则的执行不看密度。一百家都违规,不等于罚不到你;它只等于还没轮到。真正决定你会不会被抓的,是有没有人举报你、有没有触发复查,而这两件事跟同行怎么写完全没有关系。 更现实的一点是,这种时候你反而应该更早改。因为一旦平台开始集中清理某一类违规,同行会一批一批地掉,而你的申诉会排在那一批的队伍里。抢在集中清理之前改完,成本是零;等清理开始,成本是排队。 ## 为什么一条本地商家的规则值得独立站主看? 你的独立站没有商家资料,这条规则管不到你。但它背后那张清单,管的是一件所有站都在做的事。 线下与线上的经验可以互相搬,把线上SEO思维搬到实体店的做法 (https://zhangwenbao.com/seo-ux-cro-boost-brick-mortar-retail.html)是反方向的一次迁移。 ## 你的站也在声明自己叫什么名字 只要你的首页里有结构化数据、有og标签、有标题,你就已经在对外声明自己的名字了,而且不止声明了一处。常见的至少有四处:结构化数据里的组织名、og:site_name、页面标题的尾段、还有域名主体本身。 品牌名的一致性最终会体现在品牌权威度上,品牌权威度与域名权重的区别和提升方法 (https://zhangwenbao.com/moz-ba-brand-authority-seo.html)讲了这套指标怎么读。 这四处任何一处都可能被系统拿去用。Google自己在站点名称的文档 (https://developers.google.com/search/docs/appearance/site-names)里说得很清楚,它会同时参考结构化数据、og:site_name、标题和首页上的其它文本,而且明确写着“表明你的站点名称偏好”——用的是偏好这个词,不是设置。你只能表达偏好,最后显示哪一个,不是你说了算。 同一份文档还有一句话更值得记:如果系统对你提供的名字不够有把握,它可能会用其它来源自己生成一个站点名,或者直接显示你的域名甚至子域名。不确定的代价不是空白,是它替你决定。而让它不确定的最常见原因,就是你在这四处给了它四个不一样的答案。 ## 那张禁令清单可以直接搬过来当尺子 既然商家资料那边已经把“名称字段里不该有什么”写成了七条明文,那这七条就是一把现成的、有权威出处的尺子。把它拿过来量独立站的名字字段,等于是在问一个从来没人量过的问题: 借用别处的清单当尺子有风险,最佳实践清单里九条查得到出处八条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)记录过一次核对过程。 在一个没有执法的地方,人们会往名字里塞多少不属于名字的东西? 这个问题值得量,因为它的答案关系到一件很实际的事:当AI系统需要把你的品牌跟一个实体对应起来的时候,它面对的是几个名字。名字越多、越不一致,它越可能挑一个你不想要的,或者干脆退回去显示你的域名。 这种“借一个产品的执法清单,去审另一个没人执法的地方”的做法,本身就值得说一句。平台的各条产品线共享的是同一套关于实体识别的底层判断,只是执法力度不同。有执法的那条线,通常把话说得最明白——因为它必须写清楚才能罚人。所以那份写得最狠的文档,往往就是理解整套系统的最好入口。 ## 这批数据是从哪来的 样本是211个国际化的独立站与电商品牌域名,覆盖北美、欧洲、北欧、日韩以及中国出海品牌,品类横跨服装、户外、家居、母婴、美妆、3C与食品饮料。抓下来的东西有两层:170个域名的首页可解析,另外从这些站的hreflang表里挑出297个语言版本页面,也逐个抓了正文。 同一批国际站还被用来量过别的东西,一万个电商站的网址结构实测结论 (https://zhangwenbao.com/why-most-ecommerce-websites-dont-use-flat-urls.html)是另一次大样本抓取。 从每一份HTML里抠三样东西:结构化数据里所有组织类节点的name、legalName、alternateName;meta标签里的og:site_name和application-name;还有页面标题。组织类节点这个范围包括Organization、Corporation、OnlineStore、WebSite、Brand、LocalBusiness、Store以及各类具体门店类型,因为实际站点用哪一个的都有。 全部去掉多余空白之后,按“域名加名字”这个组合去重,最后剩下162条不重样的记录,覆盖112个域名。之所以按这个组合去重而不是按名字去重,是因为同一个写法在同一个站上出现十次和出现一次,说明的是同一件事,不该被计十次。 ## 这套采样有哪些先天缺口 写在前面,免得后面的数字被过度解读。第一,能抓到的语言版本数量取决于该站hreflang表的完整度,声明得少的站自然暴露得少,所以“形态数”这个指标对不同站不是等价的。第二,有41个域名的首页拿不到可解析内容,其中相当一部分返回的是人机验证页,这些站完全没进统计。 只看初始HTML会漏掉脚本注入的内容,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)解释了这两层的差别在哪。 第三,也是最重要的一条:本次只看声明,不看渲染。有些站的名字是前端脚本运行之后才写进结构化数据的,直接抓HTML拿不到。所以“没有结构化数据”这一档里,混着一部分其实有、只是不在初始HTML里的站。这条缺口会让“声明率”偏低,但不影响“同一个站给了几个形态”这个核心指标——因为那是在已经拿到的样本内部做的比较。 把缺口写出来还有一个用处:它决定了哪些结论可以引用、哪些不可以。“有多少站声明了结构化数据”这个数字,因为渲染缺口的存在,只能当下限用;“给出多少个名字形态”这个数字,因为是站内比较,可以直接用。同一批数据里,不同结论的可靠度是不一样的,这一点在引用别人的调研时也值得多留个心眼。 ## 为什么选“同一个站给了几个名字”当核心指标 本来可以有很多种量法:量名字长度、量有没有品类词、量和域名的相似度。最后选定“形态数”,理由有三条。 指标能不能被读者自己复现很关键,三百个站实测出来的收录速度指标怎么读 (https://zhangwenbao.com/seo-kpi-guide.html)也是按这个标准挑的。 第一,它不需要任何外部知识。判断一个名字对不对,你得知道这家公司真名叫什么;判断一个站给了几个名字,只需要数一数。不依赖外部知识的指标,才可能在几百个域名上跑得动。 第二,它直接对应规则要保护的东西。商家资料那条总原则说的是“一致地使用”,形态数就是一致性的直接度量:形态数等于一,一致;大于一,不一致。 第三,它对读者可复现。任何人打开自己的站,把几个语言版本的名字抄下来,五分钟就能算出自己的形态数。一个读者算不出来的指标,写进文章里只是装饰。 ## 结构化数据里的名字字段,大家都填了什么? 在动尺子之前,先看一眼这批站的基本盘。这一步没有判断,只有清点。 字段填得对不对决定别人怎么认你,GitHub Pages寄生SEO的借力实战 (https://zhangwenbao.com/github-pages-seo-parasite-seo-strategy.html)里身份声明同样是关键一环。 ## 三个数字先摆出来 项目 | 站数 | 占可解析首页的比例 | 首页有组织类结构化数据节点 | 90 | 52.9% | 其中给了name | 87 | 51.2% | 给了legalName | 17 | 10.0% | 给了alternateName | 7 | 4.1% | 同一页出现多于一个name | 9 | 5.3% | 有og:site_name | 78 | 45.9% | 层级与身份这两类结构化数据常常一起配,Shopify博客多级面包屑的三种方案 (https://zhangwenbao.com/shopify-blog-breadcrumb.html)可以顺手一起做掉。 组织类节点该选哪个类型是个高频困扰,Shopify的一百二十八种结构化数据类型怎么挑 (https://zhangwenbao.com/shopify-schema-seo-guide.html)给了一张选型表。 第一个值得停下来的数字是alternateName那一行。90个站里只有7个用了这个字段。而这个字段的官方定义 (https://schema.org/alternateName)特别直白,就一句话:这个东西的一个别名。Google的组织结构化数据文档 (https://developers.google.com/search/docs/appearance/structured-data/organization)里也把它列在推荐属性清单的第二位,说明是“如果适用的话,你的组织常用的另一个名字”。 第二个值得停下来的是最上面那一行:能被解析的170个首页里,只有90个带了组织类的结构化数据。剩下80个站在这个层面上,压根没有正面声明过自己是谁,系统只能从标题、og标签和正文里去猜。这批样本全是有一定规模的国际品牌,不是小站。 ## 没人用别名字段,别名都跑哪去了 别名当然是存在的。一个品牌在日本市场被写成片假名、在中国市场被写成中文、法务上还有一个带后缀的公司全称——这些都是真实存在的第二个名字。 把分散的结构化数据聚合成一份是解法之一,Schema聚合的五步接入方法 (https://zhangwenbao.com/yoast-schema-aggregation-agentic-web-seo.html)讲了具体怎么合并节点。 问题是它们没被放进那个专门装别名的字段。它们跑到了标题里,跑到了og:site_name里,跑到了不同语言版本页面的组织名里。人们不是不需要第二个名字,是没把它放进该放的地方。 这句话正好是商家资料那条新规的另一面。商家资料那边禁止你把第二个书写形态塞进名称字段,是因为它有单独的位置管这件事;独立站这边没有执法,于是第二个形态就自由生长到了每一个能放文字的地方。 把两边并排看,会得出一个有点反常识的结论:同一家公司,在有执法的那个产品里名字规规矩矩,在没执法的自家站上反而一团乱。这不是因为团队水平不同,往往就是同一批人;区别只在于一边有人查、一边没人查。 ## legalName那17个站在干什么 17个站填了legalName,这个比例比alternateName高一倍多。原因不难猜:法人全称是财务和法务流程里必然存在的信息,模板里加一行成本很低;而“我们的另一个常用名是什么”这个问题,没有任何一个内部流程会逼你回答。 法人与商品标识分属不同体系,跨境电商GTIN怎么申请与收录 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)是另一个容易被混进错误字段的例子。 值得注意的是,填了legalName的站,name字段普遍是干净的。这两件事是因果关系:有了专门放法人名的地方,法人名就不会去挤主名。反过来,那几个把S.r.l、LLC、Inc写进name的站,无一例外都没填legalName。 这条经验可以直接迁移到别名上——你之所以把片假名写进主名,很可能只是因为你没意识到有个字段专门装它。字段的存在感,很大程度上决定了它会不会被填对,而结构化数据里那几十个推荐属性,绝大多数都栽在这一点上——不是不该填,是没人知道它在那儿。想验证这一点很容易:打开官方那份推荐属性清单,逐条问自己“这个字段我们填了吗”,你会发现绝大多数字段你连听都没听过,而它们各自都在替某个本来会产生歧义的信息兜底。 ## 同一页出现多个name的那9个站 还有一个数字容易被跳过:9个站的首页上,组织类节点给出了不止一个name。这跟“不同语言版本不一致”是两回事——这是同一个页面、同一次加载里,就存在多个身份声明。 同一页面多个节点之间该怎么互相引用,用SignificantLink和RelatedLink表达页面关系 (https://zhangwenbao.com/significantlink-relatedlink-schema-internal-linking.html)里有对应的写法。 成因通常有三种。一种是页面上同时挂了Organization和WebSite两个节点,两边的name填得不一样;一种是插件和主题各自注入了一段结构化数据,互相不知道对方的存在;还有一种是像avocadogreenmattress那样,本身就有多家门店节点。 前两种是需要修的。同一个页面上给出两个不同的身份,比在两个页面上给出两个不同的身份更糟,因为它连“不同市场用不同名字”这个借口都没有,纯粹是内部冲突。 排查方法:把首页的所有ld+json块拿出来,逐个看它的类型和name。如果发现两个块的类型不同但都算组织类,先确认它们是不是在描述同一个实体;是的话,把name统一,或者干脆合并成一个节点用 @id互相引用。 ## og:site_name的填写率也值得看一眼 78个站填了og:site_name,比例45.9%,比结构化数据组织节点的52.9% 略低。这两个数字放在一起看,会发现一个有意思的分布:并不是所有填了结构化数据的站都填了og:site_name,也不是所有填了og:site_name的站都有结构化数据。 两个部门各填一遍是典型的协作问题,SEO汇报怎么让不同部门看到同一份事实 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)提过一套对齐办法。 这说明这两处的填写是由不同的原因驱动的。结构化数据往往来自SEO插件或者专门的开发任务;og:site_name往往来自社交分享的需求,是市场部门提的。两个部门、两条链路、两次各自的填写,天然容易不一致。 这也是为什么本文一直强调把它们抄进同一张表——它们在组织架构里本来就不挨着,只有在你的表格里才会挨着。 ## 先看一个最直接的对照 在这批数据里,只有一条名字记录同时含两种书写系统:innisfree的组织名写成“이니스프리 (innisfree)”,韩文加括号加拉丁文。这就是商家资料新规禁掉的那个形态,一字不差。 标题会被系统重写这件事已经有实测,Google用AI重写标题的改写率与应对 (https://zhangwenbao.com/google-ai-headline-rewrite-seo.html)给出了七成以上的改写比例。 但如果把范围放到页面标题,混两种书写系统的一下子变成9个站:DJI写成“DJI大疆创新 - 官方网站”,Nike中国站写成“耐克Nike-耐克(Nike)中国官网-NIKE中文官方网站”,一个标题里“耐克”出现两次、Nike出现三次;HAY丹麦站写成“HAY品牌官网”;Swarovski的标题里同时出现了汉字、假名和韩文。 同一件事,在名称字段里几乎绝迹,在标题里遍地都是。这不是巧合,这是因为标题从来没有人管。 要给标题说句公道话:标题的职责本来就包含吸引点击,两种写法并排能同时接住两拨搜索词,这个做法在中文市场是有依据的。问题不在标题本身,在于站点名称系统会去读标题。你为搜索结果标题优化的那一串字,会顺带成为“这个站叫什么”的候选来源之一。 这就是为什么把alternateName填上很划算:你把片假名和中文名正式登记在别名字段里,标题里写什么就不再是唯一的线索了。明牌一出,猜测的空间就小了。 ## 顺手记一个细节:Nike那个标题 “耐克Nike-耐克(Nike)中国官网-NIKE中文官方网站”这一串,值得单独看两眼。它里面的Nike出现了三次,大小写还不一致——两次首字母大写、一次全大写;“耐克”出现两次,其中一次带括号跟在Nike后面。 标题要同时接住点击和识别两件事,文章标题怎么写才有人点的十个技巧 (https://zhangwenbao.com/how-to-write-catchy-article-titles.html)里有兼顾的写法。 如果把商家资料那七条禁令套上去,这一串至少踩中三条:重复双语名称、地点信息、营销语。当然它不在商家资料里,没人会罚它。但把它当成“这个站叫什么”的输入信号,系统能从里面读出的候选就有好几个:耐克、Nike、耐克中国官网、NIKE中文官方网站。四个候选里,只有前两个是名字。 ## 那把尺子第一次给出的数字为什么是错的? 接下来是本次最值得写下来的一段。我把七条禁令写成七个匹配规则,跑完162条记录,拿到了第一版结果——然后花了半小时把它推翻。 两套口径算出相反结论而且都没算错,商品页推荐位两套报表打架的那次复盘 (https://zhangwenbao.com/product-page-recommendation-attribution-mismatch.html)值得对照着读。 ## 第一版结果长这样 禁令 | 命中条数 | 涉及域名 | 地点信息 | 33 | 18 | 产品或服务信息 | 12 | 8 | 营销标语 | 8 | 8 | 特殊字符或法律术语 | 5 | 5 | 两套文字并列 | 2 | 2 | 电话或网址 | 2 | 2 | 合计 | 59条 | 38个域名 | 一张自洽的表最容易骗过自己,调研数据里没有一个非会员却写给非会员看 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)是同一类陷阱。 38除以112,得33.9%。三分之一的站在名字字段里塞了不该塞的东西。这个数字看着就很适合当标题。 而且它内部的结构看起来也很合理:地点信息排第一,符合国际化品牌的直觉;两套文字并列只有2条,符合“这条规则刚出、还没人踩”的预期。没有任何一项显得离谱。这正是最危险的地方——一张自洽的表,比一张离谱的表更难被怀疑。 ## 然后我去翻了具体例子 这一步是上一批批次留下来的规矩:任何一个准备用出去的统计结论,先给它配三个具体例子,而且专门去找看起来最不像的那几组。这次翻出来的第一组就出事了。 翻具体案例是发现口径问题的唯一办法,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)也是这么被翻出来的。 被判“地点信息”的记录里,有Flying Tiger Copenhagen、Audo Copenhagen、Typology Paris。这三家公司的注册名字里本来就带着这个城市名,Flying Tiger Copenhagen就叫这个,不叫Flying Tiger。被判“产品或服务信息”的里面有Avocado Green Mattress、Chubbies Shorts、Outdoor Voices、Columbia Sportswear、Brooklyn Bedding、Function of Beauty——每一个都是完整的注册商号。 换句话说,尺子把品牌名本身当成了违规。它看见Copenhagen就判地点,看见Mattress就判品类,完全不管这个词是不是名字的一部分。 顺带说个题外话:Outdoor Voices这个名字里的Outdoor,既是品类词又是品牌名的一半,这种情况在DTC品牌里特别常见——大家起名的时候就爱用品类词,因为好记好搜。所以任何一把靠词表判品牌名的尺子,在这个人群上的误报率注定高得离谱。 ## 失效的根子在哪一层 回头看商家资料那一节的原话,它说的是“在商家名称里包含不必要的信息”。不必要,意味着有一个必要的基准存在——那个基准就是商家的真实名号。规则判的从来不是词本身,是这个词相对真实名号是多出来的还是本来就有的。 同一批数据里另一把尺子也出过类似问题,品牌词和非品牌词那条线画在哪 (https://zhangwenbao.com/brand-nonbrand-split-grounding-query.html)记录了检测器被单个停用词压垮的过程。 我的第一版尺子里根本没有这个基准。它是一把只认词表的尺子,而词表分不出“名字里的词”和“加在名字上的词”。这是本次测量的核心教训,也是三个批次以来第三次撞上同一类问题:指标本身没有任何异常,报警的只有具体案例。 前两次的失效方式跟这次不一样,但结果的方向惊人地一致——都是让问题虚高。第一次是语言检测器里放了一个跨语言撞车的停用词,把分数表整个压垮;第二次是把网址里的纯数字一律当噪声删掉,结果把五寸刀和七寸刀判成了同一件商品。三次失效,三种成因,同一个方向。 这个方向性偏差本身就值得警惕。它大概率不是巧合:一把粗糙的尺子倾向于把“不确定”当成“命中”,因为命中需要一个匹配,而不命中需要证明所有匹配都不成立。宽松的匹配天然产出更多的阳性。 ## 换一个基准重新量,结论变成什么? 修法其实很朴素:不给每个名字单独判分,而是先给每个域名找一个属于它自己的基准,再看别的写法相对这个基准多出了什么。 换个连接键结论就变了,五个渠道加起来一百五十九个百分点 (https://zhangwenbao.com/comparison-shopping-co-presence-join-key.html)是同一类基准问题。 ## 基准怎么定 对每一个域名,把它所有出现过的名字形态收集起来,全部切成词序列,取这些序列的最长公共开头,就是这个站的基线名。 基线名和域名主体常常不一致,独立站起名的命名策略与SEO避坑 (https://zhangwenbao.com/domain-generator-naming-strategy-tld-seo-guide.html)解释了这两者该怎么协调。 Flying Tiger Copenhagen在样本里只有这一个形态,公共开头等于它自己,多出来的部分是空,不判。Brompton有五个形态,公共开头是Brompton,那么UK、USA、Deutschland、France、日本 这五个尾巴就是多出来的,判。同一个词Copenhagen,在一个站上不判,在另一个站上要判,判据是这个站自己的其它版本。 这里有一个必须承认的设计取舍:取最长公共开头,意味着这把尺子只认前缀式的增量。如果某个站的两个形态是Brompton和UK Brompton,公共开头就是空,它会掉进另一类。实际数据里这种情况极少,因为品牌名加尾巴是压倒性的习惯——但这个假设写在这里,读者才知道结论的边界在哪。 ## 顺带解决了一个更难的问题 这个改法还带来一个我没预料到的好处:只有一个名字形态的站,尺子会自动说测不出。 承认测不出比硬给结论重要,测试赢了上线却掉的那二十六天 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)也是靠承认边界才找到原因。 112个域名里,有86个从头到尾只给出一个写法。对这86个站,我没有任何基准可以对照,也就没有任何依据说它多写了东西。第一版尺子会硬判,第二版尺子直接弃权。 上一批的教训里有一句话:一把诚实的尺子应该在没把握的时候说没把握。这次它自己做到了,而且弃权率高达76.8%。这个数字本身就是一条结论:绝大多数站根本没暴露出足够的信息,让任何人能判断它的名字对不对。 弃权率高到这个程度,其实说明了尺子的另一个特性:它只在你自己给出对照组的时候才工作。这跟人工审核完全相反——人工审核可以拿外部知识来判断“Flying Tiger Copenhagen是不是真的叫这个”,而一把只用站内数据的尺子做不到,它也不该假装做得到。 ## 为什么不干脆去查一次工商注册 这是我认真考虑过又放弃的方案。理论上,拿每个品牌的注册商号当基准,比拿站内公共开头当基准准确得多。 一个品牌几十个注册主体是常态,建一个大站还是多个小站的取舍 (https://zhangwenbao.com/one-authority-site-vs-multiple-niche-sites-seo-decision.html)里讨论过主体分散带来的代价。 放弃的理由有三条。第一,跨国品牌的注册主体往往和消费者认知的品牌名不是一回事,Away的注册主体是JRSK Inc.,拿它当基准的话,Away这个名字本身反而成了违规。第二,一个品牌在几十个国家有几十个注册主体,选哪个当基准本身就是个判断题。第三,也是最实际的:这条路没法自动化,而一个只能手工做的判据,写进文章里对读者没有价值。 拿站内数据当基准的最大好处是,读者能自己复现。你不需要任何外部数据库,把自己所有语言版本的名字字段抠出来排一列,公共开头一眼就看出来了。 ## 两版结果并排放 口径 | 命中条数 | 涉及域名 | 域名占比 | 第一版:按词表直接判 | 59 | 38 | 33.9% | 第二版:按本站基线判增量 | 37 | 17 | 15.2% | 虚高倍数 | 1.6倍 | 2.2倍 | — | 两版结论并排放是最好的自证方式,给那条建议配一个注定无效的对照组 (https://zhangwenbao.com/geo-tactic-control-group-evidence-test.html)用的是同一种做法。 分项差得更狠。“产品或服务信息”第一版是12条8个域名,第二版只剩1条1个域名,虚高8倍,因为这一项几乎全是把品牌名本身当成了品类词。“营销标语”从8条掉到1条,理由一样:Mango Shop、On Shop、NARWAL Official这些,在第一版里被当成加了修饰,第二版里发现它们各自都是那个站唯一的写法,判不了。 ## 有一件事在两个版本里是一样的 这一点值得单独说,因为它跟上一批得到的教训完全吻合:同一批脏数据,对不同结论的污染程度差别巨大。 排序类结论比比例类结论更抗误差,埋点之前先把测量框架设计清楚 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)讲了指标选型的次序。 受影响最狠的是所有的比例类结论——三分之一变成七分之一,某一项虚高八倍。但有一条结论在两个版本里岿然不动:地点信息是最主要的附加成分,遥遥领先其它各项。第一版是33条排第一,第二版是26条排第一,占比从56% 升到70%,排序一次都没变过。 这告诉我们一件很实用的事:如果你的结论是“哪一类最多”,它对测量误差的抵抗力,比“有百分之多少”强得多。做数据的时候,能用排序说清楚的事,尽量别用绝对比例说。排序需要的只是误差在各组之间大致均匀,比例需要的是误差接近零。 ## 这次失效有什么可固化的动作 把它写成三条,都是下次动手前能直接照做的。 把验证动作固化成流程比记在脑子里可靠,日志分析一步步挖出AI爬虫真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)里有一套可复用的核对顺序。 第一,任何一把靠词表判断的尺子,先问自己有没有基准。如果规则原文里出现了“不必要”“多余”“额外”这类相对性的词,那它一定需要基准,而基准必须从数据内部生成,不能从词表里来。 第二,抽样验证的时候不要随机抽,专门去找那几组“看起来最不像违规的”。随机抽三十条,你大概率抽到的都是真阳性;专挑最可疑的抽五条,一条就能把尺子打回去。 第三,两版结论并排放进文章,而不是只保留正确的那一版。读者需要知道的不只是答案,还有这个答案差点错成什么样。 ## 17个域名到底加了什么在名字上? 现在可以放心地看第二版明细了。19个域名能定出基线,其中17个的名字上确实挂了基线之外的东西,一共37条。 用户和系统看到的信息不是同一份,用户扫完一整屏一个都没点开这件事 (https://zhangwenbao.com/product-list-item-attributes-silent-rejection.html)说明了默默流失的部分。 ## 分项分布 加上去的成分 | 条数 | 域名数 | 典型样子 | 地点 | 26 | 12 | Brompton UK、IKEA Denmark、Dreame Canada | 其他附加词 | 5 | 4 | Casper Sleep、Swarovski Organization | 法律术语 | 5 | 4 | Mejuri Inc、Purple Innovation, LLC. | 另一套文字 | 1 | 1 | Brompton日本 | 产品或服务 | 1 | 1 | On|Swiss Performance Running Shoes & Clothing | 营销语 | 1 | 1 | On Shop | 分项集中在少数几个站上是常见分布,信息词流量过大的六大危害与破局 (https://zhangwenbao.com/informational-keywords-traffic-dtc-ecommerce-seo-strategy.html)也遇到过同样的集中度。 地点一项占了26条,是绝对主力,而且分布高度集中在几个站上。加国家和地区,是国际化品牌给名字加尾巴的默认做法。 为什么会这样,其实一点都不难理解。运营一个多国站的团队,最日常的困扰就是分不清自己在看哪个市场的后台。给每个站的名字后面加个国家代码,是内部辨识的最省事的办法——它解决的是团队自己的问题,代价却由外部系统承担。那个后缀是给你自己看的,可它被写在了一个对外声明的字段里。 ## 三个把这件事做到极致的站 Brompton是最典型的一个。这家做折叠自行车的英国品牌,在五个语言版本页面上给了五个不同的组织名:Brompton UK、Brompton USA、Brompton Deutschland、Brompton France、Brompton日本。一个品牌,五个名字,其中日本那一个还顺带把书写系统也换了。如果这五个名字出现在商家资料里,五条全部违规,其中一条同时违反两项。 多市场品牌的命名习惯值得单独看,带连字符的域名到底伤不伤SEO (https://zhangwenbao.com/hyphenated-domain-name-seo-impact-overseas-site-decision.html)也是同一类历史包袱。 IKEA给出的是IKEA Denmark、IKEA Estonia、IKEA Portugal。Jackery更全:Jackery Deutschland、Jackery Australia、Jackery EU,还有一个Jackery korea——首字母是小写的,说明这一条是拼出来的,不是人写的。 那个小写的korea很有信息量。人在手写名字的时候不会把国名首字母写成小写,只有把语言代码直接拼在品牌名后面的程序会这么干。一个字母的大小写,泄露了整条数据的生成方式。顺着这条线索去看,Jackery那四个名字大概率出自同一段模板逻辑:品牌名加空格加地区标识,而地区标识取自站点配置里的原始值,没有做首字母大写处理。 这类细节的价值在于,它把“该改哪儿”从二十个页面收窄到了一段代码。你不需要一个个改名字,你需要改那段拼接。 ## 还有一批加得更含蓄的 不是所有的尾巴都是国家名。样本里还有几个是别的东西:casper.com除了Casper还给出Casper Sleep,Sleep是品类也是品牌曾用名的一部分;monos.com给出Monos United Kingdom,把国名写全了;menuspace.com给出Audo Copenhagen U.S.,缩写带点;stanley1913.com给出Stanley 1913 CA;untuckit.com给出UNTUCKit Canada和UNTUCKit UK;wusthof.com的爱尔兰站给出WÜSTHOF Germany。 产地与品类信息该放哪个字段有讲究,Shopify图片SEO从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)也强调过字段职责。 最后这个特别值得玩味:爱尔兰站的组织名里写的是Germany。它想说的大概是“德国的双立人”,是一种产地背书。但站在系统的角度,这就是一个在爱尔兰目录下、自称德国的组织。产地信息有专门的表达方式,塞进名字里只会制造混乱。 rab.equipment则给出了五个带注册商标符号的形态:Rab® US、Rab® CA、Rab® UK、Rab® EU、Rab® NO。商家资料那七条禁令里,特殊字符是明确被点名的一类,而注册商标符号正是典型的特殊字符。它同时踩了地点和特殊字符两条。 还有一个特别的:avocadogreenmattress.com的首页上,同一个页面里挂了四个本地商家节点,名字分别是Avocado Green Mattress - Hoboken、- Orange County、- La Jolla、- Santa Monica。这四个名字在商家资料那边全部违规(地点信息),但它们出现在自家首页上,作为四家实体门店的标注,逻辑上完全说得通。同一个写法,换个位置,一个合规一个违规。 这个案例值得多想一层。它之所以说得通,是因为那四个节点的类型是本地商家,不是组织——本地商家天然是按门店分的,加城市名是识别不同门店的必要手段。类型对了,加词就不算多余。换句话说,判断一个词该不该在名字里,还得看这个名字挂在哪个类型下面。 反过来,如果同样这四行挂的是Organization类型,那就真的乱了:一家公司同时叫四个名字,而这四个名字只差城市。所以做结构化数据的时候,选类型这一步的分量,比大多数人以为的重。 ## 另一类:名字被机器改坏了 有两条特别值得单独拎出来,因为它们不是人的选择,是系统的事故。 机器无声改动内容这件事不止一次出现,浏览器自动翻译把选项改掉而问卷看不出异常 (https://zhangwenbao.com/browser-auto-translate-rewrites-page.html)是另一个版本。 rothys.com给出的两个形态是Rothy's和Rothy's。第二个里的那串字符是HTML实体,本该被解码成一个撇号,结果原样进了字段。这个站的名字之所以有两个形态,纯粹是因为某个模板少调了一次解码。 swarovski.com的两个形态是Swarovski和Swarovski Organization。后面那个Organization是结构化数据里的类型名,不是名字的一部分。这是把schema的类型字段写进了值字段。这一类错误不会有任何报表提醒你,因为语法完全合法。 还有一条同类的:delonghi.com的两个形态里,一个是De'Longhi Appliances S.r.l,另一个是DeLonghi——撇号没了,空格也没了。这两个字符串在任何一台机器眼里都是两个完全不同的名字,而它们出自同一家公司的两个页面。 这三个案例有一个共同点:没有任何一个人做过“把品牌改名”这个决定。名字长出第二个形态,靠的是一次没解码的模板、一次填错的字段、一次不同实现之间的字符处理差异。这也是为什么这类问题只能靠并排看发现——它没有决策记录,没有变更工单,没有人知道它什么时候出现的。 ## 三条长出第二个名字的路径 路径 | 触发场景 | 典型样本 | 能不能被发现 | 人为加尾巴 | 开新市场、区分后台 | Brompton UK、IKEA Denmark | 能,形态之间有共同开头 | 填错字段 | 法人名、母公司名、产品线名进了组织名 | JRSK Inc.、ankerstore、CYBEX Gold | 难,语法完全合法 | 机器事故 | 模板漏解码、类型名写进值 | Rothy's、Swarovski Organization | 最难,没有任何变更记录 | 模板与服务器层的默认值都会埋雷,服务器配置对SEO影响的二十项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以一起过一遍。 三条路径的处理成本递增。第一条改一次模板变量就好;第二条要先搞清楚这个字段该填什么,往往需要跟法务或者品牌部门确认;第三条得先找到那段生成代码,而它可能藏在某个插件里。 ## 还有七个站,两个名字之间毫无关系 26个可测域名里,除了19个能定基线的,还剩7个。这7个的情况更极端:它们给出的几个名字之间连一个公共开头都没有。 实体识别错乱会直接影响被推荐的概率,ChatGPT品牌推荐机制的六十八次实测 (https://zhangwenbao.com/bing-ranking-chatgpt-brand-visibility.html)给过量化结果。 ## 七个站的名字清单 域名 | 它同时声明的名字 | awaytravel.com | Away / JRSK Inc. / Away: Built for modern travel | soundcore.com | soundcore / soundcore FR / Soundcore EU / ankerstore | traeger.com | Traeger Grills / https://www.traeger.com | cybex-online.com | CYBEX Online Shop / CYBEX / CYBEX Gold / CYBEX Platinum | delonghi.com | De'Longhi Appliances S.r.l / DeLonghi | govee.com | Govee / EU-GOVEE | beistravel.com | Béis / Beis Travel Europe | 品牌名混乱最终损耗的是品牌资产,把品牌当权重的四大战略 (https://zhangwenbao.com/seo-without-brand-building.html)解释了这笔账该怎么算。 ## 三种完全不同的成因 第一种是把法人实体名当成组织名。awaytravel.com的加拿大版给的是JRSK Inc.,那是Away这个品牌背后的注册公司。买家不认识JRSK,他认识Away。delonghi.com的西班牙版给的是De'Longhi Appliances S.r.l,法律术语和撇号一起进了字段,而它的另一个形态干脆连撇号都没有,写成DeLonghi。 身份声明混乱在智能体时代成本更高,AI Agent时代品牌信任取代排名的四条策略 (https://zhangwenbao.com/ai-agent-brand-trust-new-ranking-factor.html)讲了原因。 第二种是把关联品牌或母公司的店名串了进来。soundcore.com的阿联酋版给出的组织名是ankerstore——那是母公司Anker的店名。一个用户在soundcore的站上,被告知这个站属于一个叫ankerstore的组织。这条不是加尾巴,是换了个实体。 第三种是字段用错了位置。traeger.com的og:site_name直接写成了https://www.traeger.com,一个完整的网址塞进了名字字段。商家资料那边有专门一条禁令管这个,叫“电话号码或网址”。cybex-online.com更热闹,把CYBEX Gold和CYBEX Platinum这两个产品线名当成了组织名。 把网址写进站点名这件事,其实有个很朴素的来源:很多模板的默认值就是站点地址。建站的时候没人去改那一栏,它就一直是网址。默认值是最容易被忽略的一种错误,因为它从来没有被人做过决定。 ## 为什么这七个站的问题比前面17个严重 加尾巴至少还认得出是同一家。名字完全不同就不一样了:系统要么把它们当成两个实体,要么挑一个当主名把另一个丢掉。无论哪种,你都失去了对这件事的控制。 实体被拆成两个的后果是可见性下降,AI搜索可见性的五维度深层策略 (https://zhangwenbao.com/ai-search-visibility-deep-seo-strategy.html)里有对应的诊断路径。 更麻烦的是,这类问题极难自查。你在浏览器里看自己的站,看到的是渲染后的页面,标题和logo都是对的;那个写着JRSK Inc. 的字段藏在结构化数据里,只有查看源码或者用测试工具才看得到。 再往下想一层:这七个站里,有几个的名字冲突发生在不同的语言版本之间。也就是说,你在本国站上看源码,一切正常;问题只存在于那个你半年不打开一次的市场站上。自查的盲区,恰好和运营的盲区重合。 ## 母公司这一类要怎么表达才对 soundcore那个案例其实提出了一个真问题:品牌确实属于某个母公司,这层关系该不该说、怎么说。 关系类属性有专门的表达方式,论坛和问答结构化数据怎么做 (https://zhangwenbao.com/google-forum-qa-structured-data-ai-bot-label.html)是另一组关系字段的用法示范。 答案是该说,但不该说在name里。结构化数据里有专门的属性表达这层关系——parentOrganization表示上级组织,subOrganization表示下级,sameAs用来把同一个实体在别处的资料页链过来。关系有关系的字段,名字只管名字。 把母公司名写进name的实际后果是:系统读到的是“这个站的组织叫ankerstore”,而不是“soundcore隶属于Anker”。前者是一次错误的身份声明,后者是一条有价值的关系信息,两者的差别不是措辞,是语义。 ## 产品线名的边界在哪 CYBEX Gold和CYBEX Platinum这两个是产品线,不是公司。但边界确实不总是那么清楚——有些品牌的子系列做大了,会独立成品牌,比如很多运动品牌旗下的高端线。 产品与品牌该分别挂哪些字段,电商产品评论的结构化与GEO联动 (https://zhangwenbao.com/ecommerce-product-reviews-seo-guide.html)给过一张对应关系表。 判据可以简单一点:这个名字有没有自己独立的官网首页。有的话,它可以在自己那个站上当组织名;没有的话,它就只是产品属性,应该出现在产品结构化数据的brand或者model里,而不是首页的组织名里。 这条判据的好处是它可执行。你不需要跟品牌部门讨论定位,只要看一眼有没有独立域名或独立目录就行。 ## 七个站里最值得学的那个反例 七个站里,traeger.com那条最有教学价值,因为它的错误最容易复制。把网址填进名字字段,这个动作本身没有任何主观判断,它只是没人去改默认值。 默认值是上线检查清单该管的事,自建站谷歌SEO开发期的十大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)里列了要逐项确认的字段。 类似的默认值陷阱在建站过程中到处都是:站点标语默认是“又一个网站”、作者名默认是admin、商品图片的替代文本默认是文件名。这些默认值有一个共同特征——它们在页面上不显示,或者显示得很不起眼,所以永远没人发现。 应对办法只有一个,就是在上线检查清单里给它们留一行。不是靠记忆,是靠清单。保哥这些年见过太多站,页面做得漂亮,源码里一堆默认值原封不动,其中最常见的就是站点名称那一栏还是安装时自动填的域名。 ## 这七个站的另一个共同点 把七个站的名字清单再看一遍,会发现一件事:每一个站的“主名”都是对的,出问题的都是第二个、第三个形态。Away是对的,JRSK Inc. 是多的;soundcore是对的,ankerstore是多的;Traeger Grills是对的,那个网址是多的。 知识没传到执行位置是管理问题,新网站SEO目标管理的三个里程碑 (https://zhangwenbao.com/new-website-seo-goal-management.html)里有拆解任务的办法。 这说明问题的性质不是“不知道自己叫什么”,而是“在某些位置上,负责填这个字段的那个人或那段代码,不知道该填哪个”。知识是有的,只是没传到那个位置。 这正好回到前面说的单一事实来源:如果名字只在一个地方定义,其它位置全部引用,那么“不知道该填哪个”这个问题从一开始就不会出现。 ## 把名字数清楚,需要几个动作? 禁止型规则的落地方式跟其它两类不一样。它不需要你设目标、不需要你做实验、不需要你追踪效果,它只需要你把不该在的东西拿掉,然后确认它真的不在了。 盘点类的活最怕漏掉边缘页面,四十个电商站的站内搜索页实测 (https://zhangwenbao.com/site-search-result-page-landing-collapse.html)也是靠逐个页面看才发现的。 ## 第一步:把所有声明位置列全 先做一张表,把你的站上所有会说出“我叫什么”的位置写下来。一般至少这么几处。 不同建站方式的字段入口差别很大,SaaS托管自建与纯代码的选型全拆解 (https://zhangwenbao.com/independent-site-builder-platform-choice-saas-wordpress-ai-code-seo.html)可以先确认自己属于哪一类。 位置 | 怎么查 | 常见问题 | 结构化数据Organization.name | 查看源码搜application/ld+json | 写成法人名或母公司名 | 结构化数据WebSite.name | 同上 | 和Organization不一致 | og:site_name | 查看源码搜og:site_name | 写成网址或带 .com | 页面标题尾段 | 看首页title | 塞了广告语和地区词 | 各语言版本页面 | 逐个语言目录重复以上 | 每个市场一个名字 | alternateName | 查看源码搜这个字段 | 基本没人填 | ## 第二步:定一个基线名,然后做减法 选一个名字当基线,判据只有一个:顾客口头提起你的时候说的是哪个。不是法务上最完整的那个,不是域名去掉后缀的那个,是顾客嘴里的那个。 基线名其实是品牌定位的一次收敛,AI搜索时代品牌定位清晰度的四个动作 (https://zhangwenbao.com/brand-positioning-clarity-ai-search.html)讲了怎么收。 这个判据有个很好用的验证方式:去翻客服工单和站内搜索词。用户在工单里怎么称呼你、在搜索框里输入的是哪几个字,那就是你真实的名字。这批数据里那些名字最干净的站,用的基本都是这个逻辑——名字短、无修饰、和域名主体一致。 另外提醒一句:基线名一旦定下来就别轻易动。名字这件事的价值几乎全部来自稳定,改一次名字的代价,远高于当初起对名字的收益。所以这一步宁可慢,也别边做边改。 然后把所有位置上的名字跟基线对齐。多出来的每一个词,按下面这张表分流。 多出来的成分 | 该去哪 | 国家、地区、城市 | 删掉。市场归属由页面语言和地址字段表达 | Official、Shop、Store、Online | 删掉。它是修饰不是名字 | Inc、LLC、GmbH、S.r.l | 移到legalName字段 | 第二种文字的写法 | 移到alternateName字段 | 母公司或关联品牌名 | 用parentOrganization或sameAs表达 | 产品线名 | 删掉。它属于产品不属于组织 | ## 第三步:验一遍,而且要在所有语言版本上验 最容易漏的就是这一步。这批数据里26个有多形态的域名,绝大多数的问题只出现在非主站的语言版本上——首页干干净净,德国站的组织名后面挂了个Deutschland。 多版本核对最容易漏掉非主站,集合页分页的索引判断与canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)也是同一类逐版本的活。 验的方法很土但很有效:把每个语言版本的首页源码拉下来,把所有名字字段抠出来放进一张表,肉眼扫一遍。不需要工具,需要的是把它们并排放在一起。分散在二十个页面上的时候你看不出问题,放进一列里三秒钟就看出来了。 如果你的站有hreflang表,这一步可以省一半力气——那张表本身就是所有语言版本的清单,照着它一个个抓就行。多语言标注和名字一致性这两件事,用的是同一份地址列表,顺手一起做完最划算。 ## 一张能直接用的盘点表 列 | 填什么 | 为什么需要这一列 | 语言地区 | en-US、de-DE之类 | 定位问题出在哪个市场 | 页面地址 | 该版本的首页 | 改的时候直接点开 | Organization.name | 原样抄,不要整理 | 整理会掩盖大小写和字符差异 | og:site_name | 原样抄 | 它是站点名称的第二来源 | 标题尾段 | 原样抄 | 它是第三来源 | 与基线的差 | 只写多出来的那几个词 | 这一列就是你的待办清单 | 抄源码这件事有工具可以省力,十款网站技术栈检测扩展的实测对比 (https://zhangwenbao.com/seo-website-technology-stack.html)里有能直接读结构化数据的。 最后一列是整张表的重点,前面五列都是为它服务的。填完这一列,你的改造工单就写完了。 表格填完之后还有一个动作值得做:把“与基线的差”那一列去重,看看一共有几种不同的多余成分。这批数据里,17个有问题的域名加起来只产生了六类多余成分——地点、法律术语、营销词、另一套文字、产品词、其它。问题的种类远比问题的数量少,这意味着一次修改往往能解决一整类。 ## 改的时候按什么顺序 如果多余成分不止一类,按这个顺序处理性价比最高。 一次改模板清掉多处问题是最划算的,类目导航改版三轮之后仍然没写清楚用户在哪 (https://zhangwenbao.com/category-navigation-scope-custody.html)也是模板层的活。 先改那些出现在最多语言版本上的。一个尾巴挂在五个市场上,改一次模板就能一次清掉五处;另一个尾巴只在某一个市场上,那是单点问题,可以晚一点。 然后改那些跟主名差别最大的。Away和JRSK Inc. 之间的距离,比Brompton和Brompton UK之间的距离大得多,前者更可能被系统当成两个实体。差别越大,消歧的代价越高。 最后改那些机器生成的。这类改起来最麻烦,因为你得先找到生成它的那段代码;但它也最不容易复发,因为改完之后模板就对了。 ## 改完怎么确认真的生效了 只看浏览器里的页面是不够的,那一层看不到结构化数据。可靠的确认方式有三种,按可信度排序:直接看每个语言版本的初始HTML源码;用富媒体测试工具跑一遍,它会把解析出来的字段列出来;等系统重抓之后看搜索结果里显示的站点名称。 改完之后要等多久是个高频问题,已收录页面加noindex后多久消失的六大场景实测 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)给过量级参考。 第三种最慢,官方对图标这类资源的重抓给出的说法是几天到几周,名字大概率也在这个量级。所以别改完当天就去搜自己的品牌名,看到没变化就再改一次。反复改是这件事上最坏的做法,它会让系统对你的名字一直保持低把握。 还有一个细节值得强调:第三、四、五列一定要原样抄,不要顺手把首字母改成大写、不要把全角空格换成半角。Rothy's那个案例之所以能被发现,就是因为没有被整理过。你在誊抄的时候做的每一次“修正”,都是在把证据擦掉。 ## 为什么单是删掉不够,还要主动填别名? 做完减法,名字干净了,但你损失了信息。日本市场的片假名写法、中文市场的中文名,这些是真实存在的、用户真的会拿去搜的东西。它们不该消失,只是不该待在name里。 主动声明比等着被理解有效得多,答案引擎优化怎么让内容被优先引用 (https://zhangwenbao.com/aeo-answer-engine-optimization-guide.html)讲的是同一件事。 ## 那个没人用的字段是干什么的 alternateName的定义只有一句话:这个东西的一个别名。它属于Thing这个最顶层的类型,所以任何类型都能用,组织能用,产品能用,文章也能用。 推荐属性填不填直接影响信息量,FAQPage结构化数据的八步实战 (https://zhangwenbao.com/shopify-blog-faqpage-schema-seo-geo.html)也是一个填了才有用的字段。 Google的组织结构化数据文档里对name和alternateName的说明是连在一起写的:使用你在站点名称上用的那同一组name和alternateName。官方文档明确把这两个字段当成一对来看待,而实测90个站里只有7个把这对填全了。 ## 填了别名,实际上换来什么 换来的不是排名,是消歧。当系统需要判断“这个中文名和那个拉丁名是不是同一家”的时候,你的alternateName就是那张明牌。没有这张明牌,它得靠上下文猜,猜错的成本你来承担。 消歧本质上是在共识层留证据,共识层六信号的九十天实战指南 (https://zhangwenbao.com/seo-consensus-layer-ai-search.html)解释了这些证据怎么被汇总。 这件事在跨语言市场上尤其值钱。上一批做多语言标注的时候我们已经见过一次同类现象:系统能不能把两个地址认成一件事,取决于你有没有明确说出来,而不是取决于它们看起来像不像。名字这件事是一模一样的逻辑。 还有一个更具体的收益场景:品牌词的搜索需求往往分散在几个写法上。用户可能搜拉丁写法,也可能搜本地文字写法,还可能搜一个通俗简称。你把这几个都登记成别名,等于告诉系统这几拨需求指向同一个实体。不登记的话,它们在系统那边可能是几件不相干的事。 ## 别名该写几个,写哪些 三条建议,都来自这批数据里的反例。 别名写什么会影响品牌被怎么描述,AI品牌情感优化五个月的操作手册 (https://zhangwenbao.com/ai-brand-sentiment-optimization-visibility-guide.html)记录过一次调整过程。 第一,写真的被用的,不写你希望被用的。片假名写法如果日本用户确实在用,写;某个内部代号没人在外面用,不写。第二,别把地区变体写成别名。Brompton UK不是Brompton的别名,它是Brompton加了个尾巴,删掉就好。第三,别名字段不是关键词字段,塞品类词进去没有任何用,反而会让系统对你的主名更不确定。 这个字段的价值来自它的克制。填两三个真别名的效果,远好过填十个凑数的。 ## 哪些东西看起来像别名,其实不是 候选 | 是不是别名 | 该去哪 | 日文片假名写法 | 是 | alternateName | 用户常用的简称 | 是 | alternateName | 品牌名加国家 | 不是 | 删掉 | 法人全称 | 不是 | legalName | 母公司名 | 不是 | parentOrganization | 产品线名 | 不是 | 产品数据里的brand | 历史旧名 | 看情况 | 用户还在搜就填,否则不填 | 域名本身 | 不是 | url字段 | 品牌词的几种写法可以在后台拆开看,GSC品牌词过滤器的五步使用指南 (https://zhangwenbao.com/google-search-console-branded-query-filter.html)讲了怎么按写法分组。 这张表里最容易搞错的是最后一条。很多站把域名当别名填进去,理由是“大家也这么叫我们”。但域名有专门的url字段,重复声明不增加信息,只增加一个需要被消歧的字符串。凡是已经有专属字段的东西,都不该再进别名。 ## 那86个测不出的站,真的没问题吗? 这是本次数据里最需要小心解读的一块。76.8% 的域名只给出一个名字形态,尺子对它们弃权——但弃权不等于合格。 让机器读得懂的前提是你先说清楚,让内容被主动引用的五个维度 (https://zhangwenbao.com/ai-search-content-writing-machine-readable-playbook.html)里有可执行的写法。 ## 弃权的三种可能 只有一个形态,可能对应三种完全不同的现实。 看不见不等于不存在,日志里带人来的其实是另一批入口 (https://zhangwenbao.com/ai-referral-source-domestic-entries-gap.html)就是一次典型的统计盲区。 第一种是真的规范:全站上下只用一个名字,各语言版本一致,这是最好的状态。第二种是信息量不足:这个站压根没做多语言,或者它的语言版本页面没被我抓到,所以看不出漂移。第三种最隐蔽:这个站的唯一一个形态本身就是错的。比如它只在一处声明了名字,而那一处写的是法人全称,全站再没有第二处可以对照。 ## 规则够不着你,取决于你暴露了多少 这一层是这次量完之后最让我在意的东西。能被这把尺子判的,只有那些自己给出了不止一个版本的站。换句话说,你得先自曝,规则才够得着你。 暴露面与风险面往往是同一件事,GEO投毒的三条攻击路径与三层防御 (https://zhangwenbao.com/geo-ai-poisoning-315-deep-analysis.html)从另一侧讨论过这个平衡。 这个结论对禁止型规则是普遍成立的。商家资料那条新规能执行,是因为名称字段是明牌,谁都看得见。而结构化数据里那些名字,除非你自己给出多个版本、被人并排一看,否则没有任何机制会发现不一致。 所以那86个站不是安全,是没被看见。没被看见和没问题之间,隔着一整个语言版本目录。 ## 暴露多少这件事,你其实是可以选的 顺着这条思路往下走会得到一个有点危险的推论:既然规则够不着不暴露的人,那少声明一点是不是更安全。 说得少而准是内容层同样适用的原则,AI搜索时代内容优化的底层逻辑五步 (https://zhangwenbao.com/context-first-seo-ai-search-strategy.html)里有一致的取舍。 这个推论在合规层面成立,在效果层面完全不成立。不声明的代价是系统只能靠猜。官方文档已经明说,把握不足的时候它会自己生成一个名字或者直接显示域名——你规避掉的那点风险,换来的是对呈现结果的失控。 正确的姿势不是少说,是说得少而准:只在必要的几个位置声明,每个位置说同一句话,别名放进别名字段。这样既没有不一致的风险,也没有信息缺失的代价。 这一点跟很多技术类规则的处理逻辑是一致的:模糊不会保护你,模糊只是把决定权交出去了。 ## 给那86个站的一份三分钟自检 如果你的站也属于“只声明了一个名字形态”这一类,下面三个问题能在三分钟内告诉你是哪一种情况。 自检之后要不要上监控工具,二十款GEO与AEO监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)可以按预算挑。 第一个问题:你有几个语言版本或国家站。如果只有一个,那你天然没有不一致的机会,这一项可以过;如果有好几个,但抓下来只有一个名字形态,先确认是不是别的版本压根没有结构化数据。 第二个问题:你唯一那个名字,是从哪来的。是有人专门决定的,还是模板默认的,还是从店铺设置里带出来的。只要不是有人专门决定的,就有必要看一眼它到底写的是什么。 第三个问题:把那个名字念给一个没见过你品牌的人听,他会不会觉得那是一家公司的名字。念出来像地址、像广告语、像网址、像法务文件的,都需要改。 三个问题都过了,你可以放心地把力气挪到别处。这正是禁止型规则该有的收尾方式:确认过线,然后离开。不需要每季度回来看一眼,也不需要建监控,只要在下次动模板的时候顺手再过一遍这三个问题就够了。 顺便说一句,这三个问题里最容易翻车的是第二个。很多团队从没想过“这个名字是谁定的”这种问题,因为它看起来太基础了。但本次样本里那些最离谱的值——写成网址的、写成一整句瑞典语的、带着未解码实体的——无一例外都属于“没人做过决定”这一类。基础问题之所以出错,恰恰是因为没人觉得它需要被检查。 ## 如果你正在开新市场 开新站的那一刻,是这件事成本最低的时候。新市场上线之前花十分钟确认三件事,能省掉后面几年的对账。 新市场上线前的这半小时,回报周期比多数投放都长,八家龙头怎么抢AI流量的打法拆解 (https://zhangwenbao.com/geo-concept-ai-traffic-2000billion-leaders.html)里有类似的前置动作清单。 第一,新站的组织名和主站完全一致,一个字符都不差。第二,市场归属由页面语言声明、地址字段和货币来表达,不写进名字。第三,如果这个市场确实需要一个本地写法,它进alternateName,不进name。 这三条加起来不到半小时的工作量,但它们决定了三年后你要不要做一次跨二十个站的名字对账。这类事情的性价比永远在开头,不在中间。 还有一个容易被忽略的场景:换建站平台或者换主题的时候。迁移过程中所有字段都会被重新映射一遍,而名字这类字段往往没人专门盯,映射错了也不会有任何报错。本次样本里那几个明显是模板事故的案例,时间点大概率就落在某次迁移上。迁移清单里加一行“核对组织名与站点名”,成本是一分钟。顺手把各语言版本也带上,因为迁移往往是一次性把所有站都动一遍,正好是并排核对最省事的时机。 ## 怎么让自己从测不出变成能自查 方法很简单,而且是免费的:把你所有语言版本的名字字段主动收集到一张表里。这张表不需要给任何人看,它的唯一作用就是让不一致暴露出来。 把分散数据收进一张表是通用手法,用正则从GSC里挖AI搜索提问的五步实战 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)也是这个思路。 这批站里有几个已经在这么做了——它们所有语言版本给出的是同一个组织名,地区信息全部靠页面语言和地址字段表达。这不是运气,这是有人维护着一份单一事实来源。 ## 顺便说说“单一事实来源”这四个字 这个词在工程团队里很常见,但在名字这件事上它有一层特殊含义:你的品牌名应该只在一个地方被定义,其它所有位置都引用它。 同一份内容供多种消费方式,用内容协商给AI交付Markdown的实操 (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是单一来源多种输出的另一个例子。 实际做法通常是在站点配置或者环境变量里放一个常量,模板里的组织名、og:site_name、标题后缀全部引用这个常量。这样做的好处不是省事,是让不一致在物理上不可能发生——你想让德国站叫一个别的名字,得先改配置,而改配置这个动作有记录、有人看得见。 反过来,如果每个语言版本的模板里各自硬写了一遍名字,那么不一致的出现只是时间问题。这批数据里那26个有多形态的站,绝大多数属于后一种结构。 ## 那几个把名字换成一句话的站 最后补一类特别的样本,它们不在前面的统计里,因为它们的名字压根不是名字。 广告语和名字被混为一谈很常见,PAS公式在SEO内容写作中的进阶用法 (https://zhangwenbao.com/pas-formula-seo-content-writing-advanced-applications.html)里区分过这两种文案的职责。 vaude.com的法比版组织名叫FR Shop,美国版叫Mountain & Bike Sports;zwilling.com的美国版叫Premium Kitchenware,葡萄牙版叫“厨房必备品”,瑞典版直接是一整句“选购刀具、厨房用具、餐具和锅具”。insta360.com的德语版叫VR Kameras。 这些字段里装的是品类描述和广告语,不是名字。它们大概率来自同一个原因:模板把某个用于展示的字段接到了名字字段上,比如接了页面标题、接了导航栏文案,甚至接了SEO描述。 这一类问题的自查方式最简单:把你的组织名念出来,如果它不像一个名字,那它就不是。“选购刀具、厨房用具、餐具和锅具”,念一遍就知道出事了。 ## 禁止型、代劳型、亲自型,力气该怎么分? 回到最开始那个三分法。认出规则的类型,是为了决定投入多少,以及投在什么形态上。 平台的介入方式在专利里能看到痕迹,从专利与专家访谈还原的GEO五步原理 (https://zhangwenbao.com/google-microsoft-patents-geo-guide.html)提供了另一个观察角度。 ## 三种规则的投入曲线完全不同 类型 | 投入曲线 | 什么时候该停 | 典型误判 | 禁止型 | 阶跃:过线前为零,过线后不再增长 | 过线就停 | 当成优化反复打磨 | 代劳型 | 钝:收敛候选有用,超出后无效 | 候选剩一个就停 | 以为有开关可以设死 | 亲自型 | 线性:做多少得多少 | 不该停 | 以为平台会提醒你 | 投入产出曲线该怎么跟老板讲,流量下降不等于SEO失败的八维度实战 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)有一套现成的说法。 名字这件事其实横跨了前两类。删掉不该有的,是禁止型;剩下那个到底会不会被系统采用,是代劳型。你能做完的只有前半段,后半段你只能把原料摆对。 ## 先做哪个 顺序上,禁止型永远排第一,因为它的下行风险最大且不可预测。代劳型排第二,因为它的收益虽然有上限但确定。亲自型排第三,但它是唯一一个长期复利的——这一点下一篇会专门讲。 排在禁止型后面的往往是技术底座,四十六个电商站的页面体积实测 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)是一次典型的亲自型排查。 保哥这两年给客户做诊断,第一天永远只做一件事:把所有可能触发处罚的地方过一遍。不是因为它最重要,是因为它最便宜——一个下午能做完的事,做完之后你就再也不用担心某天早上醒来资料被暂停。 ## 三类规则各自最容易犯的错 禁止型最容易犯的错是把它当优化做,前面已经说过了。还有一个变体:把它无限期推迟,理由是“又不影响排名”。不影响排名是对的,但它影响存在。 等平台通知是亲自型规则上最贵的错,抓取预算优化的十二项实操指南 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)里全是没人会提醒你的事。 代劳型最容易犯的错是找开关。团队会花好几天翻后台、翻文档,想找一个能把站点名称写死的设置项。找不到之后,往往得出的结论是“这功能还没上线”,而真相是它根本就不以开关的形式存在。 亲自型最容易犯的错是等通知。因为平台从不报警,没有报表,没有邮件,也没有一项检查会亮红灯,所以团队默认“没消息就是没问题”。而实际情况是,这类事情永远不会有消息。 ## 三个反直觉的判断 第一,名字字段里多写的每一个词,都在替系统做一次“这是不是同一家”的判断题,而它答错的概率比你以为的高。页面上多一个词是丰富,字段里多一个词是歧义。 多说一个词未必是丰富,七万五千条答案实证的引用偏好 (https://zhangwenbao.com/ai-search-citation-content-types-geo-strategy.html)也得出过类似的克制结论。 第二,没有执法的地方问题更多,不是更少。商家资料那边名称字段规规矩矩,是因为违规会被暂停;独立站这边一片自由,于是标题里的品牌名可以出现三次。 第三,这批数据里最干净的那批站,不是最讲究的,是最懒的——它们只在一个地方写了名字,所以不可能不一致。维护多份声明的成本,总是比你预算的高。 ## 如果只做一件事,做哪件 把所有语言版本的组织名、og:site_name和标题尾段抄进一张表,然后看它们是不是同一个字符串。就这一件。 一次盘点能带出一批改动,把旧内容更新成AI可信来源的十二步 (https://zhangwenbao.com/revise-old-content-for-aeo-ai-search-optimization.html)可以接在这次盘点后面做。 这件事不需要任何工具、不需要预算、不需要跨部门协作,一个人一下午能做完一个二十语言的站。而它能一次性暴露本文提到的绝大多数问题:加尾巴的、填错字段的、被模板改坏的、以及被接成一句广告语的。 名字这件事的所有麻烦,都源于它被写在了太多地方;所有的解法,也都始于把这些地方并排放在一起看一眼。 ## 最后回到那条新规 商家资料这次加的那一行,站在独立站主的角度看,其实是一份免费的提醒。它告诉你平台在意什么:不是名字好不好听,不是名字有没有关键词,而是一个实体在系统里能不能收敛成一个名字。 实体收敛这件事在渠道层同样成立,Reddit成了新型GEO引擎源之后官网怎么起量 (https://zhangwenbao.com/geo-channel-evolution-reddit-rise-fall-2025-optimization.html)里能看到同一个实体在多个渠道的一致性代价。 本次样本里,能被判的26个域名中有17个没做到,比例六成五;而那86个测不出的站,只是没给出足够的证据,不代表它们在别的位置上没有分叉。把这两个数字合起来看,“一个实体一个名字”这件事,在国际化独立站里远没有成为默认。 好在它的修复成本极低。不需要预算,不需要排期,不需要说服任何人——把几个字段抄进一张表,删掉多余的词,把别名归位。整件事的难点从来不是执行,是意识到那几个字段之间本来就该一致。 下一篇会接着讲第二类,也就是代劳型:当平台不是禁止你、而是替你决定的时候,你手上还剩下什么牌。那一篇量的是同一批站的另一样东西——搜索结果和广告位上显示的那个小图标,以及系统究竟从哪几个来源里挑出你的名字。名字和图标是同一个问题的两半:一半是你不该多说,一半是你说了也不算。 最后留一句可能有点扫兴的话。这批数据里做得最规范的那些站,没有一个是靠工具做到的。它们靠的是有人在某一天决定了“我们叫什么”,然后把这个决定写进了配置文件,让所有模板去引用它。技术手段能帮你发现不一致,但消除不一致靠的始终是一个决定,而不是一个脚本。 ## 常见问题解答 ## 我的独立站没有商家资料,这条新规跟我有关系吗? 直接关系没有,这条规则只管商家资料的名称字段。但它背后那张七条禁令清单,是目前能找到的、最明确的一份“名字字段里不该有什么”的官方说明,可以直接拿来审你自己站上的结构化数据和og标签。如果你同时在做本地业务、有实体门店,那就是直接相关,需要在被暂停之前主动改掉。另外还有一种常见情况:品牌方自己没开商家资料,但线下经销商开了,而经销商往往会把品牌名加上自己的城市和门店编号。这种资料出问题的时候,被搜索的人找不到的仍然是你的品牌。 ## 不同国家站用不同的组织名,到底有什么实际损害? 最直接的损害是消歧成本转嫁给了系统。当有人问某个品牌怎么样、系统需要把你的几个站聚合成一个实体的时候,五个不同的名字意味着它要多做四次判断。判断结果不透明,也不会有任何报表告诉你它判成了几个实体。次一级的损害是站点名称的显示:官方文档明说,如果系统对你提供的名字不够有把握,它可能会自己生成一个,或者干脆显示你的域名。 ## legalName和name到底该怎么分? name写顾客口头说的那个,legalName写工商登记的那个。判据很简单:如果一个陌生顾客在电话里对你说出这个名字,你会不会觉得奇怪。会觉得奇怪的,就是legalName。这批数据里17个站填了legalName,做法都是对的;有问题的是那几个把法人名直接写进name的站,比如把Away写成JRSK Inc.。 ## 把中文名和英文名一起写进name,真的会被判违规吗? 在商家资料里会,这正是新增那条规则明说的形态,而且明确写了即使实体招牌上就是这样也不允许。在独立站的结构化数据里不会有人罚你,但会有另一个后果:系统需要自己判断这两段文字是同一个名字的两种写法,还是两个不同的东西。正确的做法是主名只留一个书写形态,另一个放进alternateName。 ## 为什么第一版尺子会把品牌名本身当成违规? 因为它只有词表没有基准。规则原文说的是不必要的信息,不必要意味着存在一个必要的基准,也就是商家的真实名号。只按词表判,Copenhagen这个词在Flying Tiger Copenhagen里是名字的一部分,在Brompton Copenhagen里就是加上去的,而词表分不出这两种情况。修法是给每个站找一个属于它自己的基线,只判基线之外的增量。 ## 只有一个名字形态的站,是不是就一定没问题? 不一定,只能说测不出。可能是真的规范,可能是没做多语言所以没暴露出漂移,也可能是它唯一那个形态本身就写错了、而站上没有第二处可以对照。本次样本里112个域名有86个属于这一类,占76.8%。想从测不出变成能自查,唯一的办法是把所有语言版本的名字字段主动收集到一张表里。 ## alternateName填多了会不会被当成关键词堆砌? 目前没有任何公开说明表示会因此受罚,但填多了确实有害。这个字段的作用是消歧,填进去的每一个别名都在告诉系统“这也是我”。塞品类词进去,等于告诉系统你的名字里包含这个品类词,反而降低了它对你主名的把握。建议只填真实被用的别名,一般两三个足够。 ## 这套盘点多久做一次比较合适? 触发式比定期式更实用。每次新开一个语言版本、每次换模板、每次上新的结构化数据插件,做一次。这三件事是名字长出第二个形态的主要场景。这批数据里那个把HTML实体原样写进名字的站,几乎可以肯定是某次模板改动带出来的,而这种问题不会有任何报表提醒。如果一定要一个周期,半年一次足够,但前提是这半年里没发生上面那三件事。 ## 改了名字之后,多久能在搜索结果里看到变化? 没有确定的时间表,官方也没给过承诺。可以参考的是同类抓取行为的节奏:图标的重新抓取,官方明说需要几天到几周,取决于系统判断你更新的频率。名字这类信息的更新节奏大概率同一个量级,因为它同样只需要重抓首页。所以合理的预期是几天到几周,期间不要反复改——每改一次,系统对你的把握就低一分。 ## 用了Shopify这类平台,这些字段还能自己控制吗? 大部分能,但入口分散。组织类结构化数据通常由主题模板输出,改主题文件或者用应用注入都行;og:site_name一般跟着店铺名称走;标题后缀在SEO设置里。本次样本里有大量站跑在这类平台上,出问题的位置高度集中在多店铺场景——同一个品牌开了几个国家店,每个店的店铺名各自填了一遍,于是名字就分叉了。这种情况下最省事的办法是把店铺名统一,把国家信息交给货币、语言和地址去表达。 ## 把品牌名换成一句品类描述,会有什么后果? 后果是系统失去了你的名字这条线索,只能从别的地方找。官方文档写过,当它对你提供的名字不够有把握时,可能会用其它来源生成一个,或者直接显示域名。本次样本里有几个站的组织名被填成了品类描述甚至整句广告语,比如“选购刀具、厨房用具、餐具和锅具”。自查方法很简单:把那个字段的值念出来,不像名字就是不对。 ## 权威参考资料 ## 别照抄爬虫黑名单:266个令牌只23.3%真来过 - URL:https://zhangwenbao.com/crawler-ua-list-named-vs-real-visits-audit.html - 分类:技术SEO - 发布:2026-08-11 | 更新:2026-08-11 - 摘要:robots.txt里那些被点名的爬虫,有多少还真的会来?把157个独立站的名单和一台真实站点两个月的日志对了一遍,答案是不到四分之一。 - 关键词:robots.txt,技术SEO,日志分析,爬虫管理 > **TLDR**:摘要:157份robots.txt点名过的爬虫令牌去重281个,266个可核对。拿一台真实站点59天、248万行日志做交集,只有62个(23.3%)真来敲过门。命中率还随名单变长而下降:只点1到2个的站有85.5%是活的,点超过30个的6个站掉到26.0%。最长那份点了109个名字,只有2个来过,里面挡着二十多年前的邮件采集器和Windows 95上的IE。 > 摘要:157份robots.txt点名过的爬虫令牌去重281个,266个可核对。拿一台真实站点59天、248万行日志做交集,只有62个(23.3%)真来敲过门。命中率还随名单变长而下降:只点1到2个的站有85.5%是活的,点超过30个的6个站掉到26.0%。最长那份点了109个名字,只有2个来过,里面挡着二十多年前的邮件采集器和Windows 95上的IE。 robots.txt里最容易膨胀的不是规则,是名字。 规则写多写少,多数人心里有数;可名字这东西,加一个的成本几乎是零。看到一篇文章说某个爬虫很耗流量,加一行;同行的文件里有个陌生名字,抄过来;安全建议里列了一串坏机器人,整段贴上。每次加的时候都觉得多挡一个总没坏处。 这次想量的就是这件事:那些被点名的对象,到底还在不在。方法很直接——把157个海外品牌独立站的robots.txt里所有User-agent值收集起来,再拿一台真实运行的站点两个月的访问日志去对,看有多少名字在现实里出现过。 ## 你在robots.txt里点的那些名字,有多少真的会来? 先看名单本身的规模,这个数字比预想的大。 要先能认清对面是谁,120种爬虫UA的分类与真假验证 (https://zhangwenbao.com/crawler-identifier-user-agent-bot-verification-guide.html)是这件事的基本功。 这个文件整体怎么运作值得先过一遍,写废了会让整站从搜索结果里消失 (https://zhangwenbao.com/robots-exclusion-protocol-mechanism-complete-guide.html)是它最极端的一面。 ## 157份文件,281个不同的爬虫名字 去掉通配的星号之后,这批文件里出现过的User-agent值去重有281个。合计被点名1024次,也就是说平均每个名字只被4个站提到过。 名字收集完总要决定怎么对待,robots、UA识别、WAF三层的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)给了取舍依据。 把这些名字按类型拆开看,8类UA的22周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)提供了一份可对照的样本。 分布极度不均:其中186个(66%)只出现在1个站上。这个比例本身就说明了名单的来路——如果这些名字来自某种共识,应该有很多站重复;只出现一次意味着它们来自各自不同的源头,各抄各的。 ## 每站点名2个是中位数,最多的点了109个 按站看,每份文件点名的中位数是2个。这个数字很健康,说明多数站主是有针对性地在管特定爬虫。 这类零散积累的问题集中在几个固定位置,电商站十二类高频坑的诊断修复 (https://zhangwenbao.com/ecommerce-seo-common-mistakes.html)可以照单排查。 名单变长的外因很清楚,AI爬虫抓取量已经超过Googlebot好几倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)让所有人都想管一管。 但分布的尾巴拖得很长: 点名个数 | 站数 | 占比 | 1到2个 | 53 | 44.5% | 3到5个 | 13 | 10.9% | 6到10个 | 24 | 20.2% | 11到30个 | 17 | 14.3% | 31个以上 | 6 | 5.0% | 最长的一份点了109个名字,第二长的42个。这两份文件后面会单独拆,因为它们的成色完全不同。 ## 那186个只出现一次的名字,来路可以归类 只被一个站点名的186个名字,摊开看能分成四堆,每堆的来路都很清楚。 当年那批采集器盯的就是邮箱,临时邮箱的八款实测对比 (https://zhangwenbao.com/temp-mail.html)是需求换了形态之后的产物。 判断一个名字活没活,从日志一步步挖真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)是唯一靠得住的路子。 按标识串拦请求这条路自己也有坑,老代码里那个已被移除的函数 (https://zhangwenbao.com/wordpress-http_user_agent.html)就是典型。 第一堆是桌面工具和开源库,占了最大一块。HTTrack、WebCopier、SiteSnagger、Offline Explorer、WebStripper、Teleport、Nutch、libwww、larbin这些,都是安装在个人电脑上或者由开发者自己跑的东西。 第二堆是二十年前的邮件采集器,名字往往带着当年那股江湖气:EmailSiphon、EmailWolf、CherryPicker、ExtractorPro、Mata Hari。 第三堆是各种小语种或区域性的搜索抓取,比如已经停运的欧洲引擎、早期的国内引擎子服务。 第四堆最少但最值得说:把公司名或产品名当成了爬虫令牌。样本里有一个站一次写了五个这样的名字,包括某家AI公司的产品名、某个模型的代号。这些名字从来没有作为抓取标识出现过——写的人是照着新闻报道里的公司名写的,而不是照着对方公开的技术文档写的。 ## 名字进来的三种场合 反过来想,什么时候人会去加一个名字?基本就三种场合,而每一种都会带来不同质量的名字。 凭印象做判断的代价不小,排名搬不动的五个隐性原因 (https://zhangwenbao.com/good-content-not-ranking-google-real-reasons.html)多半也出在这上面。 报警之后的处理顺序也有讲究,三平台后台告警怎么分级诊断 (https://zhangwenbao.com/webmaster-alert-triage-gsc-bing-baidu-three-platform.html)可以直接照做。 每次加名字都该留痕,把变更做成日志的十三类信号 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)能让来路不再无从追查。 第一种是服务器报警之后。这时候人手里有日志、有具体的标识串,加进去的名字质量最高,因为它是亲眼见过的。 第二种是读到一篇文章之后。文章说某类爬虫在大量抓取内容,附一份清单。这时候加进去的是别人的观察,质量取决于文章的时效。 第三种是合规或者管理层要求之后。要求通常是模糊的——把AI爬虫管一下、把恶意爬虫挡住。执行的人为了显示做过,会倾向于把能找到的清单都加上,名单在这一步膨胀得最快。 三种场合里只有第一种带来的名字是活的。后面那张命中率的表,本质上量的就是三种来源的混合比例。 ## 一个名字从有用到没用,中间发生了什么 把一个名字的生命周期摊开看,就明白为什么它一定会烂在文件里。 服务停掉不会有人通知你,某个缓存服务退役之后还能怎么查快照 (https://zhangwenbao.com/webpage-cache-snapshot-viewing-tools-guide.html)就是这么一回事。 同样的老化问题在内容侧更常见,上千篇旧内容的留改并删转怎么定 (https://zhangwenbao.com/content-audit-pruning-decision-system.html)是一套可复用的判据。 这种没人报错的欠账攒起来很可观,技术债怎么排查和分批还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了一套顺序。 第一阶段,这个抓取程序确实在活动,某个站主在日志里看见了它,写进文件,规则生效。这一步是健康的。 第二阶段,这条经验被写成文章或者清单,传播出去。从这一刻起,抄它的人手里没有那份日志,他只知道这个名字应该管一下。名字开始脱离证据。 第三阶段,那家公司改了名字、换了标识、或者干脆关掉这个服务。这件事发生在别人的公司里,不会产生任何通知——没有邮件、没有告警、没有任何一个系统会告诉你这个名字失效了。 第四阶段,也就是现在:文件里那一行完好无损,语法正确,规则齐全,看上去和旁边那些有效的行一模一样。它已经死了,但没有任何迹象。 四个阶段里,只有第一阶段和第三阶段是真实事件,中间那次传播和最后那次失效之间可能隔着好几年。这就是本文那些名字能活二十年的完整机制——它不是谁疏忽了,是这条链上压根没有反向的信息通道。 ## 名单会长,是因为它没有过期机制 为什么会长成这样?因为名单只有加入的通道,没有退出的通道。 没被验证过的东西都不能算数,备份了不等于安全,恢复演练才是底气 (https://zhangwenbao.com/disaster-recovery-drill-backup-restore-rto-rpo-rollback.html)是同一个道理。 这类失分往往在第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验的汇总。 一个爬虫停止运营、改了名字、或者被公司关掉,不会有人通知你从robots.txt里删掉它。这条信息在你的系统里根本没有入口——它发生在别人的公司里。于是名字进来之后就永远留着,跟着文件一起穿过每一次改版。 这跟字段失效是同一类问题的两个方向:字段那边是指令的收件人公开宣布退出了,名字这边是收件人本身没了。后者更难发现,因为robots.txt里的字段总共只有九种,名字却有几百个。 ## 拿59天的日志当尺子,它量得准吗? 要判断一个名字还在不在,只有一种硬证据:看它有没有发过请求。这就需要一份日志。 数据入门阶段最该建立的就是口径意识,三类工具与排名追踪的习惯 (https://zhangwenbao.com/seo-data-concept.html)可以先看这份。 更大规模的同类观察是,5000个站样本里的爬虫伪造与抓取预算实测 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)。 日志能读出的东西不止爬虫身份,怎么从日志里读懂抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)有一步步的示例。 ## 样本:248万行,38161个不同的User-Agent 用的是一台真实运行的中文SEO站点的访问日志,时间范围2026年6月19日到8月17日,59天,2479791行请求。 日志攒多了会有信噪比问题,慢查询日志攒了783MB而真正超时的只有32条 (https://zhangwenbao.com/mysql-slow-query-log-signal-noise-ttfb-crawl-budget.html)是同一类现象。 日志要能查才有用,把日志收成结构化可检索的形式 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是前置工程。 把每行的User-Agent字段抽出来去重,得到38161个不同的串。其中含有bot、spider、crawl这类自称标识的有479个,它们贡献了636750次请求,占总量的25.7%。也就是说四分之一的流量来自自报身份的程序。 ## 38161个标识串是怎么分布的 把这38161个标识按类型归一遍,能看清这份日志的构成,也顺带说明了爬虫在总流量里的真实位置。 设备维度的差异也很大,移动端与PC端排名差异的六个因素 (https://zhangwenbao.com/mobile-desktop-ranking-differences.html)有对应的诊断办法。 标识串的构成本身有规律,模拟爬虫身份测站的具体做法 (https://zhangwenbao.com/useragent-generator-ua-string-bot-simulation-seo-guide.html)里有可直接用的串。 类型 | 请求数 | 占比 | 不同标识串 | 普通浏览器 | 1787285 | 72.1% | 33447 | 自称爬虫的程序 | 590540 | 23.8% | 401 | 命令行工具与脚本库 | 47961 | 1.9% | 81 | 其它无法归类 | 54005 | 2.2% | 4232 | 这张表有两处值得注意。 一是标识串数量和请求数量完全不成比例:浏览器有33447种标识串,因为每个版本号、每个操作系统组合都算一种;爬虫只有401种,却撑起了近四分之一的请求。所以从标识串数量看,爬虫是极少数;从请求量看,它是很大一块。 二是那4232个无法归类的标识串只贡献了2.2%的请求,大多是各种畸形串、空串、或者只有一个单词的东西。这一堆里藏着一部分伪造流量,后面会碰到。 ## 日志格式不一样怎么办,CDN后面的标识准不准 做这件事之前有两个实操问题得先解决,否则拿到的数据是错的。 前面挂了边缘节点会改变很多判断,六层缓存与边缘路由的实际影响 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)值得一并了解。 格式和真实来源地址都要先配对,访问日志怎么配才查得清问题 (https://zhangwenbao.com/apache-customlog-logformat-access-log-configuration-remoteip.html)把这两件事讲全了。 第一个是日志格式。默认格式里User-Agent通常是最后一个引号包起来的字段,但如果有人改过格式、加过自定义字段,位置就变了。稳妥的做法是先看一行完整日志,数清楚是第几个引号对,再决定取哪个字段。用固定列号去取,改过格式的日志会取到别的东西。 第二个是站点前面有没有CDN或者反向代理。有的话,日志里的来源地址可能全是代理的地址,标识串一般不受影响但也要抽查几行确认。判断爬虫真伪要用真实来源地址,所以得先确认服务器有没有把代理传过来的那个真实地址记进日志。这一步不确认,后面所有关于来源的判断都不成立。 本文的数据在这两点上都核过:标识串取的是最后一个引号对,来源地址是直连地址。 ## 这把尺子的三条边界 这份日志能证明什么、不能证明什么,必须先划清楚,否则后面的比例会被误读。 样本边界会直接影响结论,AI响应模式怎么分析 (https://zhangwenbao.com/ai-response-patterns-deep-decoding-ai-era-content-strategy.html)也强调了取样这一步。 任何数据源都该先校准,第三方数据准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 第一,它是一个站的日志,不是全网样本。某个爬虫没来过这个站,不等于它已经死了——它可能只抓电商站,可能只抓英文站,可能只抓有广告投放的站。所以下面所有没来过的结论,严格表述是这个爬虫在这类站上不活跃。 第二,59天是一个有限窗口。抓取周期长的爬虫可能刚好错过。不过对判断退役与否够用:一个还在运营的搜索或AI爬虫,两个月一次都不来的概率不高。 第三,User-Agent可以伪造。日志里出现某个名字,不代表真是它——这一点在后面会变成本文最有意思的一节。 ## 为什么不用现成的爬虫数据库 有人会问:网上有专门维护爬虫标识的数据库和服务,为什么要自己翻日志。 外部数据源都有盲区,六个工具盲区里的捡漏方法 (https://zhangwenbao.com/keyword-research-tool-blind-spots-overlooked-methods.html)是同一种思路。 外部数据源各有各的边界,五大类工具各自能回答什么 (https://zhangwenbao.com/seo-tools-recommendation-2026.html)可以拿来配自己的组合。 那些数据库解决的是另一个问题——它们告诉你某个标识串属于谁、是什么类型。这个信息很有用,本文查那62个令牌各自是干什么的时候也用到了同类资料。 但它们回答不了本文的核心问题:这个爬虫来过我的站吗。这个问题的答案只存在于你自己的日志里,任何外部数据源都没有。第三方数据库还有个天然的滞后——它收录一个新标识需要有人先发现并提交,而你的日志在对方第一次来的那一秒就已经记下了。 所以两者是配合关系而不是替代关系:日志告诉你有谁来了,数据库帮你查清来的是谁。顺序不能反——先有日志清单,再去查身份,而不是先拿一份数据库清单往文件里抄。 ## 尺子先失效了一次:子串匹配和产品令牌匹配不是一回事 第一遍对交集的时候,出了个非常离谱的结果:有个令牌命中了225万次请求,几乎等于全站流量。 匹配规则本身也常被误解,通配符判定会和标准打架的那几种情况 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)值得对照看。 量错口径这件事非常常见,量出74%的页面有差异,补上对照组后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)是同一类返工。 原因是匹配方式错了。第一版用的是子串包含——只要User-Agent里出现这个令牌的字面就算命中。而其中一个站把整串浏览器标识写成了User-agent值,形如Mozilla/5.0开头的那种。子串一匹配,全站所有浏览器请求都算它来过了。 robots.txt的匹配规则完全不是这样。标准里写明,爬虫拿自己的产品令牌去和User-agent值比对,爬虫排除协议的正式标准 (https://www.rfc-editor.org/rfc/rfc9309.html)里写明,产品令牌是那种简短的标识,不含版本号也不含括号里的描述。所以整串浏览器标识作为User-agent值,永远匹配不到任何爬虫。 修正之后的口径是这样:剔掉9个整串标识型的令牌,剔掉6个长度不足4个字符、没法可靠判定的短令牌(像doc、rma、008这类),剩下266个参与判定;匹配时要求令牌以独立形态出现,后面必须跟斜杠、空格、分号、右括号或者到串尾。这样baidu就不会误命中Baiduspider,chatgpt也不会把ChatGPT-User的请求重复计一遍。 两个口径的差距不小:宽松匹配得出73个来过,严格匹配是62个,虚高了17.7%。这已经是这个项目里第五次栽在尺子上,模式每次都一样——量之前先确认自己量的到底是什么。 ## 266个令牌对上62个,这个交集为什么这么小? 结果摊开:266个被点名的令牌里,59天内真的发过请求的有62个,占23.3%;204个(76.7%)一次都没出现。 想知道它们来了都抓什么,把爬虫的真实抓取偏好逆出来 (https://zhangwenbao.com/ai-crawler-reverse-engineering-fetch-behavior-llms-strategy.html)比看文档更实在。 ## 来过的那62个是什么样的 先看头部。请求量最大的几个是Meta的网页索引器、Googlebot、bingbot、AhrefsBot、ClaudeBot、SemrushBot、Amazonbot,全是当下正常运营的主流爬虫。 这些抓取器的产出去了哪里,引用与排名脱钩之后的判断 (https://zhangwenbao.com/ai-overview-citations-diverge-rankings-bing-geo-2026.html)值得对照看。 新出现的抓取器要及时补进名单,这一类智能体爬虫怎么识别和应对 (https://zhangwenbao.com/google-agent-ai-crawler.html)是最近才有的功课。 令牌 | 被几个站点名 | 59天请求数 | meta-webindexer | 2 | 177874 | googlebot | 22 | 115682 | bingbot | 10 | 46348 | ahrefsbot | 32 | 26224 | claudebot | 12 | 22444 | chatgpt-user | 12 | 10803 | oai-searchbot | 13 | 8155 | gptbot | 14 | 4434 | mj12bot | 34 | 418 | adsbot-google | 74 | 4 | 这张表最后两行很刺眼,后面有一整节专门讲它们。 ## 62个令牌按用途分成五类 把来过的62个按它们干什么归一下,比按请求量排序更有用——因为待遇应该按用途给。 放开检索之后还要够得上门槛,权威信号怎么强化 (https://zhangwenbao.com/strengthen-authority-eeat-signals-ai-citations-2026.html)给了实测区间。 同一家的抓取器规矩也不一样,有一整类抓取器压根不看robots.txt (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)这次改名把它推到台前。 训练和检索必须分开看,内容进模型的四条路 (https://zhangwenbao.com/ai-training-data-four-paths-robots-txt-limits.html)说明了为什么一刀切不管用。 类型 | 代表令牌 | 该给什么待遇 | 网页搜索抓取 | Googlebot、bingbot、Baiduspider、YandexBot、360Spider、Applebot | 放开,重点检查有没有被误拦 | AI检索与回答 | OAI-SearchBot、ChatGPT-User、Claude-User、PerplexityBot、DuckAssistBot、MistralAI-User | 想要AI曝光就放开 | AI训练抓取 | GPTBot、ClaudeBot、CCBot、Google-Extended、Applebot-Extended、Bytespider、img2dataset | 按自己的价值取向决定 | SEO与外链工具 | AhrefsBot、SemrushBot、MJ12bot、DotBot、DataForSeoBot、Screaming Frog | 自己授权的放开,其余按消耗决定 | 社交与聚合 | meta-webindexer、facebookexternalhit、archive.org_bot、FeedBurner | 多数应放开,影响分享卡片 | 这个分类有个直接用处:同一家公司的不同令牌往往属于不同类。比如检索用的和训练用的是两个名字,而且用户触发的取页机器人可能不受robots.txt约束 (https://www.searchenginejournal.com/openai-says-robots-txt-may-not-apply-to-chatgpts-fetch-bot/585864/),两者可以给完全不同的待遇——允许它来抓取用于实时回答,同时拒绝它拿去训练。分不清这一层,就只能一刀切。 ## 请求量高度集中,前十个占了近九成 还有个数字对做决策很有帮助:这62个令牌的请求量分布极不平均。 头部与长尾的分布规律到处都是,十种挖词渠道与意图分类 (https://zhangwenbao.com/seo-long-tail-keywords-expansion-methods-and-ideas.html)也是同一种结构。 把精力放在头部对象上更划算,抓取预算优化的十二项实操 (https://zhangwenbao.com/google-crawl-frequency-optimization-guide-2026.html)也是同一个排序思路。 请求量最大的5个合计38.9万次,占这62个令牌总请求量的73.9%;前10个合计46.1万次,占87.7%。剩下52个加起来不到13%,其中有十几个在两个月里只来了几十次甚至几次。 这意味着名单里真正值得逐个琢磨待遇的对象,大概就十来个。其余的写不写、怎么写,对实际抓取量几乎没有影响。这跟前面那条命中率曲线是一对:名单不但不该长,长了也没用——多出来的部分对应的都是极小的流量。 ## Meta那个爬虫排第一,本身是个信号 请求量榜首是Meta的网页索引器,17.7万次,比Googlebot还多五成。可它只被2个站点名——157份文件里,绝大多数人的名单上没有它。 社交侧的抓取跟着分发走,六个平台的标签用法 (https://zhangwenbao.com/hashtag-social-media-strategy-guide.html)能看出流量来自哪里。 社交平台的抓取影响的是另一条链路,社群信号到底算不算排名因素 (https://zhangwenbao.com/seo-social-signal.html)有八个平台的拆解。 这说明名单和现实的脱节是双向的:既有名单上写着却不来的,也有天天来却没人写的。后者数量还不小,后面单独有一节。 ## 来过一次算不算来过?这个阈值要说清 前面所有比例都用了同一个判据:59天里至少一次请求就算来过。这个门槛很低,得说明为什么这么定。 判据定义决定结论,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭自己的口径。 因为本文要回答的是存在性问题,不是活跃度问题。一个爬虫哪怕只来过一次,也证明它还在运行、还在抓这类站,规则写给它是有意义的。反过来两个月一次都没来的,才有理由怀疑它已经不在了。 不过这个低门槛会带来一个副作用:62个来过的令牌里,有十几个只来了几十次甚至十几次。它们算活着,但对你的抓取量几乎没有影响。如果换成活跃度判据——比如要求月均请求超过一百次——这个数字会从62掉到二十出头。 两个口径服务两个不同的问题:判断该不该删名字用存在性,判断该不该花时间琢磨待遇用活跃度。混用会得出奇怪的结论,比如把一个还活着但很少来的爬虫删掉,然后某天它加大抓取时你的规则里没有它。 ## 没来的那204个,大致分三堆 把没来过的令牌归一下类,来路相当清楚。 老工具的时代留下不少加固习惯,权限分离与应急响应的完整做法 (https://zhangwenbao.com/dedecms-site-security-settings-in-linux-environment.html)至今还适用。 真要动手拦要防误伤,拦AI爬虫与限速怎么不把Googlebot一起拦掉 (https://zhangwenbao.com/nginx-ai-bot-blocking-rate-limit-rdns-misblock-account.html)有具体写法。 第一堆是桌面离线下载工具和开源抓取库:HTTrack、Teleport、WebZIP、WebCopier、SiteSnagger、Offline Explorer、Nutch、libwww、larbin。这类东西的特点是它跑在某个人的电脑上,不是一家公司的服务。157份文件里有36个站(22.9%)点名过至少一个这类工具,Nutch被29个站点名,是其中最多的。 第二堆是已经退役、改名或者不再负责那件事的爬虫,18个站(11.5%)中招。 第三堆是从来没作为抓取标识存在过的名字——某家公司的产品名被当成了爬虫令牌。这类在样本里集中出现在1个站上,一次写了五个。 ## 名单越长,里面来过的比例是不是越低? 把每个站的名单长度和它的命中率放在一起看,出现了一条相当整齐的曲线。 同一个指标各家算法不同这件事到处都有,关键词难度为什么各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 ## 从85.5%一路掉到26.0% 这个站点名了几个 | 站数 | 可判定令牌数 | 其中来过的 | 命中率 | 1到2个 | 53 | 62 | 53 | 85.5% | 3到5个 | 13 | 48 | 34 | 70.8% | 6到10个 | 24 | 166 | 110 | 66.3% | 11到30个 | 17 | 295 | 176 | 59.7% | 31个以上 | 6 | 273 | 71 | 26.0% | 越堆越多会稀释效果,模板和广告稀释主体内容的七个陷阱 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)有对应量法。 越堆越多这个模式在索引侧也有,大量没用的页面怎么诊断和处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 单调下降,没有例外。只点一两个名字的站,命中率85.5%;点了三十个以上的,命中率26.0%,差3.3倍。 ## 为什么会这样:加名字的动机决定了名字的质量 这条曲线的解释藏在动机里。 动机会被流程放大,四类流程漏洞怎么修 (https://zhangwenbao.com/content-publishing-workflow-seo-governance.html)讲的正是这个层面。 照抄清单在工具选型里同样常见,用第一性原理做工具选型 (https://zhangwenbao.com/seo-tools-martech-replacement-trend-2025.html)比跟着别人的清单走稳。 只点一两个名字的人,通常是遇到了具体问题:某个爬虫抓得太凶把服务器压住了,或者不想让某家AI公司拿走内容。他有明确的对象,这个对象是他亲眼在日志或者监控里见过的,所以名字是活的。 点三十个名字的人,动机不一样。他多半是在做一件事情——把这类风险一次性处理干净。而要做到一次性,只能靠找一份现成的清单。清单是别人整理的,整理的时间不确定,有效性无从核对。 所以这条曲线严格说不是长度导致命中率低,而是长名单几乎必然来自照抄,而抄来的名单没人负责保鲜。长度只是这个动作留下的痕迹。 ## 自己名单的命中率,怎么算出来 这个指标可以自己算,成本很低,而且算完就知道该不该动手。 批量核对时别手写语句,安全地批量改一批字段的做法 (https://zhangwenbao.com/sql-generator-batch-update-cms-database-injection-guide.html)能省掉不少风险。 算命中率的前提是日志留得够久,日志怎么管才不爆盘又查得到 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)要先解决。 全站层面的例行检查可以一起做,桌面爬虫能查出的12类问题清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)是配套动作。 做法是三步。第一步,把robots.txt里所有User-agent值抄下来,去掉通配的星号,得到一份名字清单。第二步,在日志里逐个搜这些名字,记下每个名字的请求数——注意搜的时候要求名字后面跟着斜杠、空格或者分号,避免短名字误命中长名字。第三步,数一下有请求的占几成。 命中率在七成以上,名单是健康的,不用管。落在三到七成之间,说明有一批名字该清了,但不着急。低于三成,基本可以断定这份名单是整段抄来的,值得从头重写一遍——重写比逐条排查快。 要注意日志窗口的长度。用七天日志算出来的命中率会明显偏低,因为周期长的爬虫没来得及出现。至少要一个月,两个月更稳。 ## 一个真实的清理过程 保哥去年帮一个做宠物用品的独立站看技术问题,顺手翻了robots.txt,名单上有六十多个名字。问站里谁加的,答案是历任三个人各加过一批,最早那批在建站的时候就有了。 这类工作的交付标准最好写清,达标定义与违约责任怎么写 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)有几个真实纠纷案例。 这类清理通常是审查的一部分,从抓取到AI可见度的完整诊断框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以拿来当清单。 按上面那个办法跑了一遍:从日志里拉出真实来访的抓取程序,再和文件里的名字对。结果是六十多个名字里,两个月内出现过的不到十个,而日志里请求量排前几位的几个抓取器,名单上一个都没有。 清理的做法没什么技巧:把日志里真出现过的挑出来,按用途分成放开、限速、拒绝三档重写;六十多个名字里查不到任何公开资料的直接删;剩下几个还活着但不来这个站的,加了注释留着。文件从九十多行缩到三十行出头。 值得说的是清理之后的变化——抓取量、收录、排名都没有任何变化。这恰恰是预期结果:那些被删掉的规则本来就没在起作用,删掉它们不会有任何指标变好。这类工作的收益不体现在指标上,体现在下一次有人打开这个文件时,他能读懂每一行为什么在那儿。这也是它一直排不上优先级的原因。 ## 命中率低,不等于该把没命中的全删掉 有个反向的提醒:低命中率说明名单质量差,但不代表可以按命中率一键清理。 观察窗口不够就下结论很危险,沙盒和学习期到底怎么回事 (https://zhangwenbao.com/new-site-page-ranking-learning-period-flux-mechanism.html)是同类误判。 指标不动不代表工作没意义,流量暴跌的七个元凶与三个诊断案例 (https://zhangwenbao.com/seo-cant-fix-broken-brand.html)说明了归因有多容易错。 原因还是那把尺子的边界——某个名字在你的站上没出现,可能是它不抓你这类站,而不是它不存在了。比如广告爬虫在没投放的站上不会出现,社交平台的抓取器在没有图片被收藏的站上不会出现,可它们本身活得好好的。 所以处理顺序应该是:先按命中率判断这份名单值不值得信,再对没命中的名字逐个查它到底还存不存在。查存在性靠官方文档,查活跃度靠日志,两件事不能混。查完确认已经消失的删掉,确认还活着但不来你这的可以留着,也可以删——留着的成本是几个字节,删掉的收益是文件短一点。 ## 不过有例外,而例外正是最有价值的部分 把点名超过25个的11个站单独摊开,会发现它们分成截然不同的两群。 例外往往指向真正的原因,技术做到满分却不涨,问题多半在意图没对齐 (https://zhangwenbao.com/search-intent-alignment-vs-technical-seo.html)是另一处。 越熟练越容易漏掉结构性问题,资深团队的技术SEO为什么会失灵 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)讲的正是这类盲区。 站点 | 点名个数 | 可判定 | 来过 | 命中率 | flyingtiger.com | 26 | 26 | 22 | 84.6% | framebridge.com | 28 | 28 | 22 | 78.6% | awaytravel.com | 32 | 31 | 22 | 71.0% | gillette.com | 42 | 42 | 25 | 59.5% | pullandbear.com | 35 | 33 | 11 | 33.3% | bugaboo.com | 26 | 26 | 8 | 30.8% | mango.com | 34 | 32 | 7 | 21.9% | stradivarius.com | 28 | 26 | 5 | 19.2% | bershka.com | 28 | 26 | 4 | 15.4% | salomon.com | 39 | 37 | 4 | 10.8% | lookfantastic.com | 109 | 98 | 2 | 2.0% | 同样是三十个名字上下,命中率从84.6%到2.0%,差了四十倍。长度显然不是决定因素。 ## 同样三十个名字,命中率为什么能差四十倍? 把上面那张表里的名单内容打开看,答案立刻就有了。这两群站抄的是两份完全不同年代的清单。 同类工作里排序比努力更重要,500个站实测排出来的优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)可以直接借。 ## 第一种:这两年的AI爬虫清单 命中率高的那几个站,名单内容长这样——GPTBot、ChatGPT-User、OAI-SearchBot、ClaudeBot、Claude-User、Applebot-Extended、Google-Extended、CCBot、PerplexityBot、Bytespider、Meta的几个抓取器、Amazonbot、Diffbot、YouBot。 放开之后怎么铺开,四大模型的差异化布局 (https://zhangwenbao.com/multi-platform-distribution-ecosystem-ai-citations-2026.html)有具体分工。 还有一种思路是收费而不是拦,要不要向AI爬虫按次抓取收钱 (https://zhangwenbao.com/cloudflare-pay-per-crawl-charge-ai-bots.html)已经有平台在做。 放开这些抓取的目的不只是礼貌,从被看见到被AI推荐的三层框架 (https://zhangwenbao.com/ai-crawler-aeo-optimization-guide.html)列了具体动作。 这些名字全是最近两三年才出现的,而且都还在正常运营。所以命中率自然高:flyingtiger的26个里22个来过,framebridge的28个里22个来过。 这类名单的特点是它有明确的时代背景——AI公司开始大规模抓取内容,站主要表态。清单虽然也是抄的,但抄的时间近,来源方还在持续更新。 ## 第二种:二十多年前的坏机器人黑名单 命中率低的那几个站,名单完全是另一个世界的东西。看lookfantastic那109个名字里的一部分: 同样年代的东西还有不少,某个跳转方案下线之后的完整迁移路径 (https://zhangwenbao.com/baidu-uaredirect-js-dedecms-jumps-to-mobile.html)是一次典型清理。 老配置留下的坑往往很隐蔽,一个看不见的字节头就能让页面白屏 (https://zhangwenbao.com/notepad-edit-saved-code-generate-bom-resulting-web-page-error-white-screen-solution.html)是另一种形态。 - 邮件采集类:EmailSiphon、EmailCollector、EmailWolf、ExtractorPro - 内容抓取类:CherryPicker及其两个变体、LinkExtractorPro、Mata Hari、Mister Pix - 命名调皮的一批:BunnySlippers、CheeseBot、BuiltBotTough、DittoSpyder、JennyBot、LexiBot、NICErsPRO - 整站下载类:TeleportPro、WebZIP、WebStripper、Offline Explorer、Microsoft URL Control 5.01.4511 还有更直接的年代标记:Mozilla/4.0(compatible; MSIE 4.0; Windows 95),以及同款的Windows 98、Windows ME、Windows NT、Windows 2000、Windows XP版本,一共六行。 ## 那些工具当年在干什么 顺着这份清单往回看一段,能理解它当年为什么被整理出来,也更容易判断今天还需不需要它。 被误判成坏东西也要有申诉渠道,三大平台的申诉入口和文案 (https://zhangwenbao.com/tencent-baidu-and-360-three-major-platform-websites-intercept-false-reporting-appeals.html)可以备着。 当年防扒的另一手是防盗链,两种服务器上的防盗链配法 (https://zhangwenbao.com/using-htaccess-to-set-up-wordpress-anti-stealing-link.html)至今还有用。 名单里数量最多的是两类工具。一类是邮件地址采集器,代表是EmailSiphon、EmailWolf、EmailCollector。当年网页上直接写着联系邮箱是常态,这些工具沿着链接爬遍整站,把所有邮箱扒下来卖给发垃圾邮件的人。另一类是整站下载器,TeleportPro、WebZIP、HTTrack、Offline Explorer都属于这一类,功能是把一个网站完整抓到本地硬盘,当年拨号上网按时计费,离线看网页是正经需求。 还有一类数量少但意图明确的,是内容抓取和排名探测工具,比如CherryPicker系列、LinkExtractorPro、Keyword Density。它们服务的是早期的黑帽做法:批量抄内容、批量拿链接。 这三类东西今天基本都不构成主要威胁了。邮箱采集的成本远高于收益,联系方式也早就换成了表单;离线下载的需求消失了;批量抄内容的活现在由更隐蔽的方式完成。所以拦它们不是错,只是不再有意义。 ## 一眼认出老清单的四个特征 不用逐个考据,有几个特征一看就知道这份名单是老的。 老配置文件常一层压一层,重写、缓存、canonical六层怎么排顺序 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)有完整示例。 老配置该逐项过一遍,服务器配置影响SEO的20项清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着核。 第一,名字里带着完整的版本号,形如某个名字加斜杠加1.0。这是从早期日志里直接复制的写法,当时还没有产品令牌的规范说法。 第二,出现Windows 95、Windows 98、Windows ME这类操作系统名。这是最硬的年代标记,没有任何余地。 第三,名字里含Email字样。今天的抓取程序不会用这种命名,那是二十年前的产物。 第四,名字风格拟人化或者调皮,像BunnySlippers、CheeseBot、Mata Hari这种。现在的爬虫命名普遍是公司名加Bot,规整得多。 这四条里命中任意一条,整份清单就该整体怀疑,而不是只怀疑那一行——因为它们通常是整段抄进来的。 ## 这份名单的来路能考据出来 这批名字不是随机的,它们出自2000年代初期一份在站长论坛里广为流传的黑名单。那份清单的目标很具体:当年最猖獗的是邮件地址采集器和整站下载器,前者扒网页上的邮箱去发垃圾邮件,后者把整个网站抓到本地。清单被贴进无数篇教程,也被塞进过各种主机面板的默认配置。 抄示例这件事在各类程序里都有,虚拟文件与物理文件的优先级 (https://zhangwenbao.com/wordpress-add-robots-txt-files-and-optimize-website-collection.html)常被忽略。 问题是这些工具早就不在了。垃圾邮件的获取方式换了,整站下载器也不再是主流威胁。这份清单里的109个名字,在59天日志里只有2个出现过——而那2个后面会讲,它们的出现比没出现更糟。 ## 把Windows 95的浏览器标识当爬虫名,还有一层错 那六行Mozilla/4.0还有个技术层面的问题:它们根本不是产品令牌。 写法层面的检查还是该做,页面骨架的六个维度体检 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)能揪出结构短板。 写法层面的搞混不止这一处,robots.txt和meta robots各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)是最常见的一对。 按标准,User-agent值应该是简短的产品标识,爬虫用自己的产品令牌去匹配。写一整串带括号和版本的浏览器标识,任何爬虫的产品令牌都不会等于它,也不会以它开头。这六行从写下的那一刻起就不可能匹配任何东西——不是因为对象消失了,是因为写法本身不成立。 这也解释了为什么本文要把这9个整串标识型的令牌从统计里剔出去:它们不是收件人不在,是地址栏里填的根本不是地址。 ## 这两年的AI爬虫清单也在过期,只是慢一点 得提醒一句:新清单不等于长期有效。AI相关的抓取标识这两三年变动相当频繁,抄一份两年前的清单,今天也已经有几行是错的。 要跟上变化得有监测面,20款监控工具的评测与选型 (https://zhangwenbao.com/geo-aeo-monitoring-tools.html)可以先看这份。 清单类资产都需要年度复核,12个站样本里的冗余与八步瘦身 (https://zhangwenbao.com/ai-tool-stack-annual-audit-12-sites-4-dimensions-8-steps.html)是同一个治理思路。 变动主要有三种形式。一是改名,旧标识停用、新标识启用,本文那些claude-web就属于这一类。二是拆分,原来一个标识负责的事被拆成两三个,训练用一个、用户触发取页用一个、检索索引再用一个——这种拆分对写规则的人影响最大,因为原来一行现在要写三行,而且待遇可能不同。三是新增,某家公司推出新服务就多一个标识。 所以AI爬虫这一块的复核频率要比其它类型高。本文的建议是这一类每半年过一遍对方文档,其余类型一年一次。判断的锚点是对方的官方说明页,而不是任何第三方整理的清单——第三方清单本身也在滞后。 反过来这也说明为什么名单该短:名单越短,复核的成本越低,越可能真的被复核。一份十个名字的清单半小时能核完,一份一百个名字的清单谁都不会去核。 ## 抄清单本身不是错,抄之前问一句是哪年的 说清楚一点:这两群站的做法在结构上是一样的,都是抄清单。区别只在于抄的那份清单是哪一年整理的。 批量套用的东西质量取决于模板,从模板化转向语义化的八步 (https://zhangwenbao.com/semantic-programmatic-seo-blueprint.html)讲了怎么把默认做扎实。 把判断交给自动化之前有前提,数据、方法、人工复核这三条 (https://zhangwenbao.com/ai-seo-geo-audit-agent-pitfalls.html)缺一条结论就不能用。 所以判断一份现成名单值不值得抄,有个很快的检验:随机挑三个名字去搜一下,看它们最近有没有公开活动的痕迹——官方文档还在不在、有没有更新过、能不能查到抓取行为说明。三个里有两个查不到,这份清单就该整体放弃。 这个检查花五分钟,能省掉一份躺在文件里十年的死名单。 ## 那几个已经退役的令牌,来的真是它们吗? 接下来这一节是整篇里最出乎意料的部分。 拦截层的实际效果也常与预期不同,防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测出的答案挺意外。 前面说没来过的有204个,那意味着有些退役令牌是来过的。翻开这些请求的具体User-Agent串,才发现问题完全不是想象的那样。 ## 四个退役令牌在日志里的真面目 令牌 | 被几个站点名 | 59天请求 | 日志里实际的标识串 | claude-web | 7 | 15 | Mozilla/5.0 (compatible; Claude-Web/1.0; +官网首页地址) | anthropic-ai | 7 | 42 | 裸的anthropic-ai,整个标识就这一个词 | slurp | 2 | 14 | Yahoo! Slurp China,以及带乱码引号的Yahoo! Slurp | msiecrawler | 5 | 2 | MSIE 5.01; Windows NT 5.0; YComp 5.0.2.6; MSIECrawler | 判断真假靠特征而不是印象,十二项语言特征怎么拆 (https://zhangwenbao.com/ai-detector-12-signal-humanize-guide.html)是另一个例子。 换身份看同一个地址是常用手法,对比爬虫和用户看到的页面 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)用的也是这套办法。 四个都是伪造的,判据在标识串本身。 ## 判断伪造不用查IP,看格式就够 先说Anthropic那两个。这家公司现行公开的抓取标识是三个,各有各的用途,格式统一,都带完整的浏览器兼容前缀和一个联系邮箱。而日志里那42次请求的标识是裸的一个词,什么都没有;那15次的格式虽然像样,指向的却是公司官网首页,而不是官方文档里写的那个联系地址。 状态码本身也是判断线索,301、302、404和410分别该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)是一张速查表。 伪造流量之外还有更直接的骚扰,登录怎么加固才不被爆破 (https://zhangwenbao.com/linux-server-ssh-login-hardening-key-auth-sudo-fail2ban-brute-force-protection.html)是同一批日志里能看到的事。 换句话说,这两个标识都不符合这家公司自己公布的格式。真正的爬虫没有理由用一个官方从未使用过的写法。 Yahoo那个更明显。日志里的串写着Yahoo! Slurp China——Yahoo中国的搜索业务2013年就关了。另外两条的标识末尾带着编码错乱的引号,是从某处复制粘贴时带进来的脏字符。真实的爬虫标识不会有这种东西。 最后那个MSIECrawler,标识里写着IE 5.01加Windows NT 5.0,还带着一个2001年前后的Yahoo工具栏版本号。2026年发出这样一个标识的,只能是拿老UA库随机取值的扫描程序。 ## 再往下查一层:这些请求在找什么 光看标识串还不够,把这些请求的完整日志行拉出来,才看到真正的答案。 密钥和配置文件的暴露面值得系统看一遍,从审查到权限与提示注入防御 (https://zhangwenbao.com/claude-code-security.html)给了完整清单。 被试探的那些路径要先堵住,五种环境禁掉执行权限的加固写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是最直接的一层。 那15次冒用Claude-Web的请求,状态码全部是404,一次成功都没有。请求的路径是这些: - /.env.example、/admin/.env——应用的环境变量文件,里面通常有数据库密码和接口密钥 - /.github/workflows/deploy.yml——持续集成的部署脚本,可能含部署凭证 - /service-account.json——云平台的服务账号密钥文件 - /.gitconfig——版本库配置 冒用anthropic-ai的那42次是同一个路子,40个404加2个被服务器直接断开连接,请求的是/gcp-key.json、/server.key、/docker-compose.yaml这一类。 这不是爬虫。这是凭证扫描——挨个试探常见的密钥文件路径,看有没有哪个站忘了把它挡住。 ## 两个不同的名字,用的是同一批地址 更能说明问题的是来源地址。这两组请求分别来自3个和6个地址,而其中两个地址是共用的:一个属于某家公有云的计算实例,另一个属于某个消费级网络代理服务。 要顺着地址往上查,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)给了完整路径。 同一批地址反复来还有别的形态,被攻击时从识别到应急拦截 (https://zhangwenbao.com/wordpress-ddos-protection-guide.html)讲的是量级更大的情况。 也就是说,同一个扫描程序换着不同的爬虫名字在敲门。它今天叫Claude-Web,明天叫anthropic-ai,用的是同一台机器。选这两个名字大概率不是随机的——挑一个听起来像正经AI公司的名字,被人工翻日志时更容易被划过去。 另外几个退役令牌的情况类似但动机不同。冒用Yahoo Slurp的14次请求来自5个云主机地址,抓的是首页和一篇文章,看着像内容采集;冒用MSIECrawler的2次来自国内家宽地址,请求的是两个标签页,更像某个老工具的残留。只有WebZIP那1次是访问首页,什么也没做。 ## 于是这条规则的实际效果,是反过来的 把这件事想透会有点不舒服。 规则和对象错位还有另一种,通配组的星号对广告爬虫不生效 (https://zhangwenbao.com/robots-wildcard-adsbot-special-case-crawlers.html)也是两头落空。 假设你在robots.txt里给claude-web写了一组规则,Disallow: /。你的意图是拦住Anthropic的抓取。实际发生的是两件事: 第一,Anthropic真正在用的那三个标识不叫这个名字,它们不会匹配这一组,会落到通配组或者它们各自的组里去。也就是说你想拦的对象,压根没被这条规则碰到。 第二,唯一会匹配claude-web这个组名的,是那个冒用这个名字的程序。而冒名的程序不读robots.txt——它伪造身份的目的就是绕开限制。 所以这一组规则的效果是:对真实对象无效,对唯一匹配它的对象也无效。它是一条两头都落空的规则,而且写它的人完全有理由相信自己已经把事情办了。 ## 比无效更麻烦的是它带来的安全感 这里有个值得停一下的地方。 看着做完了其实没做成的情况不少,批量内容撞上质量墙的五层工具栈 (https://zhangwenbao.com/ai-content-scaling-failure-quality-wall.html)是另一种形态。 假的完成状态最难发现,托管主机可能正悄悄拦掉AI爬虫 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)而监控一声不响。 如果那15次扫描是用一个陌生名字来的,翻日志的人会警觉:这是谁,在找什么。可它用的是一个听起来完全正当的AI公司名字,而且这个名字还写在自己的robots.txt里——名单上有它,说明这事管过。于是这行日志被跳过的概率大大提高。 换个角度说:名单上那个已经不存在的名字,不但拦不住任何东西,还给冒用它的程序提供了一层伪装色。你亲手把这个名字写成了自己认识的、处理过的、不需要再看的东西。 这不是robots.txt的设计缺陷,是名单不保鲜的连带后果。名字一旦失去真实指向,它就成了一个可以被任何人占用的空壳。 ## 真正该做的是把这两件事分开 结论其实很清晰:意愿表达和身份验证是两件事,别指望一个文件同时办。 最外面那层也要配对,端口放行与云安全组怎么配 (https://zhangwenbao.com/linux-ufw-firewall-server-port-rules-ssh-cloud-security-group.html)是基础动作。 访问控制该在服务器层做,从版本隐藏、目录权限到访问控制 (https://zhangwenbao.com/apache-server-security-hardening-version-hide-directory-access-control-waf.html)是一份可执行的加固表。 意愿表达用robots.txt,写给对方现行的、公开申报的产品令牌,写完就可以不管——愿意配合的会配合。身份验证在服务器或者边缘层做:对自称是某家爬虫的请求,反查来源地址是否属于对方公布的地址段,或者做一次反向域名解析再正向确认。对不上的按普通可疑流量处理。 顺带一句成本很低的补充动作:那些密钥文件路径本来就不该能被请求到。日志里这些扫描全部返回404是好事,但更好的是在服务器配置里把点开头的文件、常见密钥文件名、部署配置目录统一拒掉,连404都不给。这跟robots.txt无关,但既然扫描已经找上门了,顺手补上比写十行名单实在。 ## 伪造这件事有多普遍,怎么快速筛出来 既然碰到了,顺手量一下这个层面的规模。 恶意方向的手法在演进,三条攻击路径与三层防御 (https://zhangwenbao.com/geo-ai-poisoning-315-deep-analysis.html)值得先了解。 这类筛查适合做成常规,怎么搭一套能在掉量前报警的监控 (https://zhangwenbao.com/seo-monitoring-alerting-regression-detection-system.html)里有可复用的规则。 日志里那4232个无法归类的标识串是重点嫌疑区,它们只贡献了2.2%的请求,却占了标识串总数的一成多。这个比例本身就不正常——正常的浏览器和爬虫标识是高度重复的,几万次请求共用一个串;而伪造流量倾向于每次换一个,于是串多请求少。 快速筛的办法有三条,都不需要工具。 第一条看请求数与串数的比例。一个标识串只出现过一两次,而且格式古怪,基本可以怀疑。第二条看请求的路径。正常爬虫抓的是页面和资源,伪造流量爱试探配置文件、备份文件、后台路径——本文那两组冒名请求就是这么露出来的。第三条看状态码。一整串请求全是404,说明它在猜路径而不是在抓内容。 三条里命中两条,基本就能确定。确认之后不用逐个封禁,把那几个来源地址段加进拒绝列表,或者交给边缘层的规则处理,比在robots.txt里做任何事都有效。 ## 该怎么处理这类名字 旧名字的正确处理方式不是删掉了事,而是查一遍对方现在用什么名字,把规则迁到新名字上。 对方换了名字之后抓取行为的变化会反映在报告里,五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)能帮你确认迁移有没有生效。 拿这个例子说:把claude-web和anthropic-ai这两组删掉,换成对方现行公布的那三个标识,各自按用途给规则——训练用的和检索用的可以给不同待遇。这一步做完,规则才第一次真正对上人。 至于伪造的那部分请求,robots.txt从来管不了它们。要处理得换层:在服务器或边缘层做反向解析校验,确认来源地址是不是真属于对方公布的地址段,不匹配的直接拒。这是另一套机制,跟这个文件没关系。 ## 给不存在的对象,一共写了多少条规则? 点名只是第一步,点完还要写规则。所以还有个数字值得算:这些没有收件人的分组里,一共躺着多少条规则。 规则该写给哪些路径是另一半功课,电商该屏蔽的七类页面 (https://zhangwenbao.com/page-types-to-block-in-robots-txt-for-ecommerce.html)里有逐类判断依据。 ## 44个站,215条规则 把所有命中退役令牌、从未存在的令牌、桌面工具令牌的分组挑出来,数它们组内的规则条数:44个站,合计215条,中位数是1条。 成批确认状态有现成流程,死链批量检测与分类提交 (https://zhangwenbao.com/batch-detection-of-site-dead-links.html)可以直接跑。 真正需要挡的地址里最难缠的是筛选组合,分面导航产生的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)单独讲过。 写得最多的几个:framebridge.com 46条,fromourplace.com 33条,lookfantastic.com 19条,pullandbear.com 13条,mango.com 12条。 要说明的是framebridge这个数字不算浪费——它的名单是新的AI爬虫清单,命中率78.6%,那46条里大部分是有对象的。真正空转的是lookfantastic那19条和几个西班牙品牌站的十几条。 ## 其中111条是全站禁抓 更值得看的是这215条里规则类型的分布:有111次写的是Disallow: /,也就是整站禁止抓取。 真需要全禁的场景确实存在,预发布环境被索引之后的八步清除 (https://zhangwenbao.com/staging-preproduction-environment-index-leak-prevention-recovery.html)就是其中一种。 禁抓和不收录是两件事,加了标记之后多久才真正消失 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)有六个场景的观测。 这个比例说明了这类规则的写法特征——面对一个不认识或者不想要的爬虫,人的第一反应是全站拉闸,而不是挑几个目录。这个反应本身没问题,问题是拉闸的对象已经不存在了,闸门关在了一个没人走的门上。 ## 那111条全站禁抓,写法上还有个连带风险 全站禁抓这个动作本身没问题,但它跟前缀匹配规则一起用的时候,有个容易忽略的连带效果。 配置的副作用往往不出声,每次reload都通过,Googlebot每8次抓取却有1次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类沉默。 假设你想拦一个叫做SomeBot的抓取器,结果名字写短了,写成了Some。按前缀匹配,所有产品令牌以Some开头的爬虫都会落到这一组,然后被整站禁抓。如果里面恰好有一个是带流量的搜索抓取器,那这一行就从拦截变成了自伤。 这个风险在名单短的时候几乎不存在——名字少,每个都认真写了。名单一长就开始出现,因为长名单里的名字往往是从别处成段复制的,谁也没逐个核对完整拼写。 样本里没有发现这种误伤的实例,但有几个站的写法离危险不远:把某个厂商名的前几个字母单独成组,同时组内写着全站禁抓。这类写法只要那个厂商未来推出一个带流量的抓取器,就会被顺带拦住,而且拦了不会有任何提示。 还有个容易忽略的连带影响:这些分组会让文件变得难以diff。改版的时候想比较两个版本的robots.txt差异,一百行里有七十行是无效内容,真正的变化很容易被淹没。把无效内容清掉之后,每次改动都一目了然——这对需要评审配置变更的团队来说,价值比省几个字节大得多。 ## 这些规则的代价,不在服务器上 跟上一类问题一样,这215条不消耗任何资源,也不影响收录。爬虫读到不属于自己的分组会直接跳过。 换架构时这些包袱最难搬,这套基建换了架构就得自己重搭 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是提前的提醒。 冗余配置最后都会变成读不懂,插件与主题各输出一套标记怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一种病。 代价在两个地方。一是文件长度,一个原本二十行的文件因此变成八十行,可读性下降;二是它制造了一种覆盖感——名单上有一百个名字,看上去防线很密,实际上密的是名字不是防线。这种覆盖感会让人不再去看日志,而日志才是唯一能看到真实抓取情况的地方。 ## 被点名最多的那个爬虫,为什么本站几乎见不到? 交集数据里有一组反差特别大的对比,值得单独拆。 广告落地页那条链路自己也有讲究,文案原料全在落地页上 (https://zhangwenbao.com/ad-landing-page-copy-source-robots-template.html)说明了它为什么被单独抓。 ## 74个站点名,59天来了4次 被点名最多的令牌是adsbot-google,157份文件里有74个(47.1%)提到它。这个数字的来源不神秘——它出自主流电商平台的默认模板,用平台建店就自带。 投放期的抓取节奏确实不一样,大促与日常SEO的八维度差异 (https://zhangwenbao.com/seo-during-sales-events-vs-daily-work.html)有时间轴可参考。 平台默认带来的东西不止这一行,平台内置、通用工具与专属应用的三层框架 (https://zhangwenbao.com/shopify-seo-tools-three-layer-selection.html)能帮你分清哪些该接管。 而它在这份59天日志里一共发了4次请求。 紧随其后的几个也类似:mj12bot被34个站点名,来了418次;按AhrefsBot与AhrefsSiteAudit的说明 (https://ahrefs.com/robot),后者是站主自己在工具后台授权的审计爬虫,只会去授权它的站,本文日志里它来了11350次;pinterest被27个站点名,一次没来。 ## 这种反差不是矛盾,是结构差异 解释很简单,但值得说清楚,因为它揭示了名单该怎么读。 同一个动作在不同站上的效果差很多,三平台和300个站的收录速度实测 (https://zhangwenbao.com/seo-kpi-guide.html)能看出差距。 广告爬虫只抓有广告投放的落地页,本文这台服务器没有投放,所以它几乎不来。Pinterest的抓取集中在被用户保存过图片的页面上,一个中文技术博客不在它的范围里。而Googlebot、bingbot、AI公司的抓取器不挑站,所以它们出现在几乎所有日志里。 所以正确的读法是:被点名的次数反映的是模板的分发量,请求次数反映的是这个站的真实处境,两者本来就不该相等。 ## 不同类型的站,爬虫构成能差多少 把这个差异具体化一点。本文这台服务器是中文技术内容站,它的爬虫构成大致是:网页搜索抓取占大头,AI相关的抓取器紧随其后,SEO工具类中等,社交与聚合类少,广告类几乎为零。 内容形态决定谁来抓,帮助中心怎么做索引控制与AI引用 (https://zhangwenbao.com/knowledge-base-help-center-seo-indexing-ai-citation.html)是另一种典型。 站的结构决定爬虫怎么走,架构怎么搭才不让爬虫找不到产品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是更上游的决定。 换成一个投了搜索广告的英文电商站,构成会明显不同:广告爬虫会成为常客,因为它必须核对每一个落地页;商品比价和购物聚合类的抓取会出现;社交平台的抓取会因为商品图被收藏而增加;而中文搜索引擎的抓取基本消失。 再换成一个企业官网,量级整体下降,但结构更集中——主要就是几家搜索引擎和几个安全扫描服务,AI抓取的比例反而可能更高,因为企业信息是模型爱抓的内容类型。 这三种构成没有哪个是标准答案。所以一份放之四海皆准的爬虫名单在逻辑上就不成立,它只能是某个特定站在某个特定时期的观察结果。 ## 这里有个本文测不了的问题,得说清 还有一层必须承认的局限:那74个点名广告爬虫的站,究竟有多少真在投广告,本文没法知道。 测不了的时候要说清边界,site命令能查什么、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)也是这个态度。 如果一个站确实在投放,那这一行是有意义的——广告爬虫会去抓它的落地页,规则写对了位置就能起作用。所以不能一概说这74行都是空转的。 能确定的只有两件事:一是这一行来自平台默认模板而不是站主的判断,二是在没有投放的站上它不产生任何效果。至于每个站属于哪种情况,只有站主自己看后台能确认。这个区分很重要——本文量的是名单和现实的偏差,不是每一行的对错。 ## 把两个方向的差集放在一起看 到这里两个方向的数字都有了,摆在一起才看得出这件事的全貌。 两头都变的时候最难解释,流量下降怎么跟老板交代 (https://zhangwenbao.com/seo-traffic-decline-ai-search-value.html)有一套完整口径。 两个方向的差集在别处也有,同域、跨域、参数变体六类重复怎么治 (https://zhangwenbao.com/content-duplicate-issue.html)可以对号入座。 方向 | 数量 | 说明 | 名单上有,但没来过 | 204个令牌 | 占可判定令牌的76.7%,大多是老工具和退役对象 | 名单上有,也来过 | 62个令牌 | 其中前10个占了请求量的87.7% | 来过,但名单上没有 | 137个标识 | 合计89202次请求,157份文件里无人点名 | 三行数字合起来说明一件事:名单和现实的重叠部分,比两边各自的规模都小得多。一份典型的robots.txt名单,大部分内容对应不到真实抓取行为,而真实抓取行为里又有一大块不在名单上。 这个结构决定了维护方式。如果偏差主要来自存量老化,那定期清理就够;如果偏差主要来自增量缺失,那必须建立从日志到名单的通道。而本文的数据显示两种偏差都很大——所以两件事都得做,而且后者更重要,因为它对应的是正在发生的抓取。 ## 推论:名单不该照抄,因为你的站和别人的站不一样 这一节最实用的推论在这里。既然爬虫的抓取范围取决于站点自身的类型、语言、投放和内容形态,那么任何一份现成名单都不可能适配你的站。 按自己站的情况排序才有效,三类站点各自的高回报修复项 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以直接借。 投了广告的电商站需要管广告爬虫,不投的站写了也是空转;有大量图片被社交平台收藏的站需要管社交爬虫,纯文字站不需要;做英文内容的站会被更多AI爬虫盯上,纯中文站的抓取者构成完全不同。 这个差异没法靠抄清单解决,只能靠看自己的日志。这也直接引出了后面那一节。 ## 日志里那批谁都没点名的爬虫,该管吗? 反过来查一遍更有意思:日志里那些确实来过的抓取程序,有多少在157份robots.txt里压根没被提到。 要限速得先想清副作用,限速规则拒掉的第4个请求正好是robots.txt (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html)会让全站抓取停十几个小时。 ## 137个标识,89202次请求 结果是137个自称爬虫的标识串,合计89202次请求,没有任何一个站在名单里写过它们。 这类量级的请求会影响运维安排,增量备份与快照怎么做才不出事 (https://zhangwenbao.com/linux-server-rsync-incremental-backup-snapshot-link-dest-offsite-restore.html)是配套功课。 这些请求的累积影响未必有声音,抓取速率被调低的那几天日志里一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这种情形。 请求量排在前面的几个: 标识 | 59天请求数 | 是什么 | curl | 42688 | 命令行工具,三个不同版本合计 | LinkupBot | 18200 | 一家做网页索引的服务 | YisouSpider | 13923 | 国内搜索抓取 | SERankingBacklinksBot | 8418 | SEO工具的外链爬虫 | CodexResearchBot | 5136 | 自称做站点清点的研究爬虫 | FeedBurner | 1611 | 订阅源抓取 | ShapBot | 1951 | 来源不明 | GeneralCrawlBot | 1071 | 来源不明 | Python的几种HTTP库 | 约1500 | 脚本请求,多个版本 | ## 这份清单里最值得注意的是新面孔 LinkupBot、CodexResearchBot、ShapBot、GeneralCrawlBot、HeyBlogBot、AwarioSmartBot、FindFiles、DuckAssistBot这些名字,绝大多数是最近一两年才出现的。它们不在任何一份流传的清单里,因为清单的整理速度跟不上新服务的出现速度。 要不要对它们放开取决于回报,四大AI搜索引擎的分引擎策略 (https://zhangwenbao.com/ai-search-engine-geo-optimization-strategy.html)有具体判断。 新服务出现的速度确实快,10款主流AI搜索工具的实测对比 (https://zhangwenbao.com/what-is-ai-search-tools-comparison.html)能看出这两年的密度。 这就构成了名单的第二个结构性缺陷:它不但会留下已经消失的对象,还会漏掉正在活动的对象。前者是存量问题,后者是增量问题,而后者的影响更实际——真正在消耗你带宽的往往是那些没人点名的。 还有个判断上的细节值得提:这137个里有一部分是同一个服务的不同版本,比如命令行工具的三个版本号、Python几个HTTP库的不同版本。按标识串数它们是好几个,按对象数其实是一个。所以看到这个数字不用紧张,真正需要区分对待的对象比137少得多。 反过来也有需要合并看的:某些服务会同时用两三个标识,分别对应不同用途。判断的时候按对象合并,比按标识串逐个处理省事,也更不容易漏。 ## 这137个里面,哪些该管哪些不用管 清单拉出来之后总要做决定。按三个问题分,基本就够了。 先估值再决定拒绝是通用做法,八步有毒外链审计 (https://zhangwenbao.com/backlink-value-evaluation-toxic-link-audit.html)是同一个流程结构。 外链工具的爬虫是典型的纯消耗方,反链工具怎么选与竞品反链拆解 (https://zhangwenbao.com/backlink-analysis-tools.html)解释了它们为什么抓得勤。 第一个问题是它带不带回报。搜索类和AI检索类的抓取会带来曝光,哪怕名字陌生也该先查清是谁,再决定。本文这份清单里的LinkupBot、DuckAssistBot属于这一类,它们背后是检索服务,拦掉等于自断一条曝光渠道。 第二个问题是它耗不耗资源。SEO工具的外链爬虫、通用研究爬虫属于纯消耗——它们抓走的数据用于别人的产品,对你没有直接回报。这类的处理取决于量:请求量小可以不管,大到影响服务器就限速。 第三个问题是它说不说得清自己是谁。清单里有几个标识只有一个名字加版本号,没有说明地址,也查不到任何公开资料。这类应该按可疑处理——不是因为它一定有害,而是因为无法评估。 按这三问过一遍,137个里通常只有十个上下需要真正处理,其余的记录下来下次再看就行。 ## 新爬虫出现和被写进清单之间,差多久 还有个值得估一下的量:一个新抓取服务出现之后,多久才会进入公开流传的清单。 格局变化的速度决定清单的寿命,全球搜索引擎格局与多平台优化 (https://zhangwenbao.com/search-engine-landscape-seo-strategy-guide.html)给了一份比例参照。 从本文的数据能大致推断。日志里那些新面孔多数是最近一两年出现的,请求量已经不小;而157份robots.txt里没有任何一个站点名过它们。也就是说滞后至少是以年计的。 这个滞后是结构性的,不可能通过更勤快地看文章解决。清单的生产链条是这样:新爬虫出现,被少数站主在日志里注意到,有人写成文章,文章被读到,被抄进文件。这条链每一环都要时间,走完通常一年以上。 而你自己的日志是零延迟的——它在爬虫第一次来的当天就记下了。所以真正能跟上现实的名单只有一种:从自己的日志长出来的那种。这也是下一节要说的做法。 ## 还有一类不该忽略:命令行工具和脚本 请求量最大的其实是curl,三个版本合计42688次,超过Googlebot的三分之一。加上Python的几个HTTP库,脚本类请求相当可观。 脚本请求打上来时缓存层最吃力,字节码缓存怎么调 (https://zhangwenbao.com/php-opcache-bytecode-cache-tuning-preload-jit-hit-rate.html)能扛住一部分。 脚本请求扎堆会直接反映在负载上,负载飙高怎么定位到进程 (https://zhangwenbao.com/linux-server-performance-troubleshooting-high-load-cpu-memory-disk-io-diagnosis.html)是应急时的路径。 这类请求robots.txt完全管不了——它没有产品令牌可以匹配,写规则也无处安放。它们的处理方式只有服务器层:按频率限速、按来源封禁、或者对可疑标识返回验证挑战。 把这一层认清有个好处:你会明白robots.txt能覆盖的范围其实是有限的。它只对那些既自报身份、又愿意遵守规则的程序有效。日志里那些用命令行工具和脚本库发出的请求,从一开始就不在这个文件的管辖范围内,数量还不小。 ## 令牌到底怎么写,才会真的被匹配到? 前面反复出现过写法层面的问题,这里集中说清楚。名单里有相当一部分行,不是对象不在,是写法本身不成立。 写法细节决定成败这件事到处都有,URL结构与slug的九个细节 (https://zhangwenbao.com/url-structure-slug-optimization-onpage-seo-mechanism.html)是另一处例子。 ## 匹配的是产品令牌,不是整串标识 标准里的规则是:爬虫用自己的产品令牌,去和文件里的User-agent值比对,不区分大小写,取匹配得最具体的那一组。产品令牌是简短标识,比如Googlebot、GPTBot、ClaudeBot,不带版本号,不带括号里的描述。 同样的列举法用在链接上也管用,一次扒清链接结构与扣分项 (https://zhangwenbao.com/link-analyzer-internal-external-audit-guide.html)有现成输出格式。 各家的硬边界都该记在一张表里,抓取体积上限的实测拆解 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)给了具体数值。 所以下面这几种写法都不会命中: 写法 | 样本里有几个 | 问题 | 整串浏览器标识 | 9个 | 没有任何爬虫的产品令牌以它开头 | 令牌带斜杠版本号 | 22个 | 对方申报的产品令牌里不含版本号 | 令牌里带空格和括号 | 38个 | 多数不成立,少数例外见下 | ## 带版本号的写法为什么不行 样本里有22个令牌写成了名字加斜杠加版本的形式,像iaskspider/2.0、propowerbot/2.14、harvest/1.5这样。 一个字符的差别能让整块失效,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)是同类的静默错误。 写的人大概是从日志里直接复制了标识串的一段。问题是匹配用的产品令牌不含版本——对方申报的是名字本身,版本号是运行时附加的。所以写上版本号之后,这一组就永远匹配不到它想匹配的对象。 正确做法是只写名字,版本号去掉。这样无论对方升到哪个版本都能匹配。 ## 带空格的令牌有例外,得看对方怎么申报 含空格的令牌需要分开看。像Sogou web spider、Screaming Frog SEO Spider这两个,对方申报的产品令牌里确实带空格,写上去是有效的——日志里也证实了它们的请求。 国内引擎的申报方式确实不同,做搜狗SEO绕不开的那套生态 (https://zhangwenbao.com/sogou-seo-china-search-wechat-public-account-indexing-guide.html)可以顺带看看。 但样本里另外那些带空格的,比如Black Hole、Mata Hari、Kangaroo Bot、Download Ninja,属于前面说的老黑名单,对象本身就不存在了。 判断办法只有一个:查对方的官方说明,看它自己怎么写这个名字。查不到说明的,八成不该写进去。 ## 空分组和空Disallow,各是什么意思 还有两个写法容易被混淆,它们的含义正好相反。 一字之差含义相反的情况不少,自定义错误页与软404的正确配法 (https://zhangwenbao.com/apache-errordocument-custom-error-pages-http-status-codes-soft-404.html)最容易配错。 这个文件常被用来解决它管不了的事,用robots.txt拦UTM参数的危害 (https://zhangwenbao.com/robots-txt-disallow-utm.html)就是一例。 一个分组只写了User-agent,下面一条规则都没有,这一组等于什么都没说——对方匹配到它,然后发现没有任何限制,于是全部允许。这种空组在样本里不算少,多半是删规则的时候把组名留下了。 另一种是写了Disallow但值为空,也就是冒号后面什么都没有。按标准这明确表示允许抓取全部内容,跟写Allow斜杠效果相同。它跟Disallow斜杠只差一个字符,含义完全相反——前者是全部允许,后者是全部禁止。 这两种写法本身都是合法的,但在长名单里很危险:一个本意是禁抓的分组,只要那一行的斜杠掉了,就从全禁变成全放,而文件看上去毫无异常。检查的办法很简单,把所有Disallow后面为空的行找出来,逐个确认是不是有意为之。 ## 名字写错了会怎样,有没有兜底 还有个常被问到的问题:如果名字拼错了,会不会造成事故。 不同工具的判定口径本就不同,爬虫报的死链和Googlebot抓的从来不同 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html)解释了差异来源。 结论是不会造成事故,但会静默失效。拼错的名字匹配不到任何爬虫,那一组规则就永远不执行,效果等同于没写。没有报错,没有告警,文件照样合法。 不过有一种情况需要留神——拼错的方向。如果把名字写短了,比如本想写某个完整令牌却只写了前几个字母,按前缀匹配它会命中所有以这几个字母开头的令牌,范围可能远超预期。所以拼错的两个方向后果不同:写长了或者写错字母是失效,写短了是扩大范围。 至于兜底,唯一的兜底是通配组。任何没有匹配到专属分组的爬虫都会执行通配组的规则,所以通配组应该写得足够完整——把真正不希望被抓的路径都放进去。这样即使某个专属组因为名字写错而失效,对象也会落回通配组,而不是落到一个什么限制都没有的状态。 ## 同一个名字写在两个分组里会怎样 长名单还常出现另一种情况:同一个爬虫名在文件里出现了两次,分属两个不同的分组,规则还不一样。 同一件事声明两遍就会打架,跨页场景下的八种冲突 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)有对应诊断办法。 标准对这种情况的处理是合并——匹配到同一个名字的多个分组,规则会被当成一组来执行。但不同解析器在细节上未必完全一致,尤其当两组规则互相冲突的时候,谁优先取决于实现。 所以这种写法应该避免,它属于把结果交给运气。检查方式是把所有User-agent值排序去重,看有没有重复项。样本里有几个站存在这种重复,都是名单增长过程中重复添加造成的——加的时候没搜一下文件里有没有。 ## 大小写不用纠结,前缀匹配要留神 两个容易多虑或者漏掉的细节。 分布和范围的把握是另一种功课,从锚文本分布看过度优化风险 (https://zhangwenbao.com/anchor-text-analyzer-penguin-distribution-guide.html)是同类判断。 大小写完全不影响匹配,写GPTBot、gptbot、GPTBOT效果一样,不用为此纠结。 前缀匹配则要留神:如果写了一个较短的名字,它会匹配到所有以它开头的令牌。比如只写Google,会同时命中Googlebot、Googlebot-Image、Google-Extended、GoogleOther这一整批——这可能不是你的本意。要精确控制就写完整的名字,一个一组。 ## 名单该怎么维护,才不会落后于现实? 问题诊断到这里已经很清楚:抄来的名单会同时犯两个错,留下死的、漏掉活的。那正确的做法是什么。 例行动作最好挂成定时任务,用cron把备份、sitemap、缓存这些活自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)有可直接改的脚本集。 ## 顺序反过来:先看日志,再写名单 核心只有一句:名单应该是日志的产物,不是文章的产物。 从原始数据里挖结论是同一个套路,用正则从后台挖AI搜索提问 (https://zhangwenbao.com/gsc-regex-mine-ai-search-prompts-guide.html)也是这么做的。 不过不是所有事都该自动化,哪些能交给工具、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条比较清楚的界。 具体做法是先从自己的日志里把真实来访的抓取程序列出来,按请求量排序,然后逐个决定怎么对待。这样得到的名单天然满足两个条件——它上面的每个名字都是真的会来的,而且都是真的来过你这个站的。 ## 一条命令拿到自己的爬虫清单 从日志提取爬虫标识不需要工具,一行管道就够: 想让它定期跑起来,把定时表达式写对的具体办法 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)可以直接生成。 awk -F'"' '{print $6}' /www/wwwlogs/example.com.log | grep -Ei 'bot|spider|crawl|slurp|fetch|python|curl' | sort | uniq -c | sort -rn | head -40 输出是按请求量排序的标识串清单。日志格式不同的话,调整取字段那一步就行。 拿到清单之后做三件事:把请求量最大的十几个挑出来,逐个查清是谁、抓什么用途;对照现有robots.txt,看名单上有没有它们;把文件里那些日志中从未出现的名字标记出来,等一个观察周期再决定是否删除。 ## 多久复核一次,复核什么 名单不是一次性工程,但也不需要频繁维护。按本文观察到的变化速度,一年一次足够,赶上大变动的时候临时加一次。 复核这件事在外链侧已经工程化了,反链流失监控与回收的SOP (https://zhangwenbao.com/lost-backlink-recovery-monitoring-churn-defense-engineering.html)可以借它的节奏。 复核节奏要落到协作流程里,内容运营与SEO协作的七个动作点 (https://zhangwenbao.com/content-operations-seo-collaboration-7-actions-topic-audit-22weeks.html)有可抄的表格。 复核的时候只做三件事。一是重跑那条日志命令,看有没有新面孔冒出来,请求量大的挑出来查清身份。二是把文件里的名字逐个对日志,标出这一年一次都没来的,连续两次复核都没来的可以删。三是查一遍那些还在名单上的对象有没有改名——这一步靠去对方官方文档看现行令牌,AI公司这两年改名相当频繁。 三件事加起来一两个小时,一年一次。比起那些在文件里躺了二十年的名字,这个投入实在不算什么。 ## 这件事该由谁负责,放在什么节点做 最后说落地。这类维护工作最常见的死法不是没人会做,是没人认领。 跨角色的活得有交接口径,后端与SEO协作的七个动作点 (https://zhangwenbao.com/backend-engineer-seo-collaboration-7-actions-canonical-sitemap-redirect.html)把责任切得比较清楚。 没人负责往往不是态度问题,团队怎么搭、考核怎么对上 (https://zhangwenbao.com/seo-team-structure-and-output-based-performance.html)才是根子上的事。 robots.txt横跨几个职责:名字和用途判断偏SEO,日志提取偏运维,是否拒绝AI训练偏内容策略甚至法务。三方都能改,三方都觉得是别人的事,结果就是只增不删。 比较可行的安排是把它挂在一个已经存在的固定节点上,而不是新设一项任务。三个现成的节点都合适:一是季度技术审查,顺手把日志命令跑一遍;二是每次改版上线前的检查清单里加一项,因为改版时本来就要动这个文件;三是当抓取量出现异常、有人去翻日志的时候——那时候数据已经摊在眼前,顺手核对名单几乎不增加成本。 关键是别把它做成一个独立的季度任务,那种任务的第一次执行往往也是最后一次。挂在别的事情上,它才活得久。 ## 名单多长算合理 按本文的数据给一个参考区间:十个上下。 把时间省在该省的地方,六大耗时任务的自动化方案 (https://zhangwenbao.com/ai-streamline-seo-tasks.html)能腾出复核的时间。 投入该怎么分配也是同一类取舍,内容、技术、外链三类分工与配比 (https://zhangwenbao.com/seo-three-pillar-content-technical-link-team-allocation-decision.html)有几种现成结构。 理由是请求量的集中度——前十个令牌占了总请求量的87.7%。也就是说十个名字能覆盖住绝大部分真实抓取行为,再往后加的每一个名字对应的都是极小的量。 当然这个数字跟站的类型有关。做多语言、多市场的站会多几个区域搜索引擎;投放广告的站要加广告爬虫;有大量图片的站要加社交平台的抓取器。就算全加上,二十个也差不多到顶了。 反过来说,如果你的名单超过三十个名字,而其中大部分不是这两年的AI爬虫,那几乎可以肯定它里面有大段抄来的内容。这时候最快的处理不是逐条核对,是清空重写——从日志重新长一遍,通常半小时就能完成,而且结果比原来那份可信得多。 ## 怎么决定一个爬虫该给什么待遇 拿到名字之后,判断给什么规则可以按四个问题走。 放开的收益能不能量化,3000条数据揭开的引用认知差 (https://zhangwenbao.com/ai-search-citation-optimization-guide.html)可以当参照。 放开之后还要确认对方读得懂,让AI爬虫抓得到、读得懂、引得出 (https://zhangwenbao.com/geo-technical-optimization-crawl-render-extract-guide.html)是技术端的落地清单。 第一问,它带不带流量。搜索引擎和AI搜索的抓取器会带来曝光,这类通常应该放开,甚至要检查有没有被误拦。第二问,它抓的东西会不会被拿去训练模型。这属于价值取向,想拒绝就针对训练用的令牌单独写规则。第三问,它是不是自己人。SEO工具的审计爬虫是你自己授权的,限它等于限自己。第四问,它耗不耗资源。真的抓得太凶而且不带任何回报的,才是限速或者禁抓的对象。 四问答完,规则自然就有了,而且每一条都能说出理由——这比一份一百行的名单有用得多。 ## 留一行注释,写清依据和日期 最后一步跟处理失效字段一样:每个分组上面加一行井号注释,写这个爬虫是谁、为什么这么对待它、什么时候确认过。 改版时最容易丢掉这些依据,改版不掉SEO的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)里有对应的检查项。 这一步的价值在两年后显现。到时候某个爬虫可能改名了、某家公司可能关掉了这个服务,而有注释的行能让接手的人判断该不该动,没注释的行只能继续留着。本文那些活了二十年的名字,缺的就是这一行。 ## 这份名单在整套防护里,到底是什么位置? 最后把层次理一遍,因为名单最大的风险不是写错,是被当成了防线。 相邻那一层是响应头,X-Robots、缓存和Vary几个头的实际机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)值得整体过一遍。 ## 它是分流器,不是闸门 robots.txt的作用是对愿意配合的程序做分流:告诉守规矩的爬虫哪些地方值得抓、哪些地方别浪费时间。它对不配合的程序没有任何约束力,这一点标准本身就承认——遵守是自愿的。 分层这件事在缓存侧最直观,八维决策树与规则迁移 (https://zhangwenbao.com/cloudflare-cache-real-world-optimization-decision-tree.html)是同一种思路。 没有头部标签的资源只能靠响应头,接口和feed这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)量过一次。 所以它能解决的是抓取效率和意愿表达问题,解决不了访问控制问题。前面那个伪造claude-web的例子就是最好的说明:唯一匹配那条规则的对象,恰好是最不可能遵守它的对象。 ## 名单只是分组名,真正起作用的是规则 最后纠正一个容易搞混的地方。这篇讲的都是名单,但名单本身不产生任何效果——它只是分组的标题。真正起作用的是分组里那几行规则。 在自己代码里认爬虫是另一条路,五种识别搜索引擎蜘蛛的写法 (https://zhangwenbao.com/5-ways-to-judge-search-engine-spiders-jumping-to-specified-pages.html)里含反向验证。 这个区分有实际意义。名单上多一个已经消失的名字,代价是文件长了一行;而分组里的规则写错,代价可能是一批页面被拦住不被抓取。所以清理的优先级应该是:先检查规则,再清理名字。 顺着这个思路,前面提到的分组不继承那件事就更值得警惕了:给某个爬虫单开一组,它就完全脱离通配组的规则。名单越长,单开的组越多,脱离通配组的对象也越多。一份点了三十个名字的文件,等于三十个各自独立的规则集,其中大部分组内只写了一两行——这些对象实际上得到的是比通配组宽松得多的待遇。 所以长名单不只是冗余,它还会悄悄放宽限制。这也是本文建议把名单控制在十个上下的另一个理由:分组少,规则的实际效果才好预测。 ## 四层各管什么 层次 | 管什么 | 对不配合的对象有效吗 | robots.txt的名单与规则 | 意愿表达、抓取分流 | 无效 | 页面与响应头的收录指示 | 已抓到的内容要不要进索引 | 对主流引擎有效 | 服务器的限速与来源校验 | 请求频率、身份真伪 | 有效 | 边缘层的规则与验证挑战 | 拦在源站之外 | 有效,且不耗源站资源 | 每一层各管一段,某个安全策略头的配置与回滚两条路 (https://zhangwenbao.com/https-hsts.html)是典型的分层例子。 最外那层能做的事不少,在CDN边缘改SEO的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)给了几种现成形态。 这四层的顺序不能颠倒着用。想拦住伪造身份的抓取,写多少行名单都没用;反过来,想让Googlebot别浪费预算去抓筛选页,用防火墙硬拦也是错的手段。 ## 身份验证那一层,具体怎么落 四层里最容易被跳过的是身份验证,因为它需要动服务器配置。这里给一个最小可用的做法。 加固清单照抄也会出事,一行响应头把嵌进来的地图和支付按钮变成摆设 (https://zhangwenbao.com/permissions-policy-iframe-third-party-widget-silent-denial.html)是真实案例。 要在代理层做这些判断,反向代理的完整配置场景 (https://zhangwenbao.com/nginx-proxy.html)是前置知识。 思路是对自称是主流爬虫的请求做一次来源核实。做法可以照着已验证爬虫的判定方式 (https://developers.cloudflare.com/bots/concepts/bot/verified-bots/)来,核心是反向解析加正向确认:拿请求的来源地址做反向域名解析,看得到的域名是不是属于对方声明的域,再把这个域名正向解析回地址,确认和来源地址一致。两步都通过才认。 这套逻辑在nginx里通常配合map和自定义变量实现,或者交给边缘层的现成规则——多数边缘服务已经内置了已验证爬虫的判断,打开开关就行,比自己写解析靠得住。 做不到这一步的话,退一档也有用:把各家公开的地址段抄下来做成白名单,自称是它但来源不在段内的直接拒。缺点是地址段会变,需要定期更新;优点是实现简单,一条规则就能挡掉本文那种冒名扫描。 还有个更简单的补充动作,成本几乎为零:把点开头的文件、常见密钥文件名、部署配置目录在服务器层统一拒掉。这跟爬虫名单无关,但既然日志里已经能看到有人在挨个试探这些路径,顺手补上比写十行名单实在得多。 顺便说一个心态上的调整。做完这套动作,多数人会发现自己原来的名单里大部分内容都没用,然后产生一种白忙一场的感觉。其实不必——那份名单在被抄下来的那一刻是有依据的,只是依据留在了别人的日志里,而且早就过期了。这不是谁的疏忽,是这类配置天生缺一条反馈通道。补上这条通道,就是这篇讲的全部内容。 ## 如果只做一件事,做哪件 这篇给的动作不少,如果时间只够做一件,那就做提取日志这一件。 把精力放在真有产出的事上,这一行的慢性透支比多数人以为的严重 (https://zhangwenbao.com/seo-health-zhang-xuefeng-insight.html)附了一套自查办法。 分层提问这个习惯用处很广,收录、排名、流量是三件事,先分清卡在哪 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)是最常用的一版。 理由是它同时解决两个方向的偏差:它告诉你哪些名字该留下,也告诉你缺了哪些名字。而其它所有动作——查文档、分类型、写注释、定复核周期——都建立在你先知道谁真的来过这个前提上。没有这份清单,后面每一步都只能凭猜。 成本也确实低:一条管道命令,输出一份按请求量排序的清单,五分钟。剩下的时间花在查前十个是谁上面,一个小时能查完。这一个多小时的产出,比照抄任何一份清单都可靠——因为它是关于你这个站的。 ## 一句话的判断顺序 把整篇压成一条链:先问这个名字是谁、能不能在对方的官方说明里查到;再问它在自己的日志里出现过没有;再问它带来的是曝光还是消耗;最后问要拦的话,这一层拦不拦得住。 收件人各认一套的例子还有,一键退订必须写两层,少一层整个域名就被限流 (https://zhangwenbao.com/one-click-unsubscribe-header-body-two-layers.html)也是同一个道理。 出问题时也是靠这种链式排除,四类原因的诊断决策树 (https://zhangwenbao.com/seo-traffic-drop-diagnosis-decision-tree-manual-algorithm-tech-seasonal.html)能快速缩小范围。 四问全过才写进文件,写完加一行注释注明日期。这套动作的成本是每个名字两三分钟,收益是名单从此不再是一份没人敢动的存量档案。 说到底,robots.txt里的名字不是一份愿望清单,它应该是一份来访记录的回执。谁来过、来干什么、你怎么答复——三样都对得上,这个文件才算写对了。 ## 常见问题解答 怎么快速判断自己robots.txt里的爬虫名单过没过期? 看两个信号,一分钟就能出结论。第一个信号是名单长度:超过三十个名字而且大部分不是这两年的AI爬虫,基本可以断定里面有整段抄来的内容。第二个信号是内容特征——名字里带完整版本号、出现Windows 95这类操作系统名、含Email字样、或者用了拟人化的调皮名字,命中任意一条就该整体怀疑。要更硬的判据就算命中率:把名字逐个在日志里搜一遍,看有请求的占几成,低于三成说明这份名单该重写。本文157个站里,点名超过30个的6个站命中率只有26.0%,最长那份109个名字只有2个来过。 名单上的名字在日志里一次没出现,可以直接删吗? 不能只凭这一条就删。某个爬虫没来过你的站,可能是它不抓这类站,而不是它已经消失了——广告爬虫在没投放的站上不会出现,社交平台的抓取器在没有图片被收藏的站上不会出现,但它们都活得好好的。正确顺序是先用命中率判断整份名单值不值得信,再对没命中的名字逐个查存在性:存在性查官方文档,活跃度查日志,两件事不能混。确认已经消失的删掉,确认还在但不来你这的留着也无妨,成本就是几个字节。 爬虫改了名字,旧规则该怎么处理? 不是删掉了事,而是查清对方现在用什么名字,把规则迁过去。以Anthropic为例,本文样本里有7个站还在写claude-web、7个站写anthropic-ai,而这家公司现行公开的是另外三个标识,分别用于训练抓取、用户触发的取页和检索。迁移的时候正好可以按用途分开给待遇——允许检索用的来抓,同时拒绝训练用的。旧名字那两组直接删除,它们不会匹配到任何真实对象。这一步做完,规则才第一次真正对上人。 日志里出现了名单上那个已经退役的名字,说明它还活着吗? 大概率相反,说明有人在冒用它。本文查到冒用claude-web的15次请求全部返回404,请求的是环境变量文件、部署脚本和云平台密钥这类路径;冒用anthropic-ai的42次是同一个路子,而且两组请求共用同一批来源地址。判断伪造不用查地址,看标识串格式就够——真实爬虫会用官方文档里公布的那种格式,冒用者往往只写一个裸名字,或者指向公司官网首页而不是文档里的联系地址。这类请求robots.txt管不了,得在服务器层做来源核实。 AI训练爬虫该不该全部拦掉? 先把训练和检索分开,这是这个决定的前提。同一家公司通常有两套标识:一套抓内容用于训练模型,一套在用户提问时实时取页用于生成回答。拦掉前者只影响你的内容会不会进模型,拦掉后者会直接影响你能不能被AI引用——后果完全不同。所以常见的选择是拒绝训练、放开检索。要注意各家的令牌名字不一样也在变,做这个决定之前得去对方文档确认现行的名字都有哪些,别照着两年前的文章写。 平台模板自带的那些名字,比如广告爬虫,要不要删? 不投广告的站可以删,投的话留着并检查规则。这一行在本文样本里被74个站写着,占47.1%,几乎全部来自电商平台的默认模板。而它在本文这台没有投放的服务器上59天只来了4次。要说明的是,本文没法知道那74个站里有多少真在投放,所以不能一概说这一行是空转的。判断标准很简单:自己看广告后台有没有在投,投了这一行就有用,没投就是模板留下的痕迹。 名单控制在多少个名字比较合理? 十个上下,做多市场或投广告的站可以到二十。这个区间的依据是请求量集中度:本文62个来过的令牌里,前5个占了总请求量的73.9%,前10个占87.7%,剩下52个加起来不到13%。也就是说十个名字能覆盖绝大部分真实抓取行为,再往后加的每一个对应的都是极小的量。另外分组越多,脱离通配组的对象也越多——单开一组就意味着这个爬虫完全不受通配组规则约束,长名单会悄悄放宽限制。 既然拦不住伪造身份的爬虫,这个文件还有什么用? 它管的是另一件事。robots.txt对愿意配合的程序做抓取分流,告诉它们哪些地方值得抓、哪些地方别浪费预算,这个作用是实在的——主流搜索引擎和AI公司的抓取器都遵守它。它同时是一份公开的意愿声明,在内容授权这类话题上有表态价值。它不能做的是访问控制,因为遵守完全靠自愿。所以正确的用法是分层:意愿表达和抓取分流用这个文件,身份验证和限速在服务器或边缘层做,两件事别指望一个文件同时办。 ## 权威参考资料 ## 表头去哪了?110张商品页表格,程序读得出的只有38% - URL:https://zhangwenbao.com/size-chart-column-header-unit-audit.html - 分类:技术SEO - 发布:2026-08-08 | 更新:2026-08-08 - 摘要:一张尺码表在屏幕上行列分明,交给程序却常常读不出来。55个英文独立站商品页上的110张表格逐张拆解:四成没有表头单元格,九成没有表名,同一个概念最多有7种列名写法,单位还可能只写在表格外的切换按钮上。 - 关键词:技术SEO,电商SEO,网页语义化 > **TLDR**:摘要:把55个英文独立站商品页上采到的110张真表格逐张拆开,写一段程序试着把每一行还原成“列名对应值”的记录,能还原的只有38.0%。四成的表一个表头单元格都没有,九成以上的表连个名字都没有,而“胸围”这一个概念在356个表头格子里出现了3种写法,“尺码”这一栏更是有7种。 > 摘要:把55个英文独立站商品页上采到的110张真表格逐张拆开,写一段程序试着把每一行还原成“列名对应值”的记录,能还原的只有38.0%。四成的表一个表头单元格都没有,九成以上的表连个名字都没有,而“胸围”这一个概念在356个表头格子里出现了3种写法,“尺码”这一栏更是有7种。 上一篇数的是载体:那张尺码表在源码里到底是表格、是网格、是图片,还是压根不在。尺码表实测55个站 (https://zhangwenbao.com/product-page-size-chart-carrier-audit.html)那一篇的结论是,有入口的页面里近一半在DOM里什么都没有。 那剩下那些确实写了table的呢?这一篇接着往里看一层。因为“是一张表格”只是及格线,一张表格真正值钱的地方不在格子里,而在“这一格属于哪一行、哪一列”这层关系上。而这层关系,恰恰是最容易在实现里丢掉的东西——它在屏幕上是免费的,你不写也看得出来。 ## 怎么判断一张表“说清楚了自己”? 样本是同一批:55个站、258个可解析的商品页、110张真表格,来自其中20个站。对每张表,我把最多20行12列的单元格原样取下来,同时记住每个格子是th还是td、有没有scope、有没有caption和thead、有没有跨行跨列。 判据来自规范本身。MDN的th元素说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/th)写得很直白:th不是“加粗居中的td”,它是一个声明——声明这一格是别的格子的标题。而HTML标准里scope属性那一节 (https://html.spec.whatwg.org/multipage/tables.html#attr-th-scope)更进一步,规定了这个标题管的是一整列、一整行,还是一个区块。不写th,那张表在机器眼里就是一堆没有坐标的字符串。 ## 先看这110张表是从哪来的 20个站,110张表,分布极不均匀。baseus一家贡献了11张规格表,monos和reebok各10张,brooklinen 9张,mackweldon 9张,drinkolipop 8张,taylorstitch和everlane各6张。前七家加起来就是63张,占了六成;剩下13个站分掉另外47张,好几个站只有一两张。 这个分布本身说明一件事:写不写表格,是站级决策,不是页级决策。一个站的商品页模板里如果有表格组件,那它每一页都有;没有,那就一页都没有。所以下面所有的比例,与其读成“百分之多少的表怎么样”,不如读成“有表格的这二十家里,多数人在同一个地方犯同一个错”。这跟CSS覆盖率那次实测 (https://zhangwenbao.com/css-coverage-unused-rules-audit.html)里看到的形态是一样的——问题几乎全部沉在模板层,不在内容层。 ## 还原实验的规则 还原的目标很低:把第二行开始的每一行,变成一条“列名:值”的记录。判定成功要同时满足四条——首行的格子全是th;表里没有跨行跨列;各行的格子数一致;列名不为空、也不全是纯数字。任何一条不满足,就归到对应的失败类型里。 另外把格子总数不超过2个的表单独摘出来,它们是模板留下的空壳,凑在分母里会把结论做假。110张里这样的有18张,占16.4%,下面的还原成功率都是在剩下92张上算的。 ## 四成的表一个th都没有,机器看到的是什么? 先看最基础的一层。110张表里,一个th都没有的有45张,占40.9%。剩下65张里,首行含th的正好也是65张——换句话说,只要这个站想起来写表头,它就会写在第一行,没有例外。 这张表写了什么 | 张数 | 占比 | 有thead | 60 | 54.5% | 首行有th(有列名) | 65 | 59.1% | 首列有th(有行名) | 13 | 11.8% | 写了scope | 19 | 17.3% | 有caption | 8 | 7.3% | 有跨行跨列 | 18 | 16.4% | 这里有个细节值得停一下:thead有60张、首行th有65张,两个数不一样。也就是说,有几张表写了thead这个分组标签,里面装的却是普通的td。这种写法在视觉上毫无差别——CSS选择器照样能选中它们、照样能加粗,但语义上等于什么都没声明。faherty那几张尺码表就是这样:首行明明白白写着ALPHA、NUMERIC、WAIST (IN)、HIPS (IN),四个格子全是td。 ## 写对了的那张长什么样 光看错的容易丧气,看一张写对的。everlane的裤装尺码表是13行3列,首行三个格子全是th:US Alpha Size、US Numeric Size、Waist;第二行开始是XS、27、27"。三件事它都做到了——列名齐全、列名读得懂、单位跟着值一起写。程序取下来就是一条条干净的记录,读屏软件念到中间那格会先报出列名。 反过来最值得警惕的是allbirds那张。它是整批样本里少数几张同时写了thead和th的表,结构标准得像教科书,内容却是加州隐私法要求披露的信息类别——法务模板带进来的。一个站里写得最规范的那张表,往往不是它自己做的那张。 ## 行名和列名都写全的表,为什么只有一成? 一张尺码表在本质上是二维的:横着是测量部位,竖着是尺码档位,或者反过来。要让机器知道“第4行第3列这个数字是M码的胸围”,光有列名不够,还得有行名。 可样本里首列写了th的只有13张,占11.8%。也就是说,将近九成的表只声明了一个方向。机器读到中间那个数字,最多能知道它属于“胸围”这一列,至于它是哪个码,得靠猜——猜的方式通常是“第一列的那个格子应该是行标识”,这在多数情况下对,但没有任何东西保证它对。 更麻烦的是scope。写了的只有19张,占17.3%;写全到每个th都带的有18张。ARIA的表格角色文档 (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/table_role)里把列头和行头分成两个不同的角色,就是因为这两件事在语义上不能合并。没有scope的双向表,读屏软件念到某一格时报不出完整坐标,程序解析时也只能退回到位置推断。 ## 这张表叫什么名字?九成的表答不上来 接下来这个数字是全篇里最悬殊的一个:110张表里,既没有caption、也没有aria-label的,有102张,占92.7%。 那这些表叫什么?我写了一段回溯逻辑,沿着DOM往上找最近的标题、图例、按钮或者段落文字,当作它的名字。96张表的名字是这么猜出来的,只有8张来自caption,还有6张连猜都猜不出来。 MDN的caption元素说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/caption)里讲的正是这件事:caption是表格的标题,它跟表格是绑死的,不管这张表被搬到页面哪个位置、被复制到哪个上下文里,标题都跟着走。而靠邻近元素猜出来的名字,一旦DOM顺序变了就全错。 猜出来的名字有多不靠谱,看几个真实的:一张6行7列的尺码对照表,最近的那段文字是“CM Inch”,那是单位切换按钮;一张7行2列的表,猜出来的名字是“Fit: Unisex style—true to size”,那是一句文案;还有一张,猜到的是“Transfer History”,而表里唯一的内容是一个句点。 ## 把每一行还原成一条记录,成功率有多少? 92张有实质内容的表跑下来: 结果 | 张数 | 占比 | 坏在哪一步 | 还原成功 | 35 | 38.0% | —— | 无表头 | 33 | 35.9% | 列名根本不存在 | 跨格错位 | 10 | 10.9% | 合并单元格后列位置对不上 | 列名里有空格子 | 7 | 7.6% | 左上角那格是空的 | 表头行只有一部分是th | 5 | 5.4% | 半声明,比不声明更难处理 | 列名本身是数字 | 2 | 2.2% | 列名是尺码值,不是属性名 | 三分之一强能还原。这个数字比我预估的低,也比它看起来更糟——因为“还原成功”只是说程序能把值挂到列名上,没说那个列名读得懂。 ## 左上角那个空格子,坑了7张表 这是最典型的一类。一张标准尺码表,第一行是S、M、L、XL,第一列是胸围、腰围、袖长,那么左上角那一格写什么?多数人的答案是留空。视觉上完全正确,可对程序来说,首行第一个格子是空的,意味着这一列没有名字,整行的对应关系立刻断掉。 规范给的正确写法是把左上角那格也写成th,内容可以是“测量部位”或者干脆写“Size”,再给两个方向的th分别加上scope="col"和scope="row"。这一步的工程成本几乎为零,收益是整张表从“一堆数字”变成“可查询的二维表”。 ## 值本身也会把程序绊倒 还原成功不等于取到的值可用。taylorstitch那张裤装尺码表里,腰围写的是28、30,裤裆长写的是9½,大腿围16½。那个“½”是一个独立的字符,不是9.5。程序按数字解析会得到9,差了半英寸;按字符串存下来,后面做区间比较又用不了。样本里用这种分数字符的表不止一张,服装类尤其常见,因为纸样师傅本来就是这么标的。 还有一类是区间值。faherty的尺码表里,腰围那一列写的是“28-29”“30-31”,胸围那一列写的是“34-36”。这在人看来毫无歧义,程序要用就得先拆成上下界,而拆分符号在同一批样本里就有短横、波浪号、to三种。 这两件事都不算错,页面上写得完全正确。它们只是提醒一件事:表格结构写对了,只是让机器能把值取出来,取出来之后能不能直接用,还得看值本身是怎么写的。想把一批页面的正文原样剥出来对比,可以先用把网页内容剥成干净文本 (https://zhangwenbao.com/html-to-text-clean-content-extraction-guide.html)那套流程过一遍,再动手做数值解析。 ## 跨格错位是最难自动修的一类 10张表因为合并单元格而无法还原。taylorstitch那张最典型:整张表12行6列,第一行只有一个格子,写着“Garment Size Chart”——设计上这是个横跨整行的小标题,实现上它是一个colspan为6的单元格。程序按行取格子,第一行取到1个,第二行取到6个,列数对不上,只能判失败。 这类问题不能靠加th解决,得改结构:那行小标题应该是caption,不该混在表体里。 ## 表里那些数字是厘米还是英寸,写在哪儿? 一张尺码表里的数字,脱离单位就没有意义。42可能是厘米,可能是欧码,也可能是胸围英寸。 110张表里,过半格子是纯数字的有18张。这18张里,表内一个单位词都找不到的有3张,剩下15张写了——其中10张写在表头行里,比如“WAIST (IN)”“Chest (in)”,另外几张写在单元格里,比如everlane那张,值直接写成27"。 那3张没写的,单位在哪?全都在页面别处。snowpeak那张6行7列的表最能说明问题:表头是Size、1、S、M、L、XL、XXL,第一列是Shoulder Width、Bust这些部位名,中间全是41、43、45、47.5这样的数字。单位藏在表格上方的一个“CM / Inch”切换按钮里,用户点一下,表里的数字整体换一套。对着屏幕看毫无问题;把这张表原样抓下来,41到底是41厘米还是41英寸,没有任何线索。 ## 公制英制并存的只有一成 单位口径 | 张数 | 占比 | 只出现英制(inch/lb/oz) | 44 | 40.0% | 只出现公制(cm/mm/kg/ml) | 3 | 2.7% | 两套都出现 | 10 | 9.1% | 英制出现在54张表里,公制只有13张,差了四倍。这批站主要面向北美市场,偏英制不奇怪;奇怪的是同一张表里两套单位都给的只有10张。剩下那些,欧洲和亚洲的买家要么自己算,要么去点那个切换按钮——而切换按钮改的是渲染结果,不是数据本身。这道算术该由谁来做,尺码那一栏的数字不归译者管 (https://zhangwenbao.com/minor-language-size-unit-conversion-keyword.html)那篇里已经把整条流水线上的责任缺口拆过一遍。 顺便说一句结构化数据这边的对应物:schema.org的QuantitativeValue (https://schema.org/QuantitativeValue)把“数值”和“单位代码”定义成两个必须成对出现的字段,正是因为一个脱离单位的数字不构成信息。HTML表格里没有这个约束,所以只能靠人自觉。 ## 同一件事,356个表头格子里出现了109种写法? 把110张表的首行文字全部倒出来,一共356个格子。原样不重复的写法有119种,做过大小写与括号归一之后还剩109种。 然后按概念归拢,结果挺能说明机器这一侧的难处: - 胸围:3种写法——bust、chest、chest (in); - 腰围:3种——waist、waist (in)、garment: waist; - 臀围:3种——hip、hips (in)、garment: low hip; - 尺码那一栏:7种——size、alpha、alpha size、numeric、numeric size us/ca、us alpha size、us numeric size。 七种写法说的是同一件事:这一行对应哪个码。有的站把字母码和数字码拆成两列,有的合成一列;有的在列名里带上国家,有的不带。任何一个想跨站比较尺码的程序,第一步都得先建一张同义词表,而这张表是没法一劳永逸的——下个季度换个前端组件,写法可能就变了。 相比之下,定义列表那套“名字—值”结构反而更稳,因为它把配对关系写进了标签本身。可惜样本里258页只有43页出现过dl,而且几乎全部来自导航菜单和页脚,没有一个是用来写商品属性的。最适合它的地方没人用,最不适合的地方到处都是。 ## 表头里出现最多的词,其实跟尺码没关系? 把356个表头格子按出现次数排一遍,前几名有点出人意料: 表头文字 | 出现次数 | 来自什么表 | Shipped From | 10 | 配送时效表 | Processing Time | 10 | 配送时效表 | Shipping Time | 10 | 配送时效表 | Unit | 10 | 营养成分表 | Height | 10 | 家具尺寸表 | Duvet Cover (W x L) | 8 | 床品尺寸表 | Waist | 7 | 服装尺码表 | S / M / L / XL | 各7 | 服装尺码表 | 排在最前面的三个全是配送信息。这跟上一层的发现能对上:真正写成表格的那些内容里,配送时效和营养成分占了很大比重,而这两类恰好都是有外部约束的——配送时效要写清楚是合规压力,营养成分表在多个市场是法定格式。有人在外面盯着的那些表,写得反而更像表。 另一个细节:Height、Width、Depth这三个词各自只有一种写法,而胸围有3种、尺码那一栏有7种。越是标准化的物理量,写法越统一;越是行业内部的概念,写法越发散。这条规律对做多站点数据整合的人挺有用——先啃发散的那几栏,物理量那几栏基本可以直接对齐。 ## 谁写的表更规范?答案跟直觉相反 这是本篇的对照组。同一批页面上的表格其实来自两拨人:一拨是品牌自己为这件商品做的尺码表、规格表;另一拨是模板、插件、法务文本带进来的——配送时效表、营养成分表、隐私政策里的信息类别表。 按“是不是落在尺码规格语境里”把92张表分成两组,还原成功率是: 这张表是谁做的 | 张数 | 能还原 | 成功率 | 品牌自己的尺码表、规格表 | 59 | 28 | 47.5% | 模板与法务文本带进来的表 | 33 | 7 | 21.2% | 差了一倍还多。这个结果跟我下场之前的预期正好相反——我原以为品牌自己手搓的尺码表最随意,模板生成的最规矩。实际上反过来:有人真正在乎那张表的内容时,他更可能把表头写出来。模板带进来的那些表没有主人,写成什么样都没人检查,其中还混着那18张只有一两个格子的空壳。 这个对照也顺手回答了另一个问题:这不是“做不到”,是“没人管”。同一个站、同一套前端、同一批工程师,能把尺码表写对,就说明技术上没有障碍。商品页上那个推荐位归谁管 (https://zhangwenbao.com/product-page-recommendation-attribution-mismatch.html)那篇里讲的责任真空,在表格这件事上是同一个形态。 ## 这一层写不写,到底谁在乎? ## 读屏用户 这一侧最直接,也最不容争辩。一张写全了th与scope的表,读屏软件念到某一格会先报出“胸围,M码”,再念数值;一张没写的,念出来就是一串孤零零的数字,用户得靠记忆把它跟表头对上。网站无障碍那18个改动 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)里,表格语义是投入最小的一项之一,也是最容易在改版中被丢掉的一项。语义化HTML那8类标签 (https://zhangwenbao.com/semantic-html-tags-seo.html)讲的是同一件事的一般形式。 ## AI助手与购物代理 用户问“我平时穿M码,这条裤子腰围多少”,模型要么能从这张表里取到那一行,要么去别处找。智能体读的是无障碍树 (https://zhangwenbao.com/ai-agent-accessibility-tree-not-pixels.html)这一点在表格上兑现得特别直接:无障碍树里,一张写了表头的表是有行列坐标的网格,一张没写的表就是一串平级文本。给AI代理做适配 (https://zhangwenbao.com/ai-agent-website-optimization-guide.html)时,尺码这一格常常被漏掉,因为它在人眼里已经“显示出来了”。 ## 做数据整合的那个人 如果你要把几十个站的尺码数据拉到一张表里做竞品对比,前面所有的坑会一次性砸下来:四成没有表头,一成的表左上角是空的,109种列名写法,还有半英寸那个字符。尺码标准跟用户自我认知本来就有落差 (https://zhangwenbao.com/apparel-size-self-identification-label-gap.html),再叠上一层结构上的噪声,得出的结论很容易是数据处理方式的产物,而不是市场的产物。给自己的尺子配一组对照 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)这件事,在这类活儿里省不掉。 ## 怎么改,改到什么程度算够? 按投入产出排个序,四步: - 把首行的td换成th。这是唯一一个改一行代码、语义直接从零变一的动作。前端组件里改一处,全站尺码表一起受益。 - 把左上角那个空格子填上。写成th,内容写“Size”或者“测量部位”,顺手给两个方向加scope。这一步之后,那张表才真的是二维的。 - 把单位写进列名。不要只留一个切换按钮。最省事的写法是“胸围(cm)”,需要两套就并排给两列。 - 把跨行的小标题挪进caption。顺带解决了表没有名字这个问题,一举两得。 什么时候可以停?有一个很好用的自检:把整张表复制粘贴到表格软件里,如果每一列都自动落进独立的列、首行就是列名、每个数字都能看出单位,那就够了。粘出来是一坨挤在一列里的文字,说明结构没写对。 还有一件事值得说清楚:把这四步做完,不会直接换来排名。Google早就取消了表格类富媒体结果,schema.org的Table类型 (https://schema.org/Table)也不是Google支持的富媒体类型之一。真正的收益在别处——读屏用户能听懂,AI助手取得到,客服能复制,还有一层往往被忽略:这张表是商品页上信息密度最高的一段,主体内容占比 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)这件事在商品页上本来就吃紧,把它做成可读文本,等于凭空补回一块独有内容。 如果连表格本身都还不存在,那顺序反过来:先解决载体,再谈表头。这一层的实测在同一批样本的载体清点 (https://zhangwenbao.com/product-page-size-chart-carrier-audit.html)里。 ## 二十行代码,把这套检查跑在自己站上 不用搭实验台。打开一个有尺码表的商品页,先把尺码指南点开,让表真的进到DOM里,然后在浏览器控制台里跑这一段: [...document.querySelectorAll('table')].forEach((t, i) => { const trs = [...t.querySelectorAll('tr')]; const lens = trs.map(tr => [...tr.children].length); const head = trs[0] ? [...trs[0].children] : []; console.log(i, '行', trs.length, '列', Math.max(...lens), '首行全th', head.length && head.every(c => c.tagName === 'TH'), '首列th', trs.filter(tr => tr.children[0] && tr.children[0].tagName === 'TH').length, 'scope', t.querySelectorAll('th[scope]').length, 'caption', !!t.querySelector('caption'), '跨格', t.querySelectorAll('[colspan],[rowspan]').length, '各行列数一致', new Set(lens).size === 1, '左上角', head[0] ? JSON.stringify(head[0].textContent.trim()) : '无' ); }); 输出里挨个对:首行全th是false,去改第一步;首列th是0而这张表是二维的,去改第二步;左上角打印出来是空字符串,那就是前面说的那7张里的一张;跨格不为0,去看那一格是不是本该当标题用的。 整站铺开的话,把这段接进爬虫,对每个商品页记一行,跑完按站汇总。保哥当时就是这么干的,唯一要多留一步的是:一定要在点开尺码指南之后再跑,不然量到的是另一件事。有些站的表要等点击之后才注入,先跑一遍不点、再跑一遍点开,两个数一对比,顺手就知道自己站属于哪一类,这跟对比爬虫看到的和用户看到的 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)是同一个动作。 ## 常见问题解答 ## 把td改成th,页面样式会不会变? 会变一点。浏览器默认给th加粗并居中,如果你的CSS是按标签选的,改完可能跟设计稿对不上。解决办法是在样式里显式声明font-weight和text-align,一行的事。别为了避开这一行样式改动,把语义丢掉。 ## scope属性到底要不要写?不写会怎样? 单向表(只有列名)不写通常也能被正确推断,浏览器和辅助技术会按位置猜。双向表必须写,因为“这一格既属于某列也属于某行”这件事没法从位置上稳定推断出来。判据很简单:首列也用了th,就一定要写scope。 ## 尺码表里的单位,写在列名里还是写在每个格子里? 写在列名里。写在每个格子里会让数值变成字符串,程序取出来还得再剥一次单位,也让排序和比较失效。列名写成“Waist (in)”这种形式,格子里只放纯数字,是最省事的做法。 ## 合并单元格是不是完全不能用? 能用,但要用对地方。跨列的表头(比如“上装”横跨三列)是规范支持的,配上scope="colgroup"就没问题。真正该避免的是拿合并单元格做视觉分隔——那种横跨整行的小标题应该用caption或者把表拆成两张。 ## 我的规格是键值对形式,不是二维表,该用什么标签? 用定义列表。dl加dt加dd天生就是一对一的名值结构,比拿两列表格去装更贴切,也不需要写表头。样本里baseus的规格表就是键值对形式硬塞进两列表格的,一个th都没有,还原自然失败。 ## 这一套检查有没有现成工具? 常见的页面体检工具会告诉你“表格缺少表头”,但多半只查th存不存在,不查左上角空格、不查跨格错位、更不查单位。最可靠的还是自己在控制台里跑一段:取出所有表格,逐张打印首行是不是全th、各行格子数是否一致。二十行代码,一次写好可以一直用。 ## 权威参考资料 ## HTTP响应头有248个死字段,多数不是你写的 - URL:https://zhangwenbao.com/http-response-header-dead-fields-audit.html - 分类:技术SEO - 发布:2026-08-08 | 更新:2026-08-08 - 摘要:你的响应头里可能有三四个字段,读它的那个客户端已经消失多年了。142个独立站实测,七成的站至少发着一个,而这些字段绝大多数不是站主自己写的。 - 关键词:技术SEO,HTTP响应头,独立站运营,安全加固 > **TLDR**:摘要:142个海外品牌独立站的响应头逐字段拆开,100个站(70.4%)至少发着一个没有接收端的字段,合计248个。最普遍的是X-XSS-Protection,90个站在发,而浏览器2019年就把对应功能移除了。分布更说明问题:这类头里有三个,65个站同时发全部三个,50个站三个都没有,只有3个站发了其中两个——不是一条条加的,是一个包一起来的。而那65个站里62个带着同一个电商平台的特征头。 > 摘要:142个海外品牌独立站的响应头逐字段拆开,100个站(70.4%)至少发着一个没有接收端的字段,合计248个。最普遍的是X-XSS-Protection,90个站在发,而浏览器2019年就把对应功能移除了。分布更说明问题:这类头里有三个,65个站同时发全部三个,50个站三个都没有,只有3个站发了其中两个——不是一条条加的,是一个包一起来的。而那65个站里62个带着同一个电商平台的特征头。 HTTP响应头是个很奇怪的地方:它是全站每一次请求都会带上的东西,却几乎没有人定期看一眼。 原因不难理解。它不像页面内容那样有人反馈,不像状态码那样会报警,也不像加载速度那样有工具打分。它只是安静地跟着每个响应发出去,几十个字段,几百个字节,一天几十万次。 这次把142个海外品牌独立站的响应头全抓下来逐字段拆开,想看的是一件很具体的事:这些字段里,有多少还有人在读。 ## 响应头里那些没有接收端的字段,你还在发吗? 先把这个问题的性质说清楚,它跟常说的响应头配置错误不是一回事。 服务器这一层的配置项该逐条核,影响SEO的20项服务器配置清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)可以照着走。 这一层能做的事比想象中多,X-Robots、缓存和Vary几个头的实际机制 (https://zhangwenbao.com/http-response-headers-seo-x-robots-cache-vary-canonical-mechanism.html)值得先整体过一遍。 ## 配错和过期,是两种不同的问题 配错是指值写得不对,比如缓存时间设成了负数、跨域来源写了通配符结果被浏览器拒绝。这类问题有反馈——浏览器控制台会报错,或者行为明显不对。 配错了通常立刻能看出来,伪静态和跳转的现代写法 (https://zhangwenbao.com/typecho-rewrite-rules-301-jump-settings.html)里那些错误都会直接表现出来。 配错的后果有时相当直接,照着加固清单加的一行响应头把地图和支付按钮变成了摆设 (https://zhangwenbao.com/permissions-policy-iframe-third-party-widget-silent-denial.html)就是真实案例。 过期是另一种:字段名和值都完全正确,语法无懈可击,只是读它的那个客户端已经不存在了。这类没有任何反馈。浏览器收到一个自己不认识的响应头,会直接忽略它,不报错也不提示——这是规范要求的行为,不然任何一家服务器加一个自定义头,所有浏览器都会集体报错。 所以过期的字段可以在响应里待很多年,每一次请求都发一遍,谁都不会说什么。 ## 接收端消失有三种形态 把这批数据摊开之后,接收端消失的方式其实分得很清楚。 头部那些自动输出的东西也值得清,去掉静态文件版本号的四种做法 (https://zhangwenbao.com/remove-the-version-number-after-wordpress-loaded-js-and-css-links.html)是同一类整理。 服务退役不会有人通知你,某个缓存服务下线之后还能怎么查快照 (https://zhangwenbao.com/webpage-cache-snapshot-viewing-tools-guide.html)是同一类处境。 第一种是功能被移除。字段还在规范文档里有记载,但浏览器把对应的实现删掉了。这类最彻底——现在发它和发一个随手编的字段名,效果完全一样。 第二种是接收端产品退役。这个头本来是给某个特定软件看的,那个软件已经停止运营。字段本身没被谁废弃,只是它的读者不在了。 第三种是规范换代。旧字段被新字段取代,旧的进入弃用状态,新的成为标准写法。这一种最微妙,因为旧字段往往还能被部分实现识别,处在一个靠向后兼容维持的中间状态。 ## 这批数据对一个中小站主意味着什么 先回答一个很实际的问题:这些百分比跟一个只有几百个页面的独立站有什么关系。 这类问题集中在几个固定位置,电商站十二类高频坑的诊断修复 (https://zhangwenbao.com/ecommerce-seo-common-mistakes.html)可以照单排查。 这类失分往往在第一年就埋下了,建站第一年最容易失分的十二项配置 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)是同一批经验的汇总。 关系在于这批样本正好就是这类站。142个站全是海外品牌的独立站,多数用现成的电商平台建站,团队规模从几个人到几十人。也就是说,本文量出来的不是大厂的配置水平,是这个行业的普遍状态。 更具体一点:如果你用的是主流电商平台建的店,那么你的响应头里几乎肯定有本文说的那三个字段——65个三头全有的站里62个是同一个平台。你不需要去查也能猜到结果,因为那不是你配的。 而如果你是自建站或者用静态托管,情况就完全不同:本文那50个一个死头都没有的站基本都属于这一类。这时候响应头里有什么全看你自己配了什么,需要真的去查一遍。 ## 同样的结构在别的地方也有 先把这个问题的形状抽出来,因为它不只出现在响应头里。 页面头部同样堆着没人用的东西,那几行预解析和表情代码怎么去掉 (https://zhangwenbao.com/wordpress-cancels-loading-of-google-dns-prefetch-and-s-w-org.html)是最常见的一例。 结构化数据同样存在写了没人读的情况,这些标记对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)里有官方说法和实测。 响应头之外页面头部也在堆东西,关掉那几个默认加载的头部输出 (https://zhangwenbao.com/wordpress-window-wpemojisettings.html)是同一类瘦身。 凡是符合两个条件的配置,都会长成这样:一是你写下的内容由别人的实现来解释,二是对方不认识的时候会静默忽略而不是报错。满足这两条,配置就会只增不减地积累。 符合这个描述的地方不少。域名的解析记录里可以留着指向早已停用服务的条目;邮件的发信策略记录里可以留着几年前用过的第三方服务商;Cookie上的属性各家浏览器支持程度不同,写了不支持的属性不会有任何提示;页面里的结构化数据可以标注一堆没有任何搜索引擎会消费的字段。 这些场景共享同一套判断办法,也共享同一个陷阱:因为没有报错,所以没有人知道该去看它。本文用响应头做样本,是因为它最容易批量取到,量出来的比例也最有代表性。 ## 为什么这件事值得单独量一遍 可能会有人觉得这不算问题:多发几个字节而已,又不影响功能。 真正的加固在权限这一层,文件与目录权限的完整实战 (https://zhangwenbao.com/linux-server-sets-files-folders-read-write-permissions.html)比多发几个头有用。 交付标准写清楚能省很多争论,达标定义与违约责任怎么写 (https://zhangwenbao.com/seo-website-optimization-contract-model.html)有几个真实纠纷案例。 这类核查最好放进整体框架,从抓取到AI可见度的完整诊断框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)可以拿来当清单。 直接影响确实很小,这一点后面会专门算。真正的问题在别处:安全审计工具会把这些头当成加固措施打勾,检查清单会把它们列成必配项,而实际上它们什么都没做。这就形成了一份看起来很扎实、实际上有窟窿的防护记录。 更麻烦的是它掩盖了真正该配的东西。本文后面会看到一个对照:那些浏览器还在读的现代安全头,覆盖率只有个位数百分比;而这些已经没人读的老头,覆盖率超过六成。 ## 142个站的响应头,是怎么取的? 先说样本和口径,因为响应头这个东西取法不同结果差别很大。 取法不同结论会反过来,用HEAD查说没配缓存头、换成GET那五个头全在 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html)就是这么来的。 ## 请求方式与筛选条件 抓取对象是211个海外品牌独立站的首页,用普通浏览器的标识发GET请求,跟随重定向,记录完整的响应头。 同一批站上还看过移动端表现,响应式到核心指标的三类站改造对比 (https://zhangwenbao.com/mobile-seo-optimization-guide.html)可以对照。 同一批站上还量过响应速度,多层缓存怎么同时影响体验指标与抓取 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)是配套的一篇。 为什么用GET而不是只取头部:因为有些服务端对不同请求方法返回的头并不一致,只查头部会漏掉实际存在的字段。这一点在做这类测量时经常出错,代价是得出一个反向的结论。 筛选条件是最终响应为2xx且有正文,符合的142个站进入统计。停在重定向的、返回4xx或5xx的都排除掉了——它们的响应头往往由边缘防护生成,不代表站点本身的配置。 ## 211个域名里,为什么只有142个进了统计 把被排除的那69个交代清楚,因为分母决定了所有百分比。 被判成可疑之后还得能申诉,三大平台的申诉入口和文案 (https://zhangwenbao.com/tencent-baidu-and-360-three-major-platform-websites-intercept-false-reporting-appeals.html)可以备着。 被防护层挡住这件事很普遍,防火墙到底拦不拦得住爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)实测出的答案挺意外。 排除的原因分三类。第一类是最终响应不是2xx:有些站对来自服务器机房的请求直接返回验证挑战或者拒绝,回来的是403、429这类状态码,而这些响应的头往往由边缘防护生成,反映的是防护配置而不是站点配置。第二类是请求根本没完成:连接超时、域名解析失败。第三类是停在重定向上没有走到终点。 这69个站被排除不代表它们的响应头有问题,只代表这次没取到可用的样本。所以本文所有比例的准确表述是:在能取到正常响应的142个站里,某个字段占多少。 顺带说一句,这种测量被防护层挡住的情况在这类工作里非常普遍,比例通常在两三成。做类似测量时最好一开始就预留这个损耗,别指望样本能全部覆盖。 ## 为什么不直接用在线检测工具的结论 响应头这件事有大量现成的在线检测工具,输入域名就出一份评分报告。既然如此,为什么要自己抓。 外部工具的结论都该先校准,第三方数据准不准的六步校准法 (https://zhangwenbao.com/third-party-seo-tool-data-accuracy-estimation-methodology.html)能挡掉大部分噪声。 两个原因。第一是评分规则本身可能过期——本文后面会看到,不少工具的规则里还留着已经失效的头,发了加分,没发提示缺失。用一个过期的尺子量,结果自然是错的。 第二是它们通常只给结论不给原始数据。而本文要回答的问题需要原始数据:这个字段是谁加的、和哪些字段一起出现、取值是什么。这些信息在评分报告里没有。 所以顺序应该是先自己取一份完整的响应头存下来,再用工具做辅助判断。反过来做,你拿到的是别人的结论,而那个结论的判据你看不见。 ## 响应头里最大的一块,其实是Cookie 顺带说一个跟本文主题相关但方向不同的观察。142个站的响应头里,Set-Cookie合计568行,是所有字段里行数最多的,平均每个站四行,有的站一次发几十行。 要减字节先看大头,免插件压缩HTML与压缩叠加 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)给了顺序。 Cookie堆多了还会直接报错,老用户打不开的那个页面,工具全都返回200 (https://zhangwenbao.com/request-header-too-large-400-431-cookie-seo-blindspot.html)是典型盲区。 Cookie的字节代价在请求侧更明显,每个请求都把同一份Cookie重发一遍 (https://zhangwenbao.com/http2-hpack-cookie-request-header-bytes-seo.html)算过一笔账。 这跟死头是同一类问题的另一种形态:Cookie也只有加入的通道,没有退出的通道。一个第三方服务接进来会写几个Cookie,服务停用之后写Cookie的代码往往还留着,或者标签管理里的那个配置没人敢删。 差别在于代价的量级完全不同。死头一共占响应头字节的1.74%,而Cookie往往占一半以上——它不但每次响应都要发下去,浏览器还会在后续每个请求里把它们再带回来。所以如果目标是减字节,该看的是Cookie而不是那几个老头。 本文不展开这一块,只是提醒一句:查响应头的时候顺手数一下Cookie行数,收益可能比清理死头大得多。 ## 只看最后一跳,不看中间跳 还有个细节要说明:一次请求经过重定向,会产生好几组响应头,本文只取最后那一组。 跳转链本身也常出问题,不同工具报的死链从来不是同一批 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html)解释了差异来源。 中间跳的状态码本身也有讲究,301、302、404和410分别该在什么场合用 (https://zhangwenbao.com/http-status-codes-seo-atlas-redirect-410-decision.html)是一张速查表。 这个选择是有取舍的。中间跳的响应头有时也有意义——比如某个跳转是由边缘层生成的,它带的头能说明边缘层配了什么。但要判断站点本身发什么,最后一跳才是对的对象。 ## 抓取和存档是怎么做的 把方法说完整,便于自己复现。 看原始数据免不了跟各种表示法打交道,二进制到十六进制与权限位一次理清 (https://zhangwenbao.com/base-converter-radix-octal-chmod-bitwise-guide.html)是常备工具。 原始数据留住才能改口径,把日志收成结构化可检索的形式 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)是同一个思路。 抓取用的是普通命令行工具,每个域名发一次请求,跟随重定向,把完整的响应头连同状态行一起存成一个文本文件。一个域名一个文件,文件名用域名,这样后续可以随时回到原始数据重新统计。 这一步的关键是保留全部原始响应,不要在抓取阶段做任何筛选或者提取。本文中途改过好几次统计口径——只取最后一跳、剔除非2xx、区分平台加的和自己加的,每次改动都是拿同一批原始文件重跑。如果抓取的时候就只存了自己当时关心的几个字段,后面每次改口径都要重新抓一遍。 这个习惯在这类测量里回报很高:原始数据一次抓够,口径可以改一百遍。 ## 字段名一共233种,头部长度分布很宽 142个站的响应头里,出现过的字段名去重有233种。这个数字比预想的大得多,因为里面有大量各家平台的私有字段。 一台机器上跑多个站时头会更乱,子目录映射与等价配置 (https://zhangwenbao.com/using-htaccess-to-bind-a-virtual-host-to-multiple-independent-websites.html)讲了怎么隔开。 头部字段多了压缩层会吃力,同样是4096的表,两种协议差678字节 (https://zhangwenbao.com/qpack-dynamic-table-zero-http3-header-compression-seo.html)量过这件事。 出现在最多站上的几个是:Set-Cookie(合计568行,一个站可以发几十行)、Vary(179行)、Content-Type、Content-Encoding、Strict-Transport-Security(126站)、Server(125站)、X-Content-Type-Options(110站)。 值得一提的是Server头:125个站发了它,其中87个的值就是一个云服务商的名字。这本身也是一条信息——超过六成的站,响应头的最后一站是同一家边缘网络。这个事实会在后面解释一个非常整齐的分布。 ## 浏览器七年前移除的那个安全头,为什么还有六成站在发? 先看最普遍的那一个。 真正有效的加固在别的层,从版本隐藏、目录权限到访问控制 (https://zhangwenbao.com/apache-server-security-hardening-version-hide-directory-access-control-waf.html)是一份可执行的表。 ## 90个站在发X-XSS-Protection 142个站里有90个(63.4%)在响应头里发X-XSS-Protection,取值分布是这样: 真正挡住执行的是权限设置,五种环境禁掉执行权限的写法 (https://zhangwenbao.com/method-of-disable-directory-permissions-for-php-directory-execution.html)是直接有效的一层。 真正的攻击流量要另一套手段,从识别到应急拦截 (https://zhangwenbao.com/wordpress-ddos-protection-guide.html)讲的是量级更大的情况。 真正的加固要分层来,三层拦截手段的选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)比多发几个头实在。 取值 | 站数 | 本意 | 1; mode=block | 85 | 检测到疑似脚本注入就阻止整页渲染 | 1;mode=block | 2 | 同上,只是少了个空格 | 1 | 1 | 检测到就尝试过滤 | 0 | 2 | 明确关闭这个功能 | ## 它对应的浏览器功能,2019年就开始被移除 这个头是当年为了配合浏览器内置的脚本注入检测机制而设计的。那个机制的想法是:浏览器观察请求参数里有没有出现在页面里被当成脚本执行的内容,发现疑似情况就拦下来。 各家服务器的写法都在换代,某种服务器上强制加密跳转的五步 (https://zhangwenbao.com/iis7-set-http-to-https-redirect.html)是现在的版本。 浏览器侧的规则一直在收紧,证书有效期正在砍向47天 (https://zhangwenbao.com/tls-certificate-lifetime-47-days-renewal-automation.html)是最近的一例。 问题是这个机制本身产生了不少误判,还被发现可以被利用来做别的攻击。于是各家陆续把它拿掉了:主流浏览器在2019年下半年默认关闭并随后移除,另一家浏览器从头到尾就没有实现过它,苹果那边的实现也在之后被移除。 结果是2026年的今天,这个头对任何一个主流浏览器都不产生作用。它在文档里的状态是非标准且已弃用 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-XSS-Protection)。 ## 那两个发0的站,情况最有意思 90个站里有2个发的是0,意思是明确关闭这个功能。 关掉一个已经不存在的东西并不罕见,老代码里那个已被移除的函数 (https://zhangwenbao.com/wordpress-http_user_agent.html)是同一种情形。 这个动作在当年是有道理的——既然那套检测机制会误判、还可能被利用,那么明确关掉它比开着更安全,安全指南里也这么建议过。 但放到今天,这两个站是在明确关闭一个已经不存在的功能。发0和发1,效果完全相同,都是零。这大概是这批数据里最能说明问题的一个细节:连规避风险的那个动作,也已经失去了对象。 ## 那个只发1不带阻止模式的站 取值分布里还有个细节:有1个站发的是不带阻止模式的写法。 取值停在哪一年往往说明流程,四类流程漏洞怎么修 (https://zhangwenbao.com/content-publishing-workflow-seo-governance.html)讲的是同一层问题。 这两种写法在当年是有区别的:不带阻止模式意味着浏览器检测到疑似注入时尝试改写页面内容把它去掉,带阻止模式则是直接不渲染整个页面。安全建议普遍推荐后者,因为改写页面本身也被发现能被利用。 所以这个站的写法在当年属于不够严格的那一档。而放到今天,严格和不严格的区别已经不存在了——两种写法的效果都是零。 这个细节值得留一眼,因为它说明这类配置的年代:这个站的响应头很可能是在那份安全建议广泛流传之前就配好的,之后一直没动过。响应头的取值有时候比字段名更能说明它有多久没被人看过。 ## 覆盖率相等,不等于质量相等 刚才说内容安全策略的覆盖率是64.8%,和这个死头几乎一样。但这里得补一句,免得给人一种已经配好了的印象。 有没有配和配得好是两件事,模板和广告稀释主体内容的七个陷阱 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)也是这个道理。 这个头的难点在于它的质量差异极大。同样是发了这个头,一个写得严格的策略确实能挡住脚本注入;而一个为了不影响业务而写成大范围放开的策略,防护效果接近于零。样本里有相当一部分策略里包含了极其宽松的来源声明,这在实践中很常见——因为收紧它需要逐个梳理页面上所有第三方脚本,而那是一件很费时间的事。 所以这两个数字虽然相等,含义完全不同:那63.4%是确定无效,这64.8%是效果取决于内容。前者可以一刀切地判断,后者必须逐个看。 这也提醒一件事:本文这类按字段名统计覆盖率的做法,只能回答有没有配,回答不了配得对不对。看到覆盖率高不要放心,那是两个层次的问题。 ## 那还该发什么 脚本注入这件事本身当然还在,只是防护手段换了。今天真正起作用的是内容安全策略,也就是通过一份白名单明确规定页面能加载和执行哪些来源的脚本。 批量改配置或字段时要防注入,安全地批量改一批字段的做法 (https://zhangwenbao.com/sql-generator-batch-update-cms-database-injection-guide.html)能省掉风险。 安全这块要成体系,从审查到权限与提示注入防御 (https://zhangwenbao.com/claude-code-security.html)给了一份完整清单。 这批样本里,92个站(64.8%)发了内容安全策略头,覆盖率跟X-XSS-Protection几乎一样。所以对多数站来说,这不是缺不缺手段的问题,只是那个老头留着没删。 ## 那三个头为什么总是一起出现? 接着看这批数据里最整齐的一个分布,它直接解释了这些头是从哪来的。 默认配置互相叠加会出问题,插件与主题各输出一套标记怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是同一种病。 ## 要么三个都有,要么三个都没有 把X-XSS-Protection、X-Download-Options、X-Permitted-Cross-Domain-Policies这三个头放在一起统计每个站发了几个: 默认配置里一个字符就能决定行为,一个字符改对缓存判断 (https://zhangwenbao.com/dedecms-mobile-index-html-update-solution.html)是很小但很典型的例子。 规则该写在哪一层常被搞反,两种手段各管哪一段 (https://zhangwenbao.com/robots-txt-and-meta-robots.html)有清楚的分工。 分布形状能揪出测量问题,量出74%的差异、补上对照组后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)就是靠这个发现的。 发了几个 | 站数 | 占比 | 三个都有 | 65 | 45.8% | 只有两个 | 3 | 2.1% | 只有一个 | 24 | 16.9% | 三个都没有 | 50 | 35.2% | 这是一个双峰分布:两端各占四成上下,中间几乎是空的。只有3个站发了其中两个。 自然写出来的配置不会长这样。如果这三个头是人一条条加的,应该看到各种组合——有人加了两个,有人只加一个最重要的,比例会平缓分布。双峰意味着它们是一次性一起出现的。 ## 用共现关系判断字段来源,是个通用方法 这个双峰分布的发现过程本身有方法价值,值得单独说。 对比法在别处一样好用,对比爬虫和用户看到的页面 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)也是靠两组结果相减。 判断一批配置是人写的还是自动生成的,最快的办法不是看内容,是看组合关系。人写的配置组合是发散的——每个人的判断不同,会出现各种搭配;自动生成的配置组合是收敛的,要么全有要么全无。 所以拿到一批样本,把几个相关字段的共现情况列出来,看分布形状:平缓分布说明是人在逐个决策,双峰分布说明有一个统一的来源。这个判据不需要知道任何平台的内部实现,只看数字。 这个方法在别处也好用。比如判断一批站的结构化数据是手写的还是插件生成的,判断一批页面的元信息是编辑填的还是模板套的,都可以用同样的共现分析。发散是人的痕迹,收敛是机器的痕迹。 ## 它们来自同一个平台 顺着这条线索往下查,答案很干脆:那65个三个都有的站里,62个带着同一个电商平台的特征字段;Server头的值有64个是同一家云服务商。 平台还替你决定了别的事,从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)里能看到哪些归自己管。 换成自建的电商程序又是另一套默认,索引器、缓存与调优讲透 (https://zhangwenbao.com/magento-2-performance-tuning-indexer-cache-redis-varnish-production-mode.html)可以对照看。 平台给的东西该不该接管有判据,平台内置、通用工具与专属应用的三层框架 (https://zhangwenbao.com/shopify-seo-tools-three-layer-selection.html)能帮你划清边界。 换句话说,这三个头不是站主写的,是平台在响应链路上统一加的。站主既没有主动配它们,也没有办法单独去掉它们——那不在他的控制范围里。 这一点改变了整件事的性质。如果这些头是自己写的,清理就是打开配置文件删几行;而如果是平台加的,清理这个动作本身就不存在,你只能知道它们在那儿、知道它们没有作用,然后接受。 ## 自建的站为什么头更干净 这个差异不是因为自建站的团队水平更高,原因更结构化。 自建站的加固要自己配齐,目录禁解析加文件权限 (https://zhangwenbao.com/nginx-dedecms-php-deny-all.html)是最基础的一项。 换架构时这一层要整体重搭,这套基建换了架构就得自己重做 (https://zhangwenbao.com/headless-cms-seo-infrastructure-rebuild-sitemap-meta-canonical-redirect.html)是提前的提醒。 平台建站的响应头是累积的:平台在某个年代加了一批,之后为了不影响存量店铺,一般不会去掉。任何一个新开的店,拿到的都是这份累积到今天的默认配置。 自建站的响应头是每次重新决定的:换一次服务器、迁一次架构、升级一次框架,配置文件往往会被重写或者重新审一遍。这个过程天然带着清理效果——重写的时候没人会主动去加一个陌生的老字段。 所以两边的差异是维护方式带来的,不是判断力带来的。这一点对判断自己的处境有用:如果你的响应头配置已经好几年没被重写过,它的内容大概停留在最后一次重写的那个年代。不管是自建还是平台,这个规律都成立。 ## 再看零头那50个站,构成完全不同 作为对照,把三个头都没有的50个站的Server值列出来:一家云服务商15个、没有发Server头的11个、其余是各种自建或者其它平台,包括几家静态托管服务、几种自建服务器、以及个别自定义值。 边缘那一层会改写很多东西,六层缓存与边缘路由的实际影响 (https://zhangwenbao.com/cdn-cache-configuration-seo-impact-edge-routing-complete-guide.html)值得一并了解。 这批站的共同点是响应头由自己或者自己选的技术栈决定,没有一个统一的平台在中间加东西。它们的头普遍更短,也更干净。 所以这批数据里的死头分布,本质上反映的是平台默认配置的年代,而不是站主的技术水平。用同一个平台的站,头都长得一样;自己搭的站,头各不相同但都更新一些。 ## 这对自查意味着什么 实操上有个直接的推论:查响应头之前先弄清每个字段是谁加的。 中间还有代理层时要分清谁加的,反向代理的完整配置与对比 (https://zhangwenbao.com/apache-proxy.html)讲清了链路。 配置的副作用往往不出声,每次reload都通过,Googlebot每8次抓取却有1次撞在301上 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)是同一类沉默。 判断办法是分层测。直接请求源站地址取一次头,再请求对外的域名取一次,两边做差集,差出来的部分就是边缘层或者平台加的。这一步做完,你才知道哪些字段是自己能改的、哪些不是。 省掉这一步的后果是很实际的:对着一个平台下发的字段查半天配置文件,怎么也找不到它从哪来。 ## 给一个已经停运的插件发跨域策略,还有意义吗? 三个头里最值得单独说的是X-Permitted-Cross-Domain-Policies,67个站(47.2%)在发。它的接收端是这批里最特殊的。 这类残留攒起来就是技术债,技术债怎么排查和分批还 (https://zhangwenbao.com/seo-technical-debt-audit-and-digital-asset-management.html)给了一套顺序。 ## 这个头本来是给谁看的 它管的是一件很具体的事:某些客户端软件在跨域读取数据之前,会先去站点根目录找一份策略文件,看自己有没有被允许。这个响应头的作用是覆盖那份文件的效力,比如声明整站都不许用策略文件。 真通过文档分发内容的站另有功课,压缩瘦身与页面管理的实战 (https://zhangwenbao.com/pdf-compress-reduce-size-merge-split-organize-pages-workflow.html)更贴那类场景。 PDF这类资源有它自己的一套讲究,怎么让它被收录与六个优化点 (https://zhangwenbao.com/pdf-seo-complete-guide-google-indexing-6-real-optimizations.html)单独讲过。 按X-Permitted-Cross-Domain-Policies的适用范围 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Permitted-Cross-Domain-Policies),会去读这套机制的主要就两类客户端:一个是当年遍地都是的网页动画播放插件,另一个是某家公司的PDF阅读软件。 ## 顺带说一个反面情况:确实还需要它的站 把话说完整:这个头并不是对所有站都无意义。 真通过文档分发内容的站要另想,加密、权限与涂密的实战做法 (https://zhangwenbao.com/pdf-encryption-password-permissions-redaction-security-workflow.html)更贴那类场景。 如果一个站确实通过某类客户端软件分发内容,或者提供供第三方跨域读取的数据文件,那么这套跨域策略机制还在它的场景里生效。这类站在企业软件、金融数据、地图服务里还有,只是在消费品电商里基本不存在。 所以判断的时候要加一步:先确认自己有没有那类使用场景。有的话这个头是现行配置,动它需要评估;没有的话它就是残留。 这一步之所以要强调,是因为它是这类清理里最容易出事的地方——按一份通用清单删掉一个自己其实在用的字段。本文给的所有建议动作都带着这个前提:先确认自己的场景,再照做。 ## 主要接收端在2020年底停运 那个播放插件在2020年12月31日正式停止支持,2021年1月起被厂商主动阻止运行,浏览器也早已移除了对它的内置支持。也就是说这个头最主要的读者,已经消失五年多了。 接收端下线之后的迁移可以参考,某个跳转方案下线之后的完整迁移路径 (https://zhangwenbao.com/baidu-uaredirect-js-dedecms-jumps-to-mobile.html)是一次典型清理。 这里要说得准确一些:另一类接收端——那家公司的PDF阅读软件——在某些场景下仍会读取跨域策略。所以这个头不能说完全没有接收端,它的准确状态是:主要读者已经消失,剩下的适用场景极窄,而且跟一个电商站点几乎没有关系。 67个站里绝大多数不提供需要跨域读取的数据文件,也不通过PDF阅读器分发内容。对它们来说这个头就是纯粹的历史残留。 ## 取值几乎都一样 这批站的取值高度统一,基本都是声明不允许使用策略文件。这也符合它作为平台默认配置的性质——默认值总是选最保守的那个。 默认值统一是自动生成的标志,从模板化转向语义化的八步 (https://zhangwenbao.com/semantic-programmatic-seo-blueprint.html)讲了怎么把默认做扎实。 顺带说一句,这个取值本身在当年是合理的选择:多数站确实不需要那套跨域机制,明确关掉比留着不管好。问题只在于时间——当接收端消失之后,最保守的那个声明和什么都不声明,效果一样。 ## X-Download-Options这个头,是写给谁看的? 三个头里的第三个,68个站(47.9%)在发。它的历史更短,接收端也更明确。 文件分发这一层还有别的手段,两种服务器上的防盗链配法 (https://zhangwenbao.com/using-htaccess-to-set-up-wordpress-anti-stealing-link.html)至今有用。 ## 只有一个浏览器读过它 这个头是当年某个浏览器的私有扩展,作用是让用户从站点下载文件时,不能直接在浏览器里打开,必须先存到本地。目的是防止一个恶意的HTML文件在站点的上下文里执行脚本。 只在某一种环境下成立的配置都要留意,伪静态导致后台打不开的修复 (https://zhangwenbao.com/wordpress-nginx-rewrite-404-wp-admin.html)是同类问题。 只服务单一客户端的方案都短命,响应式与自适应的九个维度对比 (https://zhangwenbao.com/responsive-web-design-seo.html)说明了通用性的价值。 它从来没有进入任何标准,也从来没有第二个浏览器实现过它。所以它的接收端从一开始就只有一个。 ## 拿它跟连接安全那个头比一下 为了说清有效和无效的区别,把这批数据里覆盖率最高的那个安全头拿来对照:126个站(88.0%)发了强制安全连接的头。 那个头的配法与回滚都要提前想好,三种服务器上的配置与两条回滚路 (https://zhangwenbao.com/https-hsts.html)都在这里。 这个头是现行有效的,所有浏览器都实现,作用是告诉浏览器以后一律用加密连接访问这个域名。它的覆盖率比X-Download-Options高整整四成。 为什么它的覆盖率这么高?因为它同时满足三个条件:接收端明确、效果可验证、而且被绝大多数平台和证书服务商做成了默认或者一键开关。 对比之下就能看出这批死头的处境:它们当年也进了默认,但当接收端消失时,没有任何机制把它们从默认里拿掉。进默认容易,出默认没有通道。这句话基本可以概括本文所有数据。 ## 那个浏览器已经在2022年退役 那款浏览器的桌面版本在2022年6月15日结束支持,之后的继任者内置了一个兼容模式,但那个模式的触发方式是企业策略配置的站点清单,跟这个响应头没有关系。 协议层的迁移也是同一类工作,从HTTP迁到HTTPS怎么才能不掉排名 (https://zhangwenbao.com/seo-https.html)是完整路径。 所以这个头今天没有任何客户端会读。跟X-XSS-Protection一样,它属于第一种形态:功能被移除,字段本身还能合法地发出去。 ## 这批头当年为什么会被一起推荐 要理解这三个头为什么会成为默认配置,得回到它们被推荐的那个年代。 当年那批加固建议里也有真正有效的,权限分离与应急响应的完整做法 (https://zhangwenbao.com/dedecms-site-security-settings-in-linux-environment.html)至今适用。 照抄清单在工具选型里同样常见,用第一性原理做选型 (https://zhangwenbao.com/seo-tools-martech-replacement-trend-2025.html)比跟着别人的清单走稳。 2010年前后,网站安全加固这件事刚开始被系统整理,出现了一批影响很大的清单式建议:把这几个响应头一起加上,就能挡住当时最常见的几类攻击。清单里的每一项在当时都有明确的对象——有一个浏览器会读它,读了会改变行为。 这批建议后来被大量转载,进了各种框架的中间件、主机面板的一键配置、以及电商平台的默认响应链路。到这一步,它就脱离了原始判断,变成了一个只需要照抄的清单项。 问题出在之后十几年里:清单里的对象一个一个消失了,而清单本身还在流传。这跟爬虫名单老化是完全相同的机制——一份清单被抄下来的那一刻,它就和产生它的那些判断断开了联系。之后对象怎么变,抄清单的人不会知道。 所以这三个头的处境不是有人做错了什么,而是一条链条上没有任何一环负责回头看。写清单的人当年是对的,抄清单的人当年也是对的,只是没有人被安排去检查对象还在不在。 ## 同样是被新头取代,为什么这一个反而该留 这里有个对照值得专门讲,因为它是判断这类问题时最容易搞错的地方。 新旧手段能不能并用是个常见问题,两个手段同时用的九种场景判断 (https://zhangwenbao.com/noindex-canonical-duplicate-page-seo.html)给了明确结论。 样本里有82个站(57.7%)发X-Frame-Options,同时有90个站(63.4%)的内容安全策略里写了帧祖先限制。后者是前者的现代替代品,功能更强也更灵活。按前面的逻辑,旧头似乎该删。 但它不该删,原因很简单:所有现代浏览器至今仍完整实现X-Frame-Options。它没有被移除,也没有被标记为已废弃,只是有了一个更好的替代方案。规范里的建议是两个并行——新的用于精细控制,旧的作为不支持新写法的客户端的兜底。 对比一下就清楚了。Pragma在响应方向上被规范明确定义为没有行为,所以该删;X-Frame-Options被所有浏览器实现,所以该留。两者都是被新头取代,区别在于接收端还在不在。 判据可以固化成一句话:被取代不是删除的理由,没有接收端才是。问这个字段还有没有人读,而不是问它有没有更新的写法。 ## 它和另一个同源头的区别 有个容易混淆的地方值得澄清。同一批安全头里还有一个X-Content-Type-Options,值通常是nosniff,这批样本里110个站(77.5%)在发。 响应头能替非网页资源说话,接口和feed这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)量过一次。 这一个是有效的。所有现代浏览器都实现了它,作用是禁止浏览器根据内容猜测响应类型。它已经进入了正式规范,是今天仍然应该配的头之一。 两个头名字前缀相同、出现的场合相同、通常由同一份默认配置一起下发,但一个有效一个无效。这也说明为什么这类判断不能靠名字或者印象,得逐个查它的接收端。 ## 报告链断在中间:64个站的错误报告,发得出去吗? 接下来这一组比前面几个复杂,因为它涉及两个头的配合,而链条断在了中间。 监控这件事要成闭环,怎么搭一套能在掉量前报警的体系 (https://zhangwenbao.com/seo-monitoring-alerting-regression-detection-system.html)有可复用的规则。 ## 64个站配了网络错误上报 样本里有64个站(45.1%)发了NEL这个头。它的作用是让浏览器把访问过程中遇到的网络层错误——连接失败、证书问题、DNS问题——收集起来上报给站点指定的地址。 这类失败在服务器日志里看不见,从DNS、线路到CDN的网络层排障 (https://zhangwenbao.com/overseas-store-unreachable-slow-network-layer-diagnosis-dns-routing-cdn.html)是配套的排查路径。 这个机制本身很有价值。网络层的失败在服务器日志里是看不见的:请求根本没到服务器,日志里当然没有记录。浏览器主动上报是唯一能看到这类失败的途径。 ## 但上报地址靠的是一个已经进入弃用状态的头 NEL本身不指定上报到哪里,它引用另一个头来定义上报端点。这里就是问题所在: 自己那一侧的日志也要配够,访问日志怎么配才查得清问题 (https://zhangwenbao.com/apache-customlog-logformat-access-log-configuration-remoteip.html)包含真实来源地址。 指定上报端点的头 | 站数 | 状态 | Report-To(旧版) | 65 | 已进入弃用状态,规范建议改用新版 | Reporting-Endpoints(新版) | 2 | 现行标准写法 | 差距是32.5倍。更极端的是把这两个头和NEL交叉看:64个配了NEL的站,全部只有旧版的Report-To,一个都没有配新版的Reporting-Endpoints。 ## 新版写法长什么样 既然结论是先补,那就把补法写清楚。Reporting-Endpoints的现行写法 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Reporting-Endpoints)是在一个头里声明一组命名端点,然后其它机制引用这些名字: 内容协商这类新机制也在长出来,用协商给机器直接送精简内容 (https://zhangwenbao.com/cloudflare-markdown-for-agents-ai-seo-geo.html)是另一个方向。 收上来的数据要有地方放,日志怎么管才不爆盘又查得到 (https://zhangwenbao.com/linux-server-log-management-logrotate-journald-analysis-alerting.html)得先解决。 Reporting-Endpoints: default="https://example.com/report", network="https://example.com/nel" NEL: {"report_to":"network","max_age":86400,"success_fraction":0} 要点有三个。第一是端点名可以自定义,NEL里引用的名字要和声明里的对上。第二是成功采样比例通常设成0,只收失败——设成正数会带来相当大的上报量,而成功的请求你在自己日志里已经有了。第三是新旧并行没有冲突,同时发旧版和新版是安全的过渡做法,不支持新版的客户端读旧的,支持的读新的。 补完之后要验证一次:打开浏览器开发者工具,在网络面板里确认这两个头都发出来了,然后故意制造一次失败——比如访问一个证书不匹配的子域名——看上报端点有没有收到数据。没有验证过的上报配置等于没配,这一点和本文批评的那些死头是同一个道理。 ## 这不等于报告一定发不出去,但状态很脆弱 这里必须说清边界,不能夸大。旧版的头目前在部分浏览器里仍被识别,属于向后兼容期。所以准确的表述是:这64个站的错误上报能不能到达,取决于浏览器还愿意兼容多久,而不取决于站点自己的配置。 依赖别人兼容承诺的事都脆弱,抓取格局这两年的变化速度 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)是另一个例子。 这跟前面几个头有本质区别。前面那些是已经确定无效,处理方式是删掉;这一个是暂时有效但依赖别人的兼容承诺,处理方式是补上新版的写法——加一行,两个头同时发,新旧客户端都覆盖。 这也是这类问题里最值得优先处理的一类:它现在还有作用,而且这个作用会在某个你不会被通知到的时间点消失。 ## 这套机制能看到的东西,日志里确实看不到 顺着说清这套机制为什么值得配,而不只是值得修。 服务器侧的异常也要有对应记录,登录加固与爆破防护 (https://zhangwenbao.com/linux-server-ssh-login-hardening-key-auth-sudo-fail2ban-brute-force-protection.html)是同一批日志里能看到的事。 有些失败确实不出现在日志里,抓取速率被调低的那几天日志里一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)就是这种情形。 服务器日志有一个天然的盲区:它只能记下已经到达服务器的请求。而访问失败最常发生的位置恰恰在到达之前——域名解析失败、连接建立超时、证书校验不通过、中间网络丢包。这些情况下用户看到的是打不开,而服务器日志里什么都没有。 浏览器主动上报机制填的正是这个洞。它让浏览器把这类失败记录下来,攒够一批之后上报给站点指定的地址。对做海外业务的站尤其有用,因为跨境链路上的失败远比本地多,而这些失败在国内的监控里完全看不见。 本文那64个配了它的站,其实配的是一件相当有价值的事——只是上报端点的写法停在了旧版。这也是为什么前面把它列成先补而不是先删:这一组不是历史包袱,是一个配了一半的有用机制。 ## 更容易被忽略的是没人看上报数据 还有一层实操上的问题。配了上报头不等于有人在看上报的数据——上报端点得有一个服务在接、有一个地方展示、有人定期打开。 收了数据没人看是常态,慢查询日志攒了783MB而真正超时的只有32条 (https://zhangwenbao.com/mysql-slow-query-log-signal-noise-ttfb-crawl-budget.html)是同一类现象。 本文没法从外部判断这64个站有没有真的在用这些数据。但从新旧头的比例可以推测一部分:如果有人在实际使用这套机制,他多半会注意到规范换代这件事,因为接收数据的那一端通常会提示。全部64个站都停在旧版,更像是这套配置由平台一次性下发,然后没有人再碰过。 ## 剩下那几个死头,各还剩多少个站在发? 把长尾的几个一起看,它们的数量小,但每一个都对应一段很具体的历史。 缓存这几个头的配合最容易搞混,怎么配才让回头客秒开又不出改了不更新的事故 (https://zhangwenbao.com/http-browser-cache-control-etag-expires-cache-headers.html)讲了取舍。 ## 四个字段的实测数量 字段 | 站数 | 接收端的状态 | Pragma: no-cache | 19(13.4%) | 响应方向上早已废弃,缓存控制由另一个头接管 | P3P | 2(1.4%) | 相关标准工作已停止,唯一读它的浏览器已退役 | X-UA-Compatible | 1(0.7%) | 只有那个已退役的浏览器据此改变渲染行为 | Expect-CT | 1(0.7%) | 浏览器已于2022年移除支持 | 状态相关的配置最容易配错,自定义错误页与软404的正确配法 (https://zhangwenbao.com/apache-errordocument-custom-error-pages-http-status-codes-soft-404.html)单独讲过。 有时候这些头不是你写的,程序在响应头里替你写了一行1981年的日期 (https://zhangwenbao.com/php-session-cache-limiter-nocache-cdn-audit.html)就是个例子。 ## 四个字段各自的时间线 把这四个的关键时间点排在一起,能直观看出它们的年龄。 新旧交替的速度在别处更快,这两年格局变化的规模 (https://zhangwenbao.com/geo-concept-ai-traffic-2000billion-leaders.html)是个参照。 字段 | 大致出现时间 | 失去接收端的时间 | 今天还剩多少站在发 | Pragma | 比现行HTTP版本还早 | 随缓存规范换代逐步废弃 | 19个 | P3P | 2000年前后 | 相关标准工作2018年停止 | 2个 | X-UA-Compatible | 2009年前后 | 对应浏览器2022年6月退役 | 1个 | Expect-CT | 2017年前后 | 浏览器2022年底移除支持 | 1个 | 有意思的是数量和年龄的关系:最老的那个反而剩得最多。这不是巧合——Pragma被写进了无数篇教程和模板,传播面远大于后面三个;而Expect-CT只活跃了五年左右,还没来得及被大量抄袭就退场了。 所以一个字段的残留数量,取决于它当年的传播广度,而不是它失效多久。这也解释了为什么本文最普遍的那三个死头都出自平台默认——传播广度的极致就是被写进默认配置。 ## Pragma这一行为什么还有19个站在发 Pragma是这几个里数量最多的,也最有代表性。它是一个比现行HTTP版本还老的字段,当年用来在请求里表达不要用缓存。 缓存声明要和缓存层对上,全页缓存怎么配以及怎么清 (https://zhangwenbao.com/nginx-fastcgi-cache-fullpage-php-wordpress-purge-microcache.html)里有对应处理。 现行HTTP缓存规范 (https://www.rfc-editor.org/rfc/rfc9111.html)对它的处理写得很明确:这个字段已经废弃,只有出现在请求方向上的no-cache需要被处理,而出现在响应方向上的Pragma没有定义任何行为。也就是说,站点在响应里发Pragma: no-cache,规范上没有任何客户端需要理它。 它能留这么久,原因是很多年前流传的一套写法:为了兼容各种老客户端,把Cache-Control、Pragma、Expires三个头一起发。这套写法在当年是有道理的,因为那时确实还有不认识Cache-Control的客户端。今天这些客户端都不在了,但那套写法还在各种教程和模板里。 ## 那唯一一个Expires单独有效的站 把这个孤例说完,因为它是本文唯一一个逆向的案例。 孤例往往出现在配置最简单的站上,双向跳转的两种服务器写法 (https://zhangwenbao.com/301-url-redirection-http-jumps-to-https-and-https-jumps-to-http.html)是那类站常用的。 孤例最能说明要看上下文,八维决策树与规则迁移 (https://zhangwenbao.com/cloudflare-cache-real-world-optimization-decision-tree.html)也是逐个场景判断的。 28个发Expires的站里,27个同时发了Cache-Control,那27个的Expires都被忽略。剩下1个只发Expires不发Cache-Control——对这个站来说,Expires是它唯一的缓存声明,完全有效。 这个孤例的意义是提醒:同一个字段在不同上下文里的状态可能相反。如果按一份通用清单批量删除Expires,这个站的缓存策略就直接消失了。 所以前面那张判断表里,Expires那一行写的是看情况而不是可删。这类需要看上下文的字段在实践中不算少,处理它们的唯一办法是逐个看,没有捷径。这也是为什么本文反复强调先确认自己的场景——通用结论在孤例上就是错的。 ## 顺带看一个相关的三头组合 正好接着说这三个头的配合,因为样本里还有个数字:28个站(19.7%)发了Expires,其中27个同时发了Cache-Control。 缓存分好几层,对象缓存的原理与运维 (https://zhangwenbao.com/redis-object-cache-wordpress-persistent-cache-hit-rate-operations.html)是另一层的事。 按现行规范,两个头同时存在时,Cache-Control优先,Expires被完全忽略。所以这27个站的Expires也是空转的——它不会造成错误,只是没有作用。 剩下那1个只发Expires不发Cache-Control的站,情况反而不同:这时候Expires是真正生效的。这就是为什么这类清理不能批量做——同一个字段,在不同上下文里可能有效也可能无效。 ## 这几个字段在别的场景里还有活的吗 为了不把话说过头,把这四个字段还可能有效的场景交代一下。 内网和公网的判断标准不同,端口放行与云安全组怎么配 (https://zhangwenbao.com/linux-ufw-firewall-server-port-rules-ssh-cloud-security-group.html)就分了这两种情况。 写代理服务时入方向的字段还得认,反向代理的完整配置场景 (https://zhangwenbao.com/nginx-proxy.html)是前置知识。 按Pragma的弃用说明 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Pragma),它在请求方向上仍然有定义——客户端发出的Pragma: no-cache需要被中间缓存处理。所以如果你在写一个代理或者缓存服务,这个字段在入方向上还得认。它失效的只是响应方向。 P3P和X-UA-Compatible在企业内网环境里可能还有对象:某些机构的终端仍在运行早期版本的浏览器。这类环境不在公网统计里,也不适用本文的结论。判断标准很实际——看自己的访问日志里有没有那些老浏览器的标识,有相当比例的话就得单独考虑。 Expect-CT是唯一没有余地的:它对应的机制已经被更基础的证书透明度要求取代,浏览器不再需要站点声明这件事。 说这些是为了强调一件事:所有关于失效的判断都带着适用范围,范围一变结论可能就变。本文的范围是面向公网消费者的站点,超出这个范围要重新判断。 ## P3P那两个站,值一模一样 剩下三个字段各只有一两个站,但细节挺有意思。 隐私相关的机制变化影响分析口径,默认追踪不到的流量怎么补 (https://zhangwenbao.com/geo-ga4.html)是同一批变化带来的。 发P3P的两个站属于同一个集团旗下的两个品牌,发出来的值一模一样,是一串当年那套隐私声明的紧凑写法。这个头的历史很特殊:它当年真正的用途不是表达隐私政策,而是让一个特定浏览器同意接受第三方Cookie——不发这个头,那个浏览器会拦掉。所以它是一个为了绕过某一款浏览器的限制而存在的头,那款浏览器退役之后,它就彻底没有了对象。 发X-UA-Compatible的那一个站值是让浏览器用最新模式渲染。这个头当年解决的是一个真实痛点:某些浏览器会用兼容模式渲染现代页面,导致布局错乱。今天这个痛点不存在了。 发Expect-CT的那一个站值是max-age=0,意思是关闭这个机制。跟前面那两个发X-XSS-Protection: 0的站一样,是在关闭一个已经不存在的功能。 ## Feature-Policy一个都不剩,这说明什么? 本来预期会在样本里看到不少Feature-Policy,因为它也是一个被新字段取代的旧头。结果是零。 该先做什么得排序,三类站点各自的高回报修复项 (https://zhangwenbao.com/technical-seo-priorities-guide.html)可以直接借。 ## 零的两种可能,得分清 看到零的第一反应可能是清理得很彻底。但这个结论下得太早——零也可能意味着这批站从来就没用过它。 数字为零要看是没做还是做完了,响应模式怎么分析 (https://zhangwenbao.com/ai-response-patterns-deep-decoding-ai-era-content-strategy.html)也强调了取样这一步。 数字为零的解释常有两种,某个命令能查什么、什么时候会误判 (https://zhangwenbao.com/site-command-seo-guide.html)也强调了这一点。 区分办法是看它的继任者用得怎么样。如果继任者覆盖率高,说明发生了迁移;如果继任者也几乎没人用,说明这一类能力从来没被广泛采用过。 ## 继任者只有6个站在用 字段 | 站数 | 说明 | Feature-Policy(旧) | 0 | 已被取代 | Permissions-Policy(新) | 6(4.2%) | 现行标准写法 | Referrer-Policy | 18(12.7%) | 现行有效 | Cross-Origin-Opener-Policy | 4(2.8%) | 现行有效 | Cross-Origin-Embedder-Policy | 2(1.4%) | 现行有效 | 该配的东西要按收益排,让机器抓得到、读得懂、引得出 (https://zhangwenbao.com/geo-technical-optimization-crawl-render-extract-guide.html)是技术端的落地清单。 答案清楚了:不是迁移完成,是这一整类头本来就极少有人配。旧的零个、新的六个,两边都接近于零。 ## 新头没人配,原因不是不知道 先解释一下为什么现行有效的新头覆盖率这么低,因为这决定了该怎么改。 收益不可见的事都排不上,500个站实测排出来的优先级 (https://zhangwenbao.com/technical-seo-prioritize-business-impact.html)能帮你把顺序讲清。 最容易想到的解释是大家不知道它存在。但这个解释站不住——这些头在各类技术清单和审计工具里都有,做技术的人多半听说过。 真实原因更实际,有三条。一是配它需要先做调研:能力策略这类头要求你列清页面上到底用了哪些浏览器能力,而这件事在一个挂了七八个第三方脚本的电商站上相当费时间。二是配错了会直接坏功能:一个写得过严的策略会把地图、支付按钮、视频播放器一起关掉,而这类故障往往要等用户反馈才发现。三是它没有可见收益:配好之后没有任何指标会变好,只是理论上减少了某类风险。 调研成本高、配错代价大、收益不可见——这三条合起来,任何团队都会把它排到最后。这跟前面那些死头留在文件里的机制正好互补:删掉没用的没有收益,配上有用的也没有收益,于是两件事都不会发生。 ## 那什么情况下它才会被推动 按观察,这类配置真正落地通常靠三种外力。 做成默认或者一键是最有效的推动,免插件自动更新站点地图 (https://zhangwenbao.com/wordpress-free-plug-in-automatically-updates-sitemap-xml.html)就是这个思路。 靠流程推动比靠说服有效,把变更做成日志的十三类信号 (https://zhangwenbao.com/seo-changelog-enterprise-governance-13-signals-5-tools-22-weeks.html)讲的就是这套办法。 第一种是平台或框架把它做成默认。这是效率最高的路径,本文那三个死头就是这么普及的——只不过它们普及的时候还是有效的。 第二种是合规要求点名。当某份检查清单明确要求某个字段时,它会在一个季度内被大批量补上。这也是为什么本文强调要把清理结果同步给做审计的人——清单的力量比技术判断大。 第三种是出过一次事故。这是代价最高的推动方式,但效果最持久。 知道这三条之后,推动这类工作的策略就清楚了:别去说服每个人理解字段的原理,去改清单,或者去找平台的默认配置。 ## 这个对照才是本文最该记住的数字 把两组数字并排放着,整件事的形状就出来了。 两个数字并排看才有意义,从指标体系到异常诊断的完整做法 (https://zhangwenbao.com/seo-data-analysis-guide.html)可以拿来搭口径。 类别 | 代表字段 | 覆盖率 | 是谁配的 | 已经没有接收端的老头 | X-XSS-Protection | 63.4% | 平台默认下发 | 已经没有接收端的老头 | X-Download-Options | 47.9% | 平台默认下发 | 现行有效的新头 | Permissions-Policy | 4.2% | 需要人主动写 | 现行有效的新头 | Cross-Origin-Opener-Policy | 2.8% | 需要人主动写 | 已经没用的头覆盖六成,真正有用的新头覆盖百分之几。这个反差不是因为大家不懂,而是因为两者的来源完全不同:老头是平台在某个年代一次性加进默认配置的,从此跟着每个新建的站;新头需要有人知道它存在、判断需不需要、然后手写进配置。 ## 那这类新头到底该不该配 给一个实用的判断,不然读完只会觉得两头都不对。 引荐来源这类设置会影响归因,服务器端跟踪的部署方式 (https://zhangwenbao.com/dtc-ga4-bigquery-user-journey-stape-server-side.html)对数据准确性影响更大。 先看能力策略这一类。它的价值在于限制页面能用哪些浏览器能力——摄像头、地理位置、全屏、支付接口这些。对一个内容站或者普通电商站,这个限制的实际收益不大,因为页面本来就不用那些能力,被滥用的概率也低。所以它属于有余力再配的档位,排在内容安全策略后面。 再看跨源隔离那两个头。它们的用途更窄,主要服务于需要用到高精度计时或者共享内存的场景。普通站点配了没有坏处但也没有收益,不配完全合理。本文列出它们的覆盖率,是为了说明覆盖率梯度,不是在建议每个站都补上。 唯一建议所有站都检查的是引荐来源策略——18个站(12.7%)在发。它决定用户从你的站点跳转出去时,对方能看到多少来源信息。这个头影响的是隐私和数据分析的准确性,配置成本极低,收益是确定的。 所以这一节的结论不是补齐所有新头,而是:按收益排序,别按清单顺序。清单是平铺的,收益不是。 ## 覆盖率高低,基本等于有没有人做成默认 这个规律在这批数据里到处都能验证。自动加的字段覆盖率极高——压缩相关的头、连接安全相关的头都在八成以上;需要人写但有成熟模板可抄的落在五到七成;需要人写又没有默认模板的,掉到一成以下。 自建站的默认值由自己决定,从主机、插件到核心指标的完整做法 (https://zhangwenbao.com/wordpress-seo-guide.html)可以对照排期。 所以要提高一类配置的覆盖率,最有效的动作不是写文章劝人配,是让它进入某个平台或者框架的默认值。反过来说,一旦一个错误的东西进了默认值,它的清理难度也一样大——这就是本文那248个死头的由来。 ## 这些多余的字段,代价到底在哪里? 这一节要把账算清,因为如果代价真的可以忽略,那前面所有内容就只是一篇趣闻。 字节这件事在别处才是真问题,页面体积超出之后商品链接被截在外面 (https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html)是实测过的后果。 ## 字节层面:中位数102字节,占响应头的1.74% 先量最直观的。142个站的响应头总字节数中位是3204,平均3298,最小的只有98字节,最大的17951。字段行数中位27行,最少4行,最多42行。 真要省字节该看压缩,出厂只压一种类型、其余字节全额计入 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)是更大的一块。 死头占的部分:100个有死头的站里,中位数是102字节,最多120字节。全部142个站合计8145字节,占响应头总字节的1.74%。 算成实际流量:一个日均10万次请求的站,每天多发大约10MB,一年3.7GB左右。这个量对带宽成本几乎没有影响,对首字节时间的影响也小到测不出来。 所以字节这一层的结论要说得干脆:不值得为了省这102个字节去动配置。如果有人拿性能当理由推动清理,这个理由站不住。 ## 那真正的代价是什么 代价有三层,都不在字节上。 看起来达标的指标常有水分,三平台和300个站的实测对比 (https://zhangwenbao.com/seo-kpi-guide.html)能看出差距。 看起来做过了其实没做的情况不少,大量没用的页面怎么诊断和处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)有一张决策矩阵。 第一层是安全审计的假阳性。各类在线检测工具会给响应头打分,而不少工具的评分规则里还留着这些老头——发了就加分,没发就提示缺失。于是一个发着三个死头、却没配现代能力策略的站,可能拿到比反过来的站更高的分数。这个分数会进到报告里,报告会进到会议里,最后变成一句这一块已经做过了。 第二层是它挤掉了注意力。前面那张对照表说明了这个问题的规模:死头覆盖六成,有效的新头覆盖百分之几。如果一个团队看到自己的响应头里已经有一排安全相关字段,他去补新头的动力会明显下降——看起来已经配了不少了。 第三层是排查时的噪声。响应头是排查线上问题时最常翻的地方之一,中位27行里有三四行是完全无效的历史残留,每次都要重新判断一遍这行有没有用。这个成本很小但反复发生。 ## 什么时候值得主动去查一遍 既然日常没有反馈,那查的时机就得靠事件触发。有四个时机的收益最高。 排查问题时顺手多看几眼最划算,负载飙高怎么定位到进程 (https://zhangwenbao.com/linux-server-performance-troubleshooting-high-load-cpu-memory-disk-io-diagnosis.html)是常走的路径。 改版是最好的清理窗口,改版不掉SEO的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)里有对应检查项。 第一个是换平台或者换架构的时候。这时候响应头会整体重建,是唯一一个天然的清理窗口,成本几乎为零。 第二个是拿到安全审计报告的时候。报告里通常会列一堆响应头相关的项,正好借这个机会把每一项的接收端核一遍,顺手把审计规则本身也修正掉。 第三个是接入或者下掉第三方服务的时候。第三方服务经常会要求放开某些策略,改完之后那些放开的部分常常忘了收回去。 第四个是排查一个跟浏览器行为有关的问题时。既然已经在看响应头了,多花五分钟把全部字段过一遍,比专门安排一次检查更容易发生。 反过来说,不建议把它做成固定周期的独立任务。这类没有可见收益的任务在排期里活不过第二个季度,挂在别的事情上才活得久。 ## 审计规则那一层,怎么改才有效 既然假阳性来自审计规则,那就得说清这一层怎么动。 把审查交给自动化之前有前提,数据、方法、人工复核这三条 (https://zhangwenbao.com/ai-seo-geo-audit-agent-pitfalls.html)缺一条结论就不能用。 常见的检查清单里,安全响应头这一项通常列着一串字段名,逐个检查有没有发。改法有两步。 第一步是把清单里的字段分成三组重新组织:现行有效的必须发、已失效的不该发、新旧换代的必须发新版。这样一份清单从一个平铺的名字列表变成了有判断的结构,而且每一组的动作是明确的。 第二步是给每个字段加一列依据来源,写明这个判断出自哪份规范或者哪条浏览器状态记录。加了这一列之后,清单本身就可以被复核了——下次有人质疑某一项,可以直接去查那个来源,而不是争论谁的经验更新。 这两步做完,清单从一份需要定期人工重写的文档,变成一份可以核对的表。这跟前面处理robots.txt里那些字段是同一个思路:把结论换成判据,结论会过期,判据不会。 ## 什么时候它会变成真问题 有两种情况会让这些字段从无害变成有害。 新旧两套声明同时存在会打架,跨页场景下的八种冲突 (https://zhangwenbao.com/canonical-tag-mechanism-cross-domain-self-conflict-diagnosis.html)有对应诊断办法。 一种是字段之间互相干扰。同一个语义有新旧两套写法时,旧的可能覆盖或者干扰新的。样本里那27个同时发Expires和Cache-Control的站属于这类的温和版本——旧的被忽略,没有坏处;但换成别的字段组合,比如新旧两套跨域策略同时存在,行为就可能不符合预期。 另一种是把它当成了防护。如果某个团队因为发着X-XSS-Protection而没有配内容安全策略,那这个头就不只是无害的残留,它直接替代掉了一个真正有效的手段。这批样本里内容安全策略的覆盖率是64.8%,跟X-XSS-Protection几乎相等——说明多数站两个都有,但那剩下的部分值得单独看一眼。 ## 怎么判断一个响应头今天还有没有接收端? 这是本文最想给出的东西:一套能自己执行的判断办法,而不是一份会过期的清单。 越熟练越容易漏掉结构性问题,资深团队的技术判断为什么会失灵 (https://zhangwenbao.com/advanced-technical-seo-overlooked-issues-diagnostic.html)讲的正是这类盲区。 ## 三个可查的信源,按可靠度排序 第一可靠的是标准文档本身。字段进了正式规范,规范里会写明它的状态——现行、已弃用、还是已废弃。已弃用意味着规范建议不要再用,通常同时指出替代方案。 信源不同结论就不同,同一个指标各家工具差那么大 (https://zhangwenbao.com/keyword-difficulty-metric-cross-tool-truth.html)是最典型的一例。 不同工具能回答的问题不一样,五大类工具各自的边界 (https://zhangwenbao.com/seo-tools-recommendation-2026.html)可以拿来配组合。 第二可靠的是浏览器的功能状态记录。各家浏览器都有公开的特性状态数据库,能查到某个功能是什么时候引入的、什么时候被移除的、当前在哪些版本里可用。这是判断功能被移除这一类的唯一硬证据。 第三是权威的字段参考文档。它们通常会在页面顶部直接标注非标准或已弃用,并写清哪些浏览器实现过它。查得最快,适合初筛。 三者都查不到的字段,基本可以断定它是某家平台的私有扩展——这类不需要判断,因为它对浏览器本来就没有语义。 ## 一个更快的反向判据 还有个不用查文档的办法,适合快速筛:看浏览器开发者工具的控制台会不会对它有反应。 开发者工具能看出的东西不少,四种渲染模式的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)也是这么测出来的。 现代浏览器对自己认识但配置有问题的头会给出提示,比如内容安全策略写错了会明确报出违规详情,跨域策略冲突会说明原因。而对完全不认识的头,控制台一个字都不会说。 所以打开控制台把页面刷一遍,凡是响应头里有、控制台从来不提的字段,都值得拿去查一查——它可能是私有扩展,也可能是已经没人读的老头。这个办法不严谨但很快,适合先缩小范围。 ## 本文所有字段的判断结果汇总 把这批数据里遇到的字段按结论整理成一张表,可以直接拿去对照自己的站: 逐项校验的思路在别处一样,一个尾逗号就能让整页标记失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)是同类静默错误。 页面那一侧也有类似的体检表,骨架的六个维度体检 (https://zhangwenbao.com/structure-analyzer-html-skeleton-6-dimension-audit-guide.html)能揪出结构短板。 字段 | 本批覆盖率 | 结论 | 建议动作 | X-XSS-Protection | 63.4% | 对应功能已被浏览器移除 | 可删,改用内容安全策略 | X-Download-Options | 47.9% | 唯一读它的浏览器已退役 | 可删 | X-Permitted-Cross-Domain-Policies | 47.2% | 主要接收端已停运 | 多数站可删 | Pragma: no-cache | 13.4% | 响应方向上已废弃 | 可删,保留Cache-Control | P3P | 1.4% | 唯一读它的浏览器已退役 | 可删 | X-UA-Compatible | 0.7% | 现代浏览器不据此改变行为 | 可删 | Expect-CT | 0.7% | 浏览器已移除支持 | 可删 | Report-To | 45.8% | 已进入弃用状态但仍被兼容 | 补发新版,两个并行 | Expires | 19.7% | 与Cache-Control同存时被忽略 | 看情况,单独存在时有效 | X-Content-Type-Options | 77.5% | 现行有效 | 保留 | Content-Security-Policy | 64.8% | 现行有效 | 保留并检查质量 | Permissions-Policy | 4.2% | 现行有效但极少人配 | 值得补 | ## 把判断做成一段能重复跑的检查 手工查一遍之后,可以把结论固化成一段脚本,以后每次上线顺手跑一次。思路是维护一份自己确认过的失效字段清单,然后检查响应头里有没有出现它们: 检查脚本适合挂成定时任务,用cron把这些活自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)有可直接改的脚本集。 DEAD="x-xss-protection x-download-options x-permitted-cross-domain-policies expect-ct p3p x-ua-compatible" H=$(curl -s -D - -o /dev/null https://example.com/) for f in $DEAD; do echo "$H" | grep -qi "^$f:" && echo "还在发: $f" done echo "$H" | grep -qi "^report-to:" && ! echo "$H" | grep -qi "^reporting-endpoints:" && echo "上报端点只有旧版" 这段东西的价值不在于它有多精巧,而在于它把一次性的判断变成了可重复的检查。清单里的字段是你自己确认过的,所以不会像通用工具那样给出过期结论;而每次上线跑一遍,能挡住配置回退——比如某次改动把老配置又带回来了。 要记得给清单加上确认日期,并且在里面写清每一项的依据。半年后再看的时候,你需要知道当时为什么把它列进来。 ## 遇到查不到的私有字段,怎么处理 实际操作时会遇到一批查不到任何资料的字段,本文样本里的233种字段名有相当一部分属于这类。它们通常是平台内部用的标识,比如请求追踪编号、缓存节点信息、分片标识。 这类字段的处理原则是不管,但要区分两件事。 第一件是它们对浏览器没有语义,所以不构成本文讨论的问题——它们不是失效的配置,而是本来就不写给浏览器看的东西。 第二件是其中有一部分会暴露技术栈信息。样本里有17个站(12.0%)发了标明服务端技术和版本的字段,还有125个站(88.0%)发了服务器软件名。这属于另一个话题——信息暴露面,跟本文的失效问题无关,但既然查到了顺手处理一下也不费事:这类字段通常在服务器配置里一行就能关掉。 判断某个私有字段是不是该关,标准也简单:它有没有暴露版本号。暴露了就关,没暴露就留着,那多半是运维或者客服排查问题时要用的。 ## 这张表本身也会过期 得说明一句:这张表是2026年8月的状态,它跟本文批评的那些清单是同一种东西——一份会过期的现成结论。 会过期的结论都需要复核机制,上千篇旧内容的留改并删转怎么定 (https://zhangwenbao.com/content-audit-pruning-decision-system.html)是同一套思路。 所以更该记住的是产生这张表的动作:拿到一个字段名,去查它在规范里的状态、在浏览器里的实现状态,两个答案合起来就是结论。这个动作每个字段花两三分钟,而且永远不会过期。 ## 清理的时候,该按什么顺序动手? 最后给一套可执行的顺序。这里的关键不是删得干净,是别把有效的一起删掉。 这几层的顺序不能乱,重写、缓存、规范化六层怎么排 (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)有完整示例。 ## 第一步:先分层,弄清每个字段是谁加的 这一步必须放在最前面,否则后面全是白忙。做法是取两次响应头做对比: 上游和边缘各自会加东西,反向代理缓存怎么配 (https://zhangwenbao.com/nginx-proxy-cache-reverse-proxy-upstream-cache-purge-stale.html)能帮你理清链路。 边缘那一层能改的东西不少,在CDN边缘改配置的原理与落地形态 (https://zhangwenbao.com/edge-seo-cdn-worker-no-deploy-implementation.html)给了几种形态。 curl -sI --resolve example.com:443:源站IP https://example.com/ > /tmp/origin.txt curl -sI https://example.com/ > /tmp/edge.txt diff <(grep -oiE '^[a-z0-9-]+:' /tmp/origin.txt | sort) \ <(grep -oiE '^[a-z0-9-]+:' /tmp/edge.txt | sort) 第一条命令绕过边缘节点直连源站,第二条走正常路径,差集就是边缘层或者平台加的字段。要注意有些环境不允许直连源站,那就换成在服务器本机对127.0.0.1请求并带上Host头。 分层的结果决定后面的动作:自己加的可以直接删;平台加的删不掉,只能记录下来知道它无效;边缘层加的通常能在边缘的规则里改。 ## 第二步:先补,再删 顺序很重要——先把需要补的补上,再动删除。原因是删除是不可逆的动作,而且删错了不会立刻表现出来。 补配置的收益有时相当直接,服务器把没改过的页面对爬虫重发了几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)就是没补的后果。 改配置前先想好怎么退回来,备份了不等于安全,恢复演练才是底气 (https://zhangwenbao.com/disaster-recovery-drill-backup-restore-rto-rpo-rollback.html)是同一个道理。 需要补的通常只有两类。一类是新旧换代里的新版写法,比如前面说的上报端点,加一行让新旧并行,这一步没有任何风险。另一类是那些覆盖率极低但现行有效的头,判断需不需要之后再配。 补完观察一两周,确认没有异常,再进行删除。 ## 第三步:删除按确定性分批 删的时候分三批,按确定性从高到低走。 动服务器配置要小步走,多域名统一跳转的完整配置 (https://zhangwenbao.com/nginx-open-ssl-www-and-http-all-jump-to-non-www-https-domain.html)可以照抄。 第一批是功能已被移除的:这类删掉零风险,因为它现在就没有任何效果。第二批是接收端产品已退役的:同样零风险,但删之前确认一下自己的用户里确实没有那类客户端——如果是面向企业客户的站,情况可能不同。第三批是被新字段取代的:必须先确认新字段已经生效,再删旧的。 每批之间留一个观察窗口。虽然理论上都是零风险,但配置改动本身可能带来别的问题——比如改动配置文件时不小心影响了同一个区块里的其它字段。 ## 平台加的那些,能做什么 如果字段来自平台且删不掉,能做的有三件事。 服务器配置这一层的写法要熟,重写规则到底怎么写才不绕晕 (https://zhangwenbao.com/apache-mod-rewrite-rewriterule-rewritecond-flags-engine-guide.html)是常用参考。 一是记录。在自己的配置文档里写清哪些字段是平台加的、哪些已经无效,这样下次做审计时不会重复判断,也不会有人对着它找配置文件。 二是不要重复。既然平台已经在发,自己就别再发一遍——样本里没发现重复发同一个字段的情况,但这在自建加平台的混合架构里确实会出现。 三是在评审里说明。当安全审计报告把这些头列成加固措施时,指出它们已经无效,把注意力引到真正需要配的字段上。这一步的价值比删掉那102个字节大得多。 ## 这件事多久做一次合适 按本文观察到的变化速度,一年一次足够,而且最好不要单独安排。 哪些该交给脚本有讲究,哪些能自动化、哪些不能 (https://zhangwenbao.com/seo-automation-tasks-tools-workflows-2026.html)划了一条比较清楚的界。 理由是响应头这一层的变化比爬虫名单那类东西慢得多。一个字段从被浏览器移除到彻底没人提,通常要好几年;而新字段的出现速度也不快,一年里值得关注的新增通常只有一两个。所以高频复核没有意义。 但有一件事值得每次上线都做,就是前面那段自动检查——它防的不是新字段出现,是旧配置回退。配置回退这件事比字段失效常见得多:一次回滚、一次合并冲突、一次从旧模板复制配置,都可能把清理掉的东西带回来。 所以节奏是:判断一年一次,检查每次上线。前者需要人的判断,后者交给脚本。 ## 一次真实的清理是什么样的 保哥今年上半年帮一个做母婴用品的独立站过技术审查,响应头这一项就是照上面这套顺序走的。 指标不动不代表工作没意义,流量暴跌的七个元凶与三个诊断案例 (https://zhangwenbao.com/seo-cant-fix-broken-brand.html)说明归因有多容易错。 先分层,结果发现团队自己在服务器上配的只有五个字段,其余十几个全是平台和边缘层加的。这个结果本身就让讨论清晰了很多——原来大部分讨论对象根本不在自己手里。 自己那五个里,有两个属于本文说的确定失效,一个是新旧换代需要补新版,剩下两个有效。动作因此变得非常具体:补一行,删两行,留两行。整件事二十分钟做完。 平台加的那批做了另一件事:写进了配置文档,标注哪些无效、依据是什么、确认日期是哪天。后来那份安全审计报告里把这几个头列成加固措施时,团队直接把这份文档贴过去,省掉了一轮解释。 值得说的是效果——所有指标都没有变化,因为删掉的东西本来就不起作用。这类工作的产出不是指标,是把一份说不清的配置变成一份说得清的配置。下次有人问这个头为什么在这儿,有答案。 ## 一份可以直接用的检查清单 把整套动作压成清单:取一次完整响应头并存档;分层确认每个字段的来源;对着字段名逐个查规范状态与浏览器实现状态;把结论写进配置文档,注明确认日期;先补新版写法,观察;再按确定性分三批删除;把清理结果同步给做安全审计的人,避免下次又被要求加回来。 后台那边的告警也要分级,三平台后台告警怎么分级诊断 (https://zhangwenbao.com/webmaster-alert-triage-gsc-bing-baidu-three-platform.html)给了处理顺序。 最后这一条经常被忽略,但它决定了这次清理是一次性的还是永久的。如果审计规则没改,删掉的头会在下一次审计之后被要求加回来——本文这248个字段里,有一部分就是这么来的。 ## 回到最初那个问题 整篇量下来,最值得带走的其实不是那些百分比,是一个提问的习惯。 分层提问这个习惯用处很广,收录、排名、流量是三件事,先分清卡在哪 (https://zhangwenbao.com/indexed-ranked-traffic-three-layer-seo-diagnosis.html)是最常用的一版。 响应这一层还有更要紧的事,一上量就慢该怎么调 (https://zhangwenbao.com/apache-performance-tuning-mpm-event-php-fpm-maxrequestworkers-high-concurrency.html)影响的是所有请求。 响应头、robots.txt、域名记录、邮件策略——凡是你写下之后由别人的实现来解释的配置,都该定期问一句:读它的那一方还在吗。这个问题不会有人替你问,因为对方消失的时候不会通知你,你的系统也不会报错。 而问这一句的成本其实很低:一个字段两三分钟,一份配置一两个小时。真正难的地方在于想起来该问——毕竟一个安静了七年的字段,看起来和一个正在生效的字段一模一样。 ## 常见问题解答 响应头里哪些字段可以直接删掉? 确定性最高的是三类:功能已被浏览器移除的(X-XSS-Protection、Expect-CT)、唯一读它的客户端已退役的(X-Download-Options、P3P、X-UA-Compatible)、响应方向上规范已定义为无行为的(Pragma)。这三类删掉零风险。另有两类不能一刀切:X-Permitted-Cross-Domain-Policies要先确认有没有通过PDF阅读器分发内容的场景;Expires要看有没有同时发Cache-Control——28个发它的站里有1个是单独发的。 怎么知道某个字段是平台加的还是自己加的? 取两次响应头做差集。第一次绕过边缘节点直连源站,第二次走正常的对外域名,两边的字段名清单一减,多出来的就是边缘层或者平台加的。不允许直连源站的环境,可以在服务器本机对127.0.0.1请求并带上Host头。这一步必须放在清理之前,否则会对着一个自己改不了的字段翻半天配置文件。本文那65个发全三个死头的站里,62个带同一个电商平台的特征字段、Server值有64个是同一家云服务商——这些字段全部不在站主的控制范围内。 删掉X-XSS-Protection会不会降低安全性? 不会,因为它现在没有提供任何防护。它对应的是浏览器内置的一套脚本注入检测机制,主流浏览器2019年下半年就默认关闭并随后移除了,另一家浏览器从来没实现过。今天真正防这类问题的是内容安全策略。本文样本里内容安全策略的覆盖率是64.8%,跟这个死头几乎相等,说明多数站两个都有。删之前确认一件事:自己的内容安全策略是不是写得足够严——如果它为了不影响业务写成了大范围放开,那实际防护就得另外补,这跟删不删老头是两件事。 有了内容安全策略的帧祖先限制,X-Frame-Options还需要发吗? 需要,两个并行才是推荐做法。区别在于接收端还在不在:X-Frame-Options至今被所有现代浏览器完整实现,它只是有了更好的替代品,不是失去了读者。规范的建议是新的用于精细控制,旧的作为兜底。这正好是判断这类问题的关键——被取代不是删除的理由,没有接收端才是。本文样本里82个站发X-Frame-Options、90个站的策略里写了帧祖先限制,两者大量重叠,这个状态是对的。 Report-To已经弃用,该怎么迁到新写法? 加一行,两个并行,不用急着删旧的。新写法是用Reporting-Endpoints声明一组命名端点,然后在NEL里引用端点名。要点有三个:端点名可以自定义但引用要对上;成功采样比例设成0只收失败,否则上报量会很大;新旧同时发是安全的过渡。本文那64个配了网络错误上报的站,全部只有旧版的Report-To,一个都没有配新版——它们的上报能不能到达取决于浏览器还兼容多久,而这是最该优先处理的一类,因为它现在还有用,而这个作用会在某个你不会被通知到的时间点消失。 这些多余的响应头会拖慢站点或者影响SEO吗? 基本不会,这一点得说得干脆。本文实测:有死头的100个站里,这些字段占的字节数中位是102,全部142个站合计8145字节,占响应头总字节的1.74%。一个日均10万请求的站每天多发大约10MB,对带宽和首字节时间的影响都测不出来。所以拿性能当清理理由是站不住的。真正的代价在三个地方:安全审计工具会把它们当加固措施打勾造成假阳性、它们让人误以为安全这块已经做过了从而不去补真正有效的头、以及每次排查问题时都要重新判断一遍这行有没有用。 安全审计报告要求加上这些头,该怎么处理? 改清单比改配置重要。做法是把清单里的响应头项重新分成三组——现行有效的必须发、已失效的不该发、新旧换代的必须发新版,然后给每一项加一列依据来源,写明这个判断出自哪份规范或哪条浏览器状态记录。加了来源之后清单本身可以被复核,下次有人质疑可以直接查依据而不是争论谁的经验更新。如果字段是平台加的删不掉,就把这个事实写进配置文档,审计时直接引用,省掉一轮解释。跳过这一步的话,删掉的头会在下一次审计后被要求加回来。 Permissions-Policy这类现行有效的新头,值不值得配? 按收益排序,别按清单顺序。本文样本里它的覆盖率只有4.2%,而已经失效的老头覆盖六成——这个反差不是因为大家不懂,是因为配它需要先梳理页面用了哪些浏览器能力、配错了会直接坏功能、而且配好之后没有任何指标会变好。对普通电商站和内容站,它的实际收益不大,排在内容安全策略后面。真正建议所有站都检查的是引荐来源策略,配置成本极低、收益确定。跨源隔离那两个头用途更窄,不配完全合理。 ## 权威参考资料 ## 尺码表实测55个站:有入口的页面里,近一半源码没有表 - URL:https://zhangwenbao.com/product-page-size-chart-carrier-audit.html - 分类:技术SEO - 发布:2026-08-07 | 更新:2026-08-07 - 摘要:AI助手答不出你家商品该穿几码,多半不是模型的毛病。做独立站的人都以为自己站上有尺码表,可换成只会读HTML的程序去看同一页,那张表常常不是表——它是网格、是图片、是PDF,或者要等用户点一下才存在。 - 关键词:技术SEO,电商SEO,网页语义化 > **TLDR**:摘要:拿真实浏览器打开55个英文独立站的258个商品页,把页面上所有“看起来是表”的东西按载体清点了一遍。写着尺码指南的入口一半页面都有,可点进去之后,DOM里既没有表格、也没有网格、也没有图的,占了48.8%。商品页里连一个table标签都没有的,是76.7%。这不是没做尺码表,是那张表根本没有以“表”的形式交出去。 > 摘要:拿真实浏览器打开55个英文独立站的258个商品页,把页面上所有“看起来是表”的东西按载体清点了一遍。写着尺码指南的入口一半页面都有,可点进去之后,DOM里既没有表格、也没有网格、也没有图的,占了48.8%。商品页里连一个table标签都没有的,是76.7%。这不是没做尺码表,是那张表根本没有以“表”的形式交出去。 做跨境独立站的人,多半都相信自己站上是有尺码表的。运营截过图,设计师画过稿,客服天天往聊天窗口里粘那张图。可如果换一个身份去看同一页——不是用眼睛,而是用一段只会读HTML的程序——你会发现事情不太一样。 我起这个念头,是因为一件很小的事。一个做户外服饰的朋友问我,为什么AI助手回答“这件冲锋衣XL的胸围是多少”的时候,答的是别家的数据。他的商品页上明明白白有一张尺码表,人人都看得见。我把那页扒下来看了一眼,尺码表在,但它是一张PNG。 于是就有了这次清点。问题很朴素:屏幕上那张尺码表,浏览器交出去的到底是什么东西? ## 这台实验是怎么搭的,判据又是什么? 样本沿用手上那份英文独立站清单,55个站,覆盖服装、鞋履、家居、寝具、3C、食品饮料几个大类。每个站挑5个商品页:变体最多的两件(通常就是有尺码的那类)、图片与标签最多的主推款一件、最长尾的一件,再随机一件。一共275个请求,其中258页返回200并且能正常解析。 剔掉的那些不算数:everlane、misen、glossier等几个站有页面撞上429限流,另有若干404,这些逐条记在原始数据里,没有拿去凑分母。ugreen整站取不回商品页,直接不进样本。这是老规矩了,拿不到页面不等于人家没写 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html),两件事必须分开。 ## 什么算“表” 判据得先说清楚,不然数出来的东西没法比。HTML标准里表格那一章 (https://html.spec.whatwg.org/multipage/tables.html)规定得很死:一张表格是一个二维网格,每个格子的坐标由它所在的行和列共同决定,浏览器解析的时候会真的构建出这个网格。这句话是本文所有判据的地基——凡是把行列关系交给CSS去表达的,浏览器那边就不存在这个网格。 页面渲染完成之后,我在浏览器里同时数五类东西: 载体 | 判据 | 机器能不能读出行列关系 | 真表格 | 存在table元素 | 能,前提是写了表头 | 网格伪表 | 非表格元素,计算样式为grid,至少3列、至少6个子元素 | 不能,行列只存在于渲染结果里 | 老式表格布局 | 非表格元素,计算样式为table/table-cell | 不能 | 整张图片 | 图片地址或替代文本命中尺码表、规格表这类词 | 不能,像素里没有结构 | 定义列表 | 存在dl元素 | 能,名字与值天生成对 | 另外单独记一件事:页面上有没有“尺码指南”这类入口——按钮、链接、折叠标题,文字命中size guide、fit guide、measurement这几组词。有入口,说明这个站主观上认为自己提供了尺码信息。入口和内容对不对得上,是本文最核心的那一格。 ## 三条不打算展开的边界 第一,不谈尺码数值本身对不对。厘米换英寸这道算术上没人负责,那是另一篇的事,尺码那一栏的数字不归译者管 (https://zhangwenbao.com/minor-language-size-unit-conversion-keyword.html)里已经把整条流水线拆过一遍。第二,不谈尺码标准与用户自我认知的错位,行业标准把多数成年人算成大码 (https://zhangwenbao.com/apparel-size-self-identification-label-gap.html)那篇讲的是另一层。第三,不谈折叠与标签页把信息藏起来对转化的影响,那排标签把商品页收拾得很干净 (https://zhangwenbao.com/product-page-horizontal-tabs-adjacency-requirement.html)已经算过那笔账。这一篇只问一件事:载体。 ## 五分之四的商品页,一个table标签都没有 先看最粗的一层。258个商品页里,含至少一个table元素的只有60页,占23.3%;剩下的198页,一个都没有。按站算,55个站里只有20个站的商品页上出现过表格,另外35个站整站零表。 这个数字第一眼看着离谱,细想又很合理。商品页是模板生成的,模板里的字段是键值对,前端渲染成什么样全看设计稿。设计稿上没画表格线,工程师就不会去写table。而table这个标签在前端圈子里背了二十年的坏名声——早年拿它做页面布局留下的心理阴影,到现在还在起作用,尽管MDN的table元素说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/table)里写得清清楚楚,它就是用来放二维数据的。 顺带说一句反直觉的:老式CSS表格布局其实已经基本绝迹了。计算样式是table或table-cell的非表格元素,258页里只在4页上出现过,占1.6%。大家不是在用旧办法画表,是压根不用“表”这个概念在想问题。 ## 这些表本身有多大 110张表的规模分布挺能说明问题:行数中位数6行,列数中位数3列,四分之三的表不超过7行4列。最大的一张35行,最宽的一张25列——前者是reebok的中性鞋码指南,后者是aloyoga那张把男码、女码、袜码和英码摞在一起的鞋码对照,7行25列,横过来铺了一整屏。 另一头也值得看。110张里有18张的格子总数不超过2个,占16.4%,基本可以判定是模板留下的空壳。mackweldon那几个最典型:一个1行1列的table,唯一那个格子里写着一个句点,上面挂着标题“Transfer History”。这类东西在体检工具的报表里会被算成“页面含表格”,实际上一个字的信息都没有。做站内审计时如果只数标签个数不看内容,这一格就会把结论抬高一大截。 ## 那20个有表的站,表都是些什么表 把110张表按它最近的那句说明文字归类,前几名很有意思: - 出现最多的是配送时效表——“The delivery time for items is as follows”,10张; - 其次是床品尺寸对照,7张; - 再往下,5张是隐私政策里那张“我们收集哪些个人信息”的表格; - 营养成分表8张,来自食品饮料类的站; - 真正写着size chart、size guide、how to measure的,加起来不到三分之一。 allbirds是个典型。它的商品页上确实有一张table,7行2列,写得规规矩矩,还带thead——内容是加州消费者隐私法要求披露的个人信息类别。这个站唯一的一张标准表格,跟鞋没有半点关系,而且它是display: none的。至于鞋码,在另一个地方,下面会说到。 ## 那110张表,用户真能看见的有几张? 把每张表沿着祖先链一路查上去,逐层看计算样式、hidden属性、aria-hidden、未展开的details与dialog,结果是:110张表里,渲染完成那一刻真正可见的只有24张,占21.8%。 状态 | 张数 | 占比 | 机器读不读得到 | 可见 | 24 | 21.8% | 读得到 | display: none | 53 | 48.2% | 在DOM里,读得到,但权重存疑 | visibility: hidden | 24 | 21.8% | 同上 | aria-hidden="true" | 6 | 5.5% | 辅助技术直接跳过 | hidden属性 | 3 | 2.7% | 同上 | 另外一个角度:110张表里有67张的祖先容器带着modal、drawer、popup这类类名,占60.9%。也就是说,商品页上的表格,六成活在弹窗和抽屉里,等着用户去点那一下。 藏起来本身不是错。尺码表放在弹窗里是合理的产品决策,商品页首屏塞不下那么多行。真正要紧的是后半句——它在不在DOM里。在,机器至少还有机会;不在,那就是另一回事了。 ## 逐站看,两头的差距比平均值大得多 把这110张表按站摊开,会看到两种截然相反的做法并排站着。 站 | 表总数 | 其中可见 | 尺码语境 | 这个站在干什么 | monos | 10 | 0 | 10 | 尺码表写得很全,一张都不露面 | reebok | 10 | 0 | 10 | 同上,且网格里混进了CSS选择器 | brooklinen | 9 | 0 | 9 | 床品尺寸对照,全在抽屉里 | baseus | 11 | 1 | 1 | 规格表堆了11张,只露一张 | drinkolipop | 8 | 8 | 0 | 营养成分表,全部直接可见 | wusthof | 5 | 5 | 0 | 刀具规格,全部直接可见 | thirdlove | 0 | 0 | 0 | 13张表图,一张真表格都没有 | 前三家不是不重视尺码,恰恰相反——它们是样本里尺码信息写得最细的几家,只不过整套都收进了弹窗,可见数是零。drinkolipop和wusthof正好反过来,表不算多,但全在明面上。可见与不可见的分界,跟这个站用不用心几乎没有关系,只跟它的前端组件怎么写有关系。 thirdlove是第三种:13张图命中表图判据,真表格零张,而且页面上还挂着一对名叫size-table-scroll-more-arrow.svg的左右箭头。也就是说,那张“表”是一张需要横向滚动去看的图片——连横向滚动这个交互,都是围着图片重新造了一遍。 ## 写着尺码指南的那个入口,点进去到底有没有表? 这是整台实验最想问的一格。258页里有129页带尺码指南入口,正好50.0%,分布在37个站上。我把这129页按“入口背后到底是什么”分了六类: 入口背后是什么 | 页数 | 占比 | 真表格,而且在尺码语境里 | 28 | 21.7% | 网格伪表 | 16 | 12.4% | 整张图片 | 11 | 8.5% | 一份PDF | 4 | 3.1% | 有表,但那表跟尺码无关 | 7 | 5.4% | DOM里什么都没有 | 63 | 48.8% | 近一半。decathlon的5个商品页每一页都挂着两三个“Size Guide”的按钮,DOM里零表、零网格、零图。rothys、tentree、untuckit、outdoorvoices、gymshark也是同一个形态:入口在,内容不在。 这一格的解释我原本写错了一次,后面那节的对照实验把它纠正了过来:这些页面上的尺码表,有一部分确实是点了才去取的,但更多的是别的原因。Google的JavaScript SEO基础 (https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics)里反复强调的“渲染之后才有的内容要付出额外成本”是其中一种,而交互触发的那一类比滚动触发的更难拿到。具体是哪一种,得替用户点一下才知道。 ## ice-watch把尺码表做成了PDF 4个页面的入口指向的是watches-sizes-guide.pdf。这个做法在手表、家具、B2B工业品里并不少见——设计部门出图,市场部门导成PDF,挂上去就算完事。问题是PDF的文字层是另一套东西,能不能被读出来取决于它是怎么生成的,PDF怎么做成无障碍又能长期归档 (https://zhangwenbao.com/pdf-accessibility-tagged-reading-order-pdfa-archiving-compliance.html)里拆过标签结构与阅读顺序这一层,那页规格书在屏幕上是好好的泰语 (https://zhangwenbao.com/minor-language-pdf-text-layer-extraction-failure.html)那篇里还有更糟的一种:屏幕上完全正确,复制出来是另一串字符。 ## 不用table,那张表是拿什么画出来的? 剩下的三类载体,一类一类看。 ## 网格伪表:行和列只存在于渲染结果里 先交代判据是怎么定的。MDN的display属性 (https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/display)把网格和表格列成两种彼此独立的显示模式:设成网格的元素会按你写的列数把子元素排成矩阵,但这个矩阵只存在于布局阶段,DOM里那些子元素依然是平级的兄弟节点。我把“至少3列、至少6个子元素”当作伪表的门槛,宽了会把导航菜单也算进来,窄了会漏掉小尺码表。 258页里有126页至少有一个符合条件的网格容器,其中落在尺码语境里的有30页。allbirds那张鞋码对照就是这么做的:一个display: grid的容器,7列,14个子元素,第一行是男码8、8.5、9一路到11.5,第二行是对应的女码。在屏幕上它是一张两行七列的对照表;在DOM里它是14个并排的div,谁跟谁一组,只写在CSS的列数里。 aloyoga更彻底一点,27个格子3列,每个格子里写着“3M/4.5W”这样的组合值,男码女码被压进了同一个字符串。fahertybrand的腰围网格是36个格子6列,第一行连着三个28,第二行三个29——那三个28分别属于三个不同的裤长,可这层归属在DOM里没有任何痕迹。 reebok那组更值得说。它的尺码网格是visibility: hidden的,27个格子4列,而第一个格子里的文字是.sliderow__links.g——一段CSS选择器漏进了DOM,被当作内容渲染了出来。眼睛看不见,因为整块是隐藏的;机器读得到,而且会把它当成这张表的第一个数据。 这个门槛也确实会误伤。mackweldon那9个被判成尺码网格的容器,点开看其实是变体选择器——6个格子,写着S、M、L、XL、XXL加上“Out of Stock”,是让人挑码的,不是给人查尺寸的。所以本文把网格伪表的严格判据(类名或标签里明写size chart、size guide这类词)和宽判据(只要出现size、fit这类词)分开算,严格口径下命中的是18页,宽口径是30页。这12页的差额,就是“挑码的控件”和“查尺寸的表”之间的模糊地带。 要补一句公平话:ARIA的table角色 (https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/table_role)本来就是给这种情况准备的,一个div加上role="table"、role="row"、role="cell",语义可以补回来。这55个站上,我一个都没数到。 ## 整张图片:13页命中,替代文本各写各的 命中“表图”的有13页、8个站。同样是把尺码表做成图,替代文本的写法差得非常远: - casper把整张床垫尺寸图的替代文本写成了“King Dimensions 76"x80", California King Dimensions…”——数据本身写进了alt,这是全样本里唯一一家这么干的; - italic的浴巾尺码指南是一张2570×4289的PNG,alt写着“Size Guide”,等于告诉机器“这里有张图,内容不告诉你”; - brooklynbedding的床垫尺码图,alt是“FAQ Image”; - liquiddeath的T恤尺码图,alt是商品名“Tatum Henderson #66 Official Tee”; - materialkitchen那两张尺寸图,alt="",按规范这是在声明“这是装饰图,请忽略”。 这几行差别,是图片alt能帮上什么忙、帮不上什么忙 (https://zhangwenbao.com/image-alt-text-ranking-factor-myth.html)那篇结论最直接的一次落地:alt对网页排名帮不上什么,但当图里装的是本该可读的数据时,它是唯一的出口。想批量查一遍自己站上的alt,可以用一页图片的alt与属性批量体检 (https://zhangwenbao.com/image-alt-checker-batch-audit-cls-accessibility-guide.html)那套流程。 ## 还有一类载体,几乎没人拿它装尺码 方法那一节列了五类载体,前面说了四类,第五类是定义列表。dl加dt加dd是HTML里唯一天生就把“名字”和“值”绑在一起的结构,写“材质:美利奴羊毛”这种一对一的属性,它比表格更合适。258页里有43页出现过dl,占16.7%,来自9个站。 但仔细看会发现,这些dl基本没有一个是拿来装商品属性的。它们绝大多数出自导航菜单、页脚链接组和第三方组件的模板,最夸张的一页里有259个dl、1749个dt——那是一整套多级导航。MDN的dl元素说明 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dl)里专门提醒过不要拿它做布局,可现实里它最常见的用途恰恰就是布局。真正该用它的那个地方——商品的材质、产地、重量、保养方式——反而清一色是div套div。 ## 同一个页面等5秒和等25秒,量出来一样吗? 这一问必须做,不然前面的数字全是浮的。做法很笨:挑30个站各一页,同一个浏览器标签,等5秒量一次,再等20秒量第二次,中间滚到底再滚回顶。 结果是30页里有3页至少一项读数变了,占10.0%。aloyoga那一页第一次量到0张表,第二次量到1张——那张7行25列的尺码对照表是在第5秒之后才被注入的,同时正文字符数从3566涨到5540。brooklinen从4张变5张,jackery那张表的数量没变,但从不可见变成了可见。 10%听起来不高,可这三页恰好都是有尺码表的那类。反过来说,那些一张表都没有的页面,等多久都还是零,两次一致得毫无信息量。真正会抖的,恰恰是你想量的那一部分。 还有更细的一种。italic的4个商品页被两条采集通道各跑了一次,两次的正文字符数一模一样,但尺码指南入口一次数到0个、一次数到5个。页面主体是同一份,挂在上面的那几个按钮是异步补上去的。 所以本文所有数字的正确读法是:它们是等大约7秒、滚动一次之后的下限。真人拿着手机在弱网下打开,看到的多半更少;一个只抓首字节的爬虫,看到的更少。这条教训在渲染对比这件事 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)上翻来覆去出现过,量出来的差异有多少是页面真的不一样、有多少是自己的尺子在抖,必须先分开。 ## 不点那个按钮,表在不在页面里? 第二组自基线,是替用户点一下。30个页面里成功点开29个,点完等3.5秒再量一次。这一组把我原来的猜测改掉了一半。 先说数字:29个页面里,点完之后读数变了的只有6个,占20.7%。这6个里真正“点了才出现”的只有两个——rothys点开之后凭空多出3张表,而且全部可见;fromourplace多出1张。另外三个变的不是表的数量,是可见性:表一直躺在DOM里,点击只是把盖在上面的那层样式掀开。 还有一个是反过来的:monos点完之后,原本DOM里那2张尺码表反而不见了——那个按钮触发的是一次视图切换,旧的表格节点被整块替换掉了。 最要紧的是剩下那批:29个页面里有13个,替它点完之后DOM里依然既没有表也没有网格。这13个里有几个是我的判据认错了入口——harrys那个按钮上的文字其实是“Full-Size (18oz)$8.00”,那是商品规格不是尺码指南;ice-watch指向的是PDF,点击当然不会在页面里长出表来。但decathlon、gymshark、peakdesign、liquiddeath这几个是实打实的:入口在,点了,什么都没出现。它们要么把内容放在另一个地址里,要么需要比合成点击更真实的用户手势。 所以前面那48.8%不是一句话能解释的,它至少混着四种情况:真的要点才加载、点了也加载不出来、内容在另一个页面上,以及我这把尺子本身认错了入口。能确定的只有一件事:对一个抓完HTML就走的程序来说,这四种的结果一模一样。 顺带说个操作上的坑,写给要复现这套的人:用自动化框架的标准点击方法会大面积超时,因为它要等元素“可交互”,而这些站上同名的隐藏元素往往排在前面。换成在页面里自己找到那个可见的元素再触发点击,29比30的成功率立刻就有了。 ## 原始HTML里有几张表,浏览器里有几张? 顺手做的一层对照:在页面上下文里再请求一次同一个地址,拿到服务器发出的那份原始HTML,数里面的table标签,跟渲染完成后的DOM比。 258页里88.0%两边一致;7.0%的页面渲染之后表变多了,说明是JS注入的;还有5.0%反过来,原始HTML里有、渲染完反而没了——前端框架接管之后把服务端那份结构换掉了。有11页原始HTML一张表都没有,DOM里才出现。 这几个数字看着不大,但它们决定了一件事:你用不同的工具审自己的站,会得到不同的答案,而两个答案都不算错。拿源码查看器看是一回事,拿爬虫抓是一回事,拿浏览器开发者工具看又是一回事。这和JS渲染的页面Google抓不到时该从哪查起 (https://zhangwenbao.com/javascript-rendering-seo-csr-ssr-debugging.html)是同一类问题,只是这次被检查的对象是一张表。 ## 这件事到底影响谁? ## 搜索这一侧 Google早就不给表格单独出富媒体结果了,所以别指望写了table就能多一块展示位。真正的收益在别处:一张有表头的表格,是这个页面上信息密度最高、最容易被摘出来当答案的一段。主体内容占比 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)这件事在商品页上尤其难看——商品页本来就没多少字,尺码表往往是整页字数最多、最独有的一块。把它做成图,等于把这一页最不可替代的内容从可读文本里删掉了。产品详情页怎么做出唯一内容 (https://zhangwenbao.com/product-detail-page-onpage-seo-unique-content-engineering.html)那篇里讲的“摆脱供应商文案”,其实这张表就是现成的答案。 ## AI购物这一侧 用户问“我平时穿US 9,这双该选几码”,模型要么能从页面上取到那一行,要么就得去别处找。智能体读的是无障碍树,不是页面截图 (https://zhangwenbao.com/ai-agent-accessibility-tree-not-pixels.html)这个判断,在尺码表上兑现得最直接:一张display: grid的伪表在无障碍树里是一堆平级的文本节点,图片里的表连节点都没有。AI代理替用户逛店下单 (https://zhangwenbao.com/agentic-commerce-brand-visibility-blindspot.html)的时候,这一格取不到,它就换一家。 ## 客服这一侧,账最好算 保哥手上有个做宠物出行装备的客户,去年把尺码问题的客服会话捞出来数过一遍:问“这个尺寸我家狗能不能用”的会话,占了售前咨询的两成出头。他们的尺码对照原本是一张放在弹窗里的图,客服每次回答都要重新打一遍数字。后来只做了一件事——把那张图旁边补了一份可选中的表格,客服可以直接复制粘贴。会话数没有明显下降,但单次会话的处理时长短了一截,因为不用再手打了。这不是SEO收益,是运营侧顺手捡的,可它恰好说明同一件事:能不能被复制、被摘取、被引用,取决于那份数据是不是以文本的形式存在。 ## 读屏用户这一侧 这一侧最直接。网站无障碍那18个改动 (https://zhangwenbao.com/website-accessibility-seo-optimization-guide.html)里,表格语义是投入产出比最高的一项之一:一张写了表头的表,读屏软件念到某一格时会先报出它属于哪一行哪一列;一张没写的,念出来就是一串孤零零的数字。语义化HTML那8类标签 (https://zhangwenbao.com/semantic-html-tags-seo.html)讲的是同一件事的一般形式,表格只是其中最容易被忽略的一类。 ## 自己站上怎么查,查完改哪里? 不用搭实验台,四步就够: - 打开一个有尺码的商品页,什么都别点,直接在控制台里数document.querySelectorAll('table').length。为0,说明尺码表不是表格做的;不为0,接着看第二步。 - 把结果里每一张表的可见性查一遍,看它是不是在弹窗里、是不是display: none。在DOM里就行,不必强求首屏可见。 - 点开尺码指南,再数一次。数字变了,说明内容是点击之后才来的,这是最需要改的一类——把它挪进初始HTML,用折叠而不是用异步请求。 - 如果尺码表是一张图,最低成本的补救不是重做,是把关键数据写进替代文本,像casper那样。彻底一点就是在图旁边补一份可读的表格,图留着给人看。 改的顺序,得先看第三步查出来的是哪一类。如果点完之后DOM里还是空的,那才是最该先动的一档——内容根本没进这一页,加载时机、样式、语义都无从谈起,得先把它搬回来。如果点一下就出来了,把它挪进初始HTML即可,不改样式、不改设计,只改加载时机,是这几步里最便宜的。如果表一直躺在DOM里只是被样式盖着,其实已经及格了,把网格换成真表格是下一档,这一步要动前端组件,但同一套组件全站复用,改一次全站受益。替换图片放最后。 什么时候可以不查?如果你的品类根本没有尺码概念——食品、香氛、订阅制服务——那这一层确实不用管。样本里drinkolipop的8张表全都可见、全都是营养成分表,wusthof的5张表也全可见,是刀具规格。它们没有尺码表,但它们把该表格化的东西表格化了,这就已经比一半的服装站做得好。 ## 常见问题解答 ## 把尺码表从图片改成HTML表格,能带来排名提升吗? 直接的排名提升不要指望。Google已经取消了表格类富媒体结果,写不写table本身不是排名因素。真正的收益有三处:这一页的可读文本变多且更独有;AI助手回答尺码问题时能取到你的数据;读屏用户能听懂。第三条在部分市场还是合规要求。 ## 尺码表放在弹窗里,会不会被搜索引擎当成隐藏内容? 不会被当成作弊,前提是它在初始DOM里、只是被样式收起来。真正有风险的是另一种:内容压根不在HTML里,等用户点击才去请求。那种情况下不是权重折扣的问题,是根本没有内容可评估。 ## 用div加role="table"补语义,和直接用table标签等价吗? 语义上接近,工程上不等价。ARIA角色要求把role="table"、role="row"、role="cell"甚至role="columnheader"成套写全,漏一层就断,而且浏览器不会替你兜底。原生table把这些默认给全了。除非布局上确实用不了表格,否则没必要绕这一圈。 ## 怎么快速判断我站上的尺码表是不是点了才加载? 打开商品页,先不点任何东西,在控制台跑一次表格计数并记下数字,然后点开尺码指南,再跑一次。两个数不同,就是点击触发的。也可以直接看服务器返回的原始HTML里有没有那几个尺码关键词。 ## 集合页和分类页上要不要也放尺码表? 不需要,那一层的信息任务不一样。尺码属于单品级别的属性,放在列表页只会稀释主体内容。列表页该解决的是另一批问题,商品列表页那97条准则 (https://zhangwenbao.com/product-list-guidelines-scoring-selection-bias.html)里已经排过序。 ## 这次的结论只适用于服装类目吗? 不。样本里家具、床垫、箱包、手表、厨具都出现了同样的形态——凡是需要给出尺寸对照的品类,都有把它做成图或做成网格的倾向。反倒是食品饮料类因为要合规披露营养成分,表格化程度最高。 ## 权威参考资料 ## 页面体积实测46个电商站,4个的商品链接谷歌根本没读到 - URL:https://zhangwenbao.com/html-byte-budget-crawl-truncation-audit.html - 分类:技术SEO - 发布:2026-08-07 | 更新:2026-08-07 - 摘要:抓取截断从不报错:46个电商站实测,4个已越线,最紧的一个余量只剩23字节;而丢什么取决于排序,不取决于超了多少。撑爆额度的是前端框架内联的那份数据副本。 - 关键词:结构化数据,技术SEO,页面性能,DTC转化率优化 > **TLDR**:摘要:一个页面超出抓取上限50%却一样东西都没丢,另一个只超27%就丢光了全部结构化数据——这两件事同时出现在保哥这次的实测里。46个真实电商与建站平台的页面逐字节量完,中位数吃掉46.4%的额度,4个越线,7个用掉八成以上,最紧的那个组合装页余量只剩23字节。真正吃掉额度的既不是商品也不是文案,是前端框架为了在浏览器端接管页面而内联的那份数据副本;实测里最大的一个这样的标签,比整条上限还长287272字节。而从头到尾,没有任何一个环节会报错。 > 摘要:一个页面超出抓取上限50%却一样东西都没丢,另一个只超27%就丢光了全部结构化数据——这两件事同时出现在保哥这次的实测里。46个真实电商与建站平台的页面逐字节量完,中位数吃掉46.4%的额度,4个越线,7个用掉八成以上,最紧的那个组合装页余量只剩23字节。真正吃掉额度的既不是商品也不是文案,是前端框架为了在浏览器端接管页面而内联的那份数据副本;实测里最大的一个这样的标签,比整条上限还长287272字节。而从头到尾,没有任何一个环节会报错。 ## Googlebot为什么会读到一半就停下来? 2026年3月31日,谷歌搜索团队的Gary在搜索中心博客上写了一篇罕见的内部机制文,题目是《Googlebot内幕:把抓取、取回和我们处理的那些字节讲清楚》 (https://developers.google.com/search/blog/2026/03/crawler-blog-post)。这篇文章里最值得反复读的不是任何一条优化建议,是它对一个动作的描述方式。 ## 它不拒绝,它只是停下 原文的句子是这样的:如果你的HTML文件大于2MB,Googlebot不会拒绝这个页面,它会在正好2MB的位置停止取回。这句话里有两个动词,一个是不会拒绝,一个是停止。它们描述的是同一次抓取,但落到你这边是两种完全不同的处置。 这套流程完整走一遍是几个独立的阶段,搜索引擎抓取和渲染DOM分几步 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)那篇把每一步会在哪里丢内容拆开讲过,本文说的截断发生在第一步。 拒绝会留下痕迹。抓取失败会在Search Console的抓取统计里变成一条曲线,会在服务器日志里对应一个非200的状态码,会在你的监控面板上触发一次告警。停下不会。停下之后,前面那部分字节被原样交给索引系统和网页渲染服务,而且是当作完整文件交上去的。 > 会报错的系统是在替你干活。停在半路而不报错的系统,只是安静地把你的一部分内容从这个世界上取消掉了。 ## 被取消的那部分到底怎么样了 Gary把这件事写得很干脆:2MB阈值之后的任何字节都会被完全忽略,它们不会被取回、不会被渲染、也不会被索引。三个动词全否,没有留任何余地。 这条上限本身的成因和常规优化步骤,Googlebot抓取2MB限制的8步实战 (https://zhangwenbao.com/googlebot-crawl-limits-2mb-deep-analysis.html)那篇已经讲过,本文不再重复,只补它没覆盖的落点问题。 抓到了不等于进索引,进索引不等于能被搜到,提交了为什么还不收录 (https://zhangwenbao.com/baidu-index-crawl-mechanism-why-not-indexed.html)那篇把抓取与索引之间的几道关系理了一遍,可以对照着看。 注意这里的措辞不是“不会被排名”或者“权重较低”。是不存在。你的第481个商品链接,你的评价结构化数据,你的面包屑,如果它们排在第2097153个字节上,那么在谷歌的世界模型里,你这个页面从来没有过它们。 ## 2MB不是一条通用的线 同一篇文章里还给了另外几个数字,它们合在一起才构成完整的图景。 要看清楚到底是哪个客户端在抓你、各抓了多少次,唯一可靠的地方是服务器日志,读懂Googlebot抓取与预算浪费 (https://zhangwenbao.com/log-analyzer-crawl-budget-googlebot-guide.html)那篇给了完整的读法。 抓取客户端 | 单个网址的字节上限 | 影响的产品面 | Googlebot(网页) | 2MB | 谷歌搜索、Discover及全部搜索功能 | Googlebot抓PDF | 64MB | 同上,PDF单独放宽32倍 | 未单独指定上限的爬虫 | 15MB | 不限内容类型,走默认值 | 图片与视频类爬虫 | 各自不同,跨度很大 | 取决于它在为哪个产品取内容 | 取favicon的抓取 | 官方原话是“非常低” | 站点图标 | 这张表里藏着一个很少被讲的事实:同一个网址,不同的抓取客户端看到的长度不一样。你那个2.4MB的分类页,对谷歌搜索是被切掉一截的,对某个走15MB默认值的客户端却是完整的。你没法用一次测试覆盖所有情况,因为它们本来就在读不同长度的同一份文件。 ## 它是一个平台,不是一个机器人 这篇文章顺手纠正了一个流传二十多年的误解。Gary写道,21世纪初谷歌只有一个产品,所以只有一个爬虫,Googlebot这个名字就这么留了下来;而今天的Googlebot只是一个类似集中式抓取平台的东西的使用者之一。 日志里那个自称Googlebot的请求也不一定真的是它,每5次Googlebot抓取就有1次IP不属于谷歌 (https://zhangwenbao.com/server-log-collection-structured-searchable.html)那篇实测过反向验证该怎么做。 你在日志里看见Googlebot,你看到的只是谷歌搜索。谷歌购物、AdSense还有几十个别的客户端,全都走同一套底层基础设施,只是用着不同的爬虫名字。字节上限就是每个客户端各自设置的一项参数,和用户代理字符串、和它在robots.txt里认哪个令牌,摆在同一个配置块里。 ## HTTP响应头也算在这2MB里 这是原文里一句很容易被跳过的补充:这个限额包含HTTP请求头。也就是说预算表的第一行不是你的HTML,是你自己平时根本不会去看的那几KB。 响应头这一层还有别的账要算,服务器把没改过的页面对爬虫重发了几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)那篇讲的是条件请求没配好会怎样浪费掉抓取资源。 保哥顺手量了一下手上这批站点的响应头。22个站的头部字节均值是2938字节,最大的一个是webflow.com的13975字节。放在2MB这个尺度上,最大的那个也只占0.67%,看起来无关紧要。但如果你的余量本来就只剩两位数,这几KB就是那个把你推过去的东西。 ## 渲染只能执行爬虫真的取到的那部分代码 抓取拿到字节之后交给网页渲染服务,也就是常说的WRS。原文提醒了两件事,第二件比第一件重要得多。 渲染这一层对不同的抓取方有不同的结果,CSR、SSR与ISR的引用率实测 (https://zhangwenbao.com/js-rendering-ai-crawler-citation-rate-csr-ssr-isr-divergence.html)那篇量过几种渲染模式在被引用上的真实差距。 第一件:HTML里引用的每一个资源,除了媒体、字体和少数特殊文件,都会由WRS用Googlebot单独抓一次,它们各有自己的字节计数器,不计入父页面的额度。所以把重的东西挪成外链文件是真的有用,不是心理安慰。 第二件:WRS只能执行爬虫实际取到的那部分代码,而且它是无状态运行的,请求之间会清掉本地存储和会话数据。这两条叠在一起会产生一个很难排查的后果——你的页面在浏览器里跑得好好的,是因为浏览器拿到了完整的文件,而WRS拿到的是被切过一刀的版本。 ## 一个容易被误读的地方 有人会把“外部资源各有自己的额度”读成“把东西挪到外部文件就等于免费”。不是这样的。挪出去只是让它不占父页面的份,它自己那份仍然有上限,而且WRS要不要去取它、什么时候取,是另一套逻辑。 正确的理解是:挪出去解决的是父页面被截断的问题,不是解决那份内容一定会被读到的问题。如果你把结构化数据挪进一个外部脚本再动态注入,你等于把一个确定的问题换成了一个不确定的问题。 所以本文全程建议的是“往前排”而不是“挪出去”。往前排是把重要的东西放进那段一定会被读到的字节里,这是所有做法里唯一一个不引入新变量的。 ## 这条线还会变 原文结尾留了一句:这个限制并非一成不变,随着网页不断变大(或者变小,希望是变小)它可能会随时间改变。这句括号里的自嘲值得记一下,因为它说明谷歌自己也知道趋势在往哪个方向走。 谷歌抓取侧的规则历史上改过好几次口径,移动优先索引与Googlebot渲染机制的演变 (https://zhangwenbao.com/mobile-first-indexing-mechanism-googlebot-rendering-evolution-survival.html)那篇复盘过一次改动落到站点上是什么体感。 > 一条会变的线,你不能踩着它做优化。你只能给它留余量,而余量的大小取决于你多久才会发现自己越了线——按本文后面的实测,答案通常是永远不会。 ## 那15MB的默认值意味着什么 官方给出的“未指定上限的爬虫默认15MB”这一条,实际上是在说抓取平台的配置结构:字节上限是每个客户端自己填的一个字段,不填就走默认。 顺着这个结构往下想会得到一个有点冷的结论:谷歌搜索这个客户端,把这个字段填成了全平台默认值的七分之一。这不是疏忽,是搜索侧对网页文档长度的一个判断——他们认为2MB足够容纳任何一个合理页面的全部内容。 这个判断在2026年是不是还成立,本文的实测给了一个不太好看的答案:8.7%的头部电商页面已经不在这个假设里了。 ## 为什么这件事该由做转化的人来管 把抓取上限放进转化率优化的话题里,第一反应会觉得串台了。但这两件事在同一个文件里争同一份预算,而且争抢的原因恰恰是转化侧的诉求。 搜索侧和体验侧本来就该并成一条链来看,搜索体验优化SXO把SEO、UX和CRO拧成一条链 (https://zhangwenbao.com/sxo-search-experience-optimization-seo-ux-cro.html)那篇讲的是这种跨界协作的组织方法。 首屏要快,所以关键CSS被内联进HTML;交互要跟手,所以服务端渲染完还要把数据再内联一份供浏览器接管;个性化推荐要即时,所以一整套商品数据被提前塞进页面。这三件事全是为了转化,也全是在往同一个2MB的桶里倒东西。 更麻烦的是它们的收益你看得见——首屏时间、交互延迟、加购率,都在报表上;它们的代价你看不见,因为代价发生在一个不产生任何错误信号的地方。 ## 这类失败为什么特别难被抓到 常见的技术故障都有一个共同点:它们会让某件事变得不成立。接口挂了会返回500,证书过期会让浏览器拦截,脚本报错会在控制台留下红字。这些都是断言失败,断言失败会喊。 同样是不报错的故障,人机验证屏被谷歌当正文索引 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)那次事故里页面照样返回200,只是搜索引擎读到的是另一份内容。 截断不是断言失败,它是一次成功的部分完成。系统按设计工作,返回了它承诺的东西,只是那个东西比你以为的短。没有任何一层会为“比预期短”这件事负责,因为没有任何一层知道预期是多少。 ## 先说清楚它不是什么 它不是抓取预算问题。抓取预算讲的是Googlebot愿意在你的站上花多少次请求,是站级别的资源分配;字节上限是单次请求内部的截断,是页面级别的。两者可以同时存在,也可以互不相关。 抓取预算是站级别的另一件事,分面导航产生的海量URL怎么治理 (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)那篇讲的才是预算被稀释的典型场景,跟本文的页面级截断不是一回事。 它也不是渲染超时。渲染超时是WRS等不到你的脚本执行完,那件事发生在拿到字节之后;截断发生在拿字节的时候,等于渲染那一步收到的原料就是残缺的。 它更不是robots.txt或者noindex。那两者是你主动做出的排除决定,有明确的语义、有专门的报告位置、也有人为它们负责。截断没有决定者。 ## 46个真实电商站的字节结构实测 官方文档给了一条线,但没有告诉你线在哪个位置、你离它有多远。保哥决定自己量一遍。 ## 为什么必须自己量 因为这条线的所有已知信息都是定性的。官方说了上限是多少,没说行业实际分布在哪;说了超出会被忽略,没说超出的比例有多高;说了要把关键元素放在前面,没说现在有多少站没这么做。 行业基准这种东西最怕拿来直接套,转化率、排名周期、流量占比该对标多少 (https://zhangwenbao.com/seo-industry-benchmarks-data-reference-guide.html)那篇整理过一批公开基准以及它们各自的适用边界。 这些空白不能靠推测填。一个只在文档里存在的风险,和一个八分之一的头部站点已经踩上去的风险,值得投入的资源完全不同,而两者的区别只有量一遍才知道。 ## 样本怎么选的 选站的标准只有一条:跟看这篇文章的人在同一个赛道上。最后落到四类。 第一类是头部DTC品牌的独立站,包括Allbirds、Gymshark、Glossier、Bombas、Away、Brooklinen、Ruggable、Chubbies、Mejuri、Oura、Lovevery、Article和Purple。这批站的共同点是设计精良、技术栈新、有专职团队维护。 第二类是面向出海卖家的大型电商与品牌站,包括SHEIN、Anker、Jackery、EcoFlow、Uniqlo、IKEA、Target和Walmart。第三类是建站与营销工具自己的官网,包括Shopify、BigCommerce、Squarespace、Wix、WooCommerce、Webflow、Mailchimp和HubSpot。 第四类是几个做SEO的人天天访问的站,包括Semrush、Ahrefs、Cloudflare、Stripe和PayPal。把这一类放进来是想看看,天天讲技术优化的人自己做得怎么样。 挑样本这件事本身有方法,以消费级3D打印机为例做细分品类数据洞察 (https://zhangwenbao.com/category-geo-insight-method-3d-printer-example.html)那篇把选样、取数和交叉验证的完整流程走了一遍。 页面类型上首页和分类页各抓一份。分类页是重点,因为商品列表页天生就长,而且它在站内链接结构里承担着往商品页分发权重的职责——它被截掉一截,后果是可以直接算出来的。 ## 怎么量的 抓取用的是普通桌面浏览器的用户代理,不伪装成Googlebot。这一点要说明白:伪装成爬虫会拿到某些站专门为爬虫准备的版本,量出来的是另一件事。本文量的是普通访客拿到的那份HTML,也就是绝大多数站点交给Googlebot的同一份。 伪装成爬虫去抓会拿到另一份内容,这件事在5000站爬虫伪造与抓取预算实战 (https://zhangwenbao.com/server-log-file-analysis-seo-crawl-budget-bot-verification.html)那篇里有更完整的说明和验证办法。 每个页面记两个数:一个是加了压缩协商之后服务器实际传输的字节,另一个是解压之后落到磁盘上的字节。后面会看到,这两个数的差别足以改变结论。 剔除规则也写在这里:返回403、429、302且没有跟到最终页面的,以及解压后不足20000字节的(基本是防护页或者跳转壳),全部丢掉。两轮抓取一共75个网址,最后留下46个有效样本。 ## 总体分布长什么样 指标 | 数值(未压缩HTML字节) | 占2MB预算 | 中位数 | 972274 | 46.4% | 算术平均 | 1131569 | 54.0% | 最大值(wix.com首页) | 3148564 | 150.14% | 最小值(semrush.com首页) | 196343 | 9.4% | 电商站的高频坑里有好几个都和页面结构有关,电商SEO最常见错误清单的12类高频坑 (https://zhangwenbao.com/ecommerce-seo-common-mistakes.html)那篇可以当一份对照表用。 中位数和均值分开看是有讲究的,砍掉虚荣指标、定准北极星指标 (https://zhangwenbao.com/vanity-metrics-north-star-omtm-ecommerce.html)那篇讲过一个分布右偏的指标被平均值掩盖会造成什么误判。 中位数46.4%这个数字第一眼看着挺安全,一半的额度都还没用。但请注意它是中位数——意味着有一半的站点比它更重,而且这个分布是明显右偏的:均值比中位数高了7.6个百分点,尾巴全在右边。 ## 已经越过线的有几个 4个,占46个样本的8.7%。 分类页出问题会顺着结构往下传,独立站架构搭错了谷歌爬虫根本找不到你的产品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)那篇讲的就是这种自上而下的连带损失。 页面 | 未压缩字节 | 占预算 | 超出 | wix.com首页 | 3148564 | 150.14% | 1051412字节 | allbirds.com男款分类页 | 2673710 | 127.49% | 576558字节 | anker.com充电器分类页 | 2654871 | 126.59% | 557719字节 | anker.com首页 | 2105560 | 100.40% | 8408字节 | 八分之一强。这个比例比保哥开工前的估计高了不少——动手之前保哥心里的数字大概是二十分之一,而且以为超标的会集中在那些明显做得糙的站上。结果全是行业里被当作范本的品牌。 ## 踩在线上的那一批 比超标更值得看的是紧贴着线的那些。用掉八成到十成预算的一共7个页面。 贴着阈值的数最怕被当成稳定值来用,一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)那篇讲的是同一个指标在不同时段其实量的不是同一件事。 页面 | 未压缩字节 | 占预算 | 剩余余量 | lovevery.com组合装页 | 2097129 | 99.999% | 23字节 | jackery.com首页 | 1975241 | 94.19% | 121911字节 | lovevery.com首页 | 1974154 | 94.13% | 122998字节 | ikea.com美国站首页 | 1827147 | 87.13% | 270005字节 | uniqlo.com美国站首页 | 1770744 | 84.44% | 326408字节 | uniqlo.com男装分类页 | 1769926 | 84.40% | 327226字节 | jackery.com电源分类页 | 1677966 | 80.01% | 419186字节 | > 第一行那个数值得盯一会儿:2097129对2097152,余量23个字节。往这一页上再加一个商品的alt文本,它就过线了。而做这件事的人不会收到任何提示。 23个字节大概是什么概念?一个稍微写得完整点的HTML属性名加上等号和引号就到了。一次A/B测试往页面里塞一个实验标识,一次埋点升级多加一个data属性,一次翻译更新把某个短语从三个词改成五个词,都够。 ## 为什么首页反而不是最危险的 直觉上首页最重,因为它模块最多。实测结果不支持这个直觉:46个样本里,超标的4个中有2个是分类页,紧贴上限的7个里有4个是分类页或者商品列表页。 原因是首页的内容量由设计稿决定,一个轮播加六个模块就是六个模块,不会自己变多;分类页的内容量由在售商品数决定,而在售商品数会随着生意变好一直涨。首页的长度有人负责,分类页的长度没人负责。 ## 关键内容排在第几个字节 页面总长只是一半的故事。另一半是:你最要紧的那几个标签,落在这条时间线上的什么位置。 开发期就把这些位置定死是最省事的,自建站谷歌SEO开发期10大优化要点 (https://zhangwenbao.com/google-seo-considerations-for-website-development.html)那篇讲的正是这一批只在开工时改起来便宜的事。 要把一页里所有结构化数据的位置和字段一次扒清楚,结构化数据审计工具一次扒清五种格式的字段缺漏 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)那篇给了现成的做法。 保哥把每个页面里的标题标签、规范链接、页面描述、Open Graph标签、多语言标注和最后一段结构化数据的收尾位置全部取出来,取其中最靠后的那一个,作为“关键内容落点”。 关键内容落点占预算 | 页面数 | 占比 | 不到1% | 26 | 57.8% | 1%到5% | 6 | 13.3% | 5%到20% | 6 | 13.3% | 20%到60% | 3 | 6.7% | 60%到100% | 3 | 6.7% | 超过100%,已被截断 | 1 | 2.2% | 好消息是压倒性多数的站都把这些东西放在了文档最前面,57.8%的页面在头1%的字节里就把关键标签写完了。这说明行业整体的习惯是对的。 坏消息在最后三行。有6个页面的关键内容落在了预算的20%之后,其中3个越过了60%,1个直接掉到线外。 ## 落点最靠后的那批是谁 页面 | 关键内容落点(字节) | 占预算 | allbirds.com男款分类页 | 2673529 | 127.48% | brooklinen.com首页 | 1451653 | 69.22% | awaytravel.com首页 | 1264313 | 60.29% | awaytravel.com商品列表页 | 1263412 | 60.24% | gymshark.com首页 | 981045 | 46.78% | casper.com首页 | 552107 | 26.33% | squarespace.com首页 | 524711 | 25.02% | 结构化数据的失效方式不止落在线外一种,一个尾逗号就能让整页结构化数据失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)那篇列了几种同样不报错的写法错误。 这几个站的共同点是把结构化数据放在了文档尾部。这个做法本身完全合法,规范里从来没说结构化数据必须写在head里。它只是把一件本来零风险的事,变成了一件跟页面长度绑在一起的事。 Brooklinen那个69.22%尤其值得说:它今天是安全的,因为页面停在1571567字节。可它的安全不来自任何一次决策,来自“页面暂时还没长到那么长”。而页面只会越长越长。 ## 安全和暂时安全的区别 这批数据里最该被记住的分类,不是超标和不超标,是“结构上安全”和“当前数值安全”。 这种当前数值安全的隐性欠账在建站第一年攒得最多,独立站CMS第一年SEO隐性失分排查 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)那篇列了12项跨平台的共有坑。 结构上安全的站,把关键标签写在文档头部,页面再长十倍也不会丢;当前数值安全的站,靠的是页面还没长到那个长度。两者今天的体检报告完全一样,明天的走向截然不同。 26个站的关键标签落在头1%以内,它们属于第一类,这件事对它们永远不会成为问题。剩下那20个站里,每一个都在跟自己的增长赛跑。 ## 一个容易看错的地方 有人会拿总大小的中位数46.4%来安慰自己:一半额度都还没用,慌什么。这个读法漏掉了一件事——中位数描述的是这一批站,不是你那一个站。 拿别人的分布往自己身上套是个通病,把DTC流量打法搬到B2B工业品为什么不灵 (https://zhangwenbao.com/b2b-industrial-seo-vs-consumer-dtc-playbook-not-transferable.html)那篇讲的就是这种迁移失败。 而且分布本身有很强的品类特征。首页普遍比分类页轻,纯内容站普遍比商品站轻,用传统模板渲染的普遍比用现代前端框架的轻。你要对比的不是这46个的中位数,是跟你技术栈和SKU结构最像的那两三个。 ## 顺带量到的一件小事 抓取过程中有9个网址返回了403,全部来自那些启用了严格机器人防护的品牌站。这一点跟本文主题无关,但值得提一句:这些站对普通爬虫的防护做得很紧,而Googlebot走的是另一套通道,两者的体验完全不同。 那些403来自机器人防护,要不要拦、拦到什么程度是个单独的题,robots加UA加WAF三层选型框架 (https://zhangwenbao.com/block-ai-bots-robotstxt-waf.html)那篇给了取舍方法。 这也是本文样本量止步46的原因。原计划的75个网址里,扣掉403、跳转未跟到底和防护壳,最后能拿到真实HTML的就这么多。把这个数字如实写出来,比补几个不相干的站凑整要诚实。 ## 超过2MB的页面,到底丢了什么? 知道谁超标了没有用,得知道超标之后具体损失了什么。保哥把4个超标页面按截断点切成两段,数了数落在线外的东西。 ## Allbirds男款分类页:丢掉三分之一的商品入口 这一页总长2673710字节,截断点落在预算用尽的位置,也就是文件的78.4%处。 商品列表页该挂哪几种结构化数据是有定论的,Shopify怎么给页面加结构化数据以及128种类型怎么选 (https://zhangwenbao.com/shopify-schema-seo-guide.html)那篇给了选型清单。 元素 | 整页总数 | 截断点以内 | 被切掉 | 带href的链接 | 288 | 191 | 97个,占33.7% | 结构化数据段 | 1 | 0 | 全部 | 图片标签 | 140 | 77 | 63个,占45.0% | 97个链接。这一页是男款商品的分类页,被切掉的那97个链接里绝大部分是商品卡片上的入口。对Googlebot来说,那些商品在这一页上没有入口——它们可能还能从站点地图或者别的分类页进去,但从这个理应最相关的页面进不去。 更要命的是那唯一一段结构化数据。它的起点在2670014字节,也就是预算的127.3%处,比截断点还要靠后57万字节。这一页的结构化数据在谷歌那边等于没写。 保哥把截断点那128个字节的原文取出来看了看,正好卡在一个商品卡片的链接标签中间,属性还没写完。Googlebot拿到的是一个从中间被剪断的HTML片段,连闭合标签都没有。 ## Wix首页:链接丢了三分之二,结构化数据反而安全 这一页是本次样本里最长的,3148564字节,超出上限50.14%。 面包屑既是链接又是结构化数据,两头都受截断影响,面包屑导航的四种类型与结构化数据实操 (https://zhangwenbao.com/seo-breadcrumbs-types-schema-implementation.html)那篇讲了它该怎么放。 元素 | 整页总数 | 截断点以内 | 被切掉 | 带href的链接 | 158 | 55 | 103个,占65.2% | 结构化数据段 | 4 | 4 | 0 | 图片标签 | 148 | 20 | 128个,占86.5% | 它的4段结构化数据全部落在预算的15.3%到15.4%之间,安安稳稳地在线内。但它的链接丢了将近三分之二,图片丢了86.5%。截断点落在一段内联SVG的路径数据中间——那是一个图标的矢量描述。 这里出现了一个很有意思的对照:Wix超得比Allbirds更多,结构化数据却是安全的;Allbirds超得少一些,结构化数据却全丢了。 ## Anker两个页面:超标了,却什么都没丢 Anker的分类页2654871字节(超26.59%),首页2105560字节(超0.40%)。按理说前者的处境应该和Allbirds差不多。实际结果是: 同一件事在两套口径下给出相反结论并不罕见,两套报表算出相反的结论而且两套都没算错 (https://zhangwenbao.com/product-page-recommendation-attribution-mismatch.html)那篇拆过一个结构非常像的案例。 页面 | 链接总数/线内 | 结构化数据总数/线内 | 图片总数/线内 | anker.com充电器分类页 | 87 / 87 | 2 / 2 | 28 / 28 | anker.com首页 | 179 / 179 | 2 / 2 | 113 / 113 | 一个都没丢。两个页面的结构化数据分别落在预算的0.1%和0.2%处,链接和图片标签全部排在文档前部。它们超出的那五十多万字节里,装的是别的东西。 > 四个页面都越了线,超出幅度分别是0.40%、26.59%、27.49%和50.14%。受伤程度却完全不按这个顺序排:超得最少的什么都没丢,超得最多的结构化数据完好,中间那个丢光了全部结构化数据。 ## 那条决定命运的规则 把这四个案例并排看,规则其实非常朴素:决定你丢什么的不是你超了多少,是你把重要的东西排在了第几个字节。 要查单页的抓取体积有现成的工具,抓取体积检查器与Googlebot上限实测 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)那篇讲的是怎么用,本文补的是行业分布和落点这两件它不回答的事。 分类页的分页处理本来就有一套讲究,Shopify集合页分页的索引判断和canonical设置 (https://zhangwenbao.com/shopify-collection-pagination-seo-guide.html)那篇把常见的几种做法和后果对照过。 这句话听起来像常识,但它推翻的是一个非常普遍的做法——用页面总大小当作健康指标。总大小是一个必要条件,不是充分条件;它能告诉你有没有风险,不能告诉你风险落在谁头上。 Anker那个分类页的总大小比Allbirds还大,但它是安全的。如果你的巡检脚本只看总大小,你会给Anker报警而放过Allbirds——两次都错。 ## 一个可以自己复现的验证 如果想亲手确认这件事,最直接的办法是把一个超标页面的前2097152个字节单独存成一个文件,然后用浏览器打开它。 你会看到一个突然中断的页面:某个商品卡片显示到一半,后面全空。这就是Googlebot拿到的那份文档,不是一个近似,是字节级别完全一致的同一份东西。把它截图发给团队,比任何一段解释都管用。 再进一步的话,把这个截断版本丢进富媒体结果测试,看它还认不认得出你的结构化数据。这一步会把“可能有影响”变成“确实没有”,而这两句话在推动排期时的分量完全不同。 ## 不报错不等于没后果 有个问题保哥被问过很多次:既然截断不产生错误,那我怎么知道自己中招了? 不会喊的问题都得自己去找,接口和feed这类地址拿什么说自己不想被收录 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)那篇讲的是另一类同样没有报错位置的疏漏。 答案是:从现有的监控里你确实不知道。Search Console的覆盖率报告不会因为截断而变红,因为页面确实被成功抓取并索引了;抓取统计里那次请求是200;页面速度报告更不会提这件事,它量的是用户侧体验。 能看出来的地方只有三个,而且都不直接。第一是富媒体结果测试——如果它报“未检测到结构化数据”而你的源码里明明有,八成就是这个原因。第二是Search Console的网址检查工具里“已抓取的页面”那一栏,把它复制出来数字节数。第三就是自己量,也就是本文这套做法。 ## 为什么四个案例值得逐个拆 因为把它们归成一句话会丢掉最有用的那部分信息。如果只说“有4个站超标了”,读者拿到的是一个比例;逐个拆开之后,读者拿到的是一张自己站点的对照表。 Allbirds对应的是结构化数据放尾部的站,Wix对应的是首屏内联做得很重的站,Anker对应的是用了现代框架但把语义标签写在前面的站。这三种形态覆盖了绝大多数电商技术栈,你大概率能在里面找到自己那一类。 另外还有一层意思:Anker那两个页面证明了超标本身不是罪。如果本文只讲“别超过2MB”,读者会得出一个过度简化的结论,然后在一个不需要动的地方投入排期。 ## 渲染那一层还有第二重后果 前面提到WRS只能执行爬虫真的取到的那部分代码。当截断点落在一段脚本或者一段JSON数据的中间时,交给WRS的就是一份语法上根本不成立的东西。 框架站的渲染模式选择直接决定这类风险有多大,React和Next.js框架站渲染模式选错就抓成空壳 (https://zhangwenbao.com/react-nextjs-framework-seo-rendering.html)那篇把几种模式的取舍列全了。 Anker那两个页面的截断点恰好都落在同一类标签内部——后面一节会讲清楚那是什么。这意味着虽然它们的链接和结构化数据全都安全,但依赖客户端接管才能出现的内容仍然有风险。索引层安全和渲染层安全是两件事,不能互相担保。 而且WRS是无状态的,请求之间会清掉本地存储和会话数据。任何依赖“上一次访问留下的东西”才能正确渲染的逻辑,在它那里都不成立。这一条和截断没有直接关系,但它们经常一起出现在同一个技术栈里。 ## 被切开的那个标签会怎么样 浏览器的HTML解析器有很强的容错能力,遇到没闭合的标签会自动补齐,遇到写到一半的属性会尽力猜。所以一个被截断的HTML文档,多半还是能解析成一棵勉强能用的DOM树。 要确认一段JSON到底是不是完整的,最省事的办法是丢进格式化工具跑一次,JSON格式化与JSON-LD调试 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)那篇讲得很细。 但脚本和JSON不吃这一套。一段被从中间切开的JSON就是语法错误,解析它的代码会直接抛异常。如果那段JSON是页面接管所依赖的数据源,接管这一步就不会发生,客户端负责渲染的那部分内容一个字都不会出现。 ## 三种不同的受伤方式 把前面几个案例归一下类,截断造成的损失一共有三种形态,严重程度递增。 结构化数据该做哪些不该做哪些是有依据的,Schema官方第一次公开全网使用数据 (https://zhangwenbao.com/schema-org-usage-statistics-priority-guide.html)那篇拿实际使用率排了优先级。 第一种是内容缺失:链接、图片、文字段落被切掉。它的特点是损失可以数出来,也可以按比例估算影响。 第二种是元数据缺失:结构化数据、多语言标注、规范链接落在线外。它的特点是损失不成比例——一段结构化数据丢了就是全丢,没有丢一半这回事。 第三种是解析中断:截断点落在脚本或JSON中间,导致后续逻辑整个不执行。它的特点是损失可能远大于被切掉的那部分本身,因为断掉的是一个开关,不是一段内容。 ## 先查哪一种 按发现成本从低到高:先查元数据,因为富媒体结果测试几分钟就能给答案;再查内容缺失,需要自己数链接;最后查解析中断,它需要把截断后的文档喂给解析器才能确认。 要快速生成或者比对一段标准的结构化数据,结构化数据生成器与13种Schema类型 (https://zhangwenbao.com/schema-generator-jsonld-13-types-guide.html)那篇的工具可以直接拿来做对照基准。 好在这三种的修复方式高度重合——把关键的东西往前排,同时把体积压下来。你不需要先分清是哪一种才能动手,分类的价值在于估算损失的大小,不在于决定做什么。 ## 是什么把HTML撑到2MB的? 量到这里,最自然的猜测是内容太多——商品太多、文案太长、导航太深。保哥抓着这个猜测去拆了一遍,结果是猜错了。 ## 先看一个夸张的数字 Anker那个充电器分类页里,有一个标签单独占了2384424字节。 要看清一段内联代码到底占了多少字节,格式化工具比肉眼靠谱,CSS格式化、压缩与前端性能的真实账 (https://zhangwenbao.com/css-formatter-beautify-minify-frontend-performance-guide.html)那篇算过这笔账。 不是一段代码块,不是一整个区域,是一个标签。它的开头长这样:一个id叫做NEXT_DATA的脚本标签,类型标着application/json。它从文件的269963字节处开始,一直写到2654387字节处才结束,中间没有换行也没有别的标签。 > 这一个标签的长度是2384424字节,而整条抓取上限是2097152字节。也就是说,光是它自己,就比Googlebot愿意读的全部内容还长287272字节。 截断点2097152落在这段JSON的正中间,保哥把那个位置前后的原文取出来,是一张商品图的地址和它的替代文本,写到一半被切断了。 ## 那坨JSON里装的是什么 是这一页已经渲染出来的那些商品,再写一遍。 同一份内容在系统里存在两次这件事不只发生在前端,把内容当产品来设计 (https://zhangwenbao.com/content-productization-landing-page-first-step.html)那篇讲的是内容生产侧的另一种重复。 现代前端框架的通行做法是服务端先把HTML渲染好发给浏览器,让用户尽快看到内容;然后浏览器端的框架要接管这个页面,让它变得可交互。接管的前提是框架得知道这一页当初是用什么数据渲染出来的。最省事的传递方式,就是把那份数据原样序列化成JSON,内联进同一个HTML文件。 于是同一份商品列表在同一个文件里存在两次:一次是给人看的标签,一次是给框架用的数据。而抓取上限量的是两份之和。 ## 不是一家的问题 换了几个技术栈之后发现这是普遍现象,只是名字不一样。 这些机制全在前端手里,前端工程师SEO协作的7个动作点 (https://zhangwenbao.com/frontend-engineer-seo-collaboration-7-actions-semantic-cwv-render.html)那篇整理过哪些事必须由前端来做、SEO只能提要求。 页面 | 那个大标签叫什么 | 单标签字节 | 占整页 | anker.com分类页 | id为NEXT_DATA的JSON脚本 | 2384424 | 89.8% | uniqlo.com首页 | 赋值给PRELOADED_STATE的脚本 | 1635097 | 92.3% | brooklinen.com首页 | id为defaultData的脚本 | 1272381 | 81.0% | ikea.com首页 | 两个type为text/hydrate的脚本 | 777729+608078 | 75.8% | lovevery.com组合装页 | 394个分片推送调用,最大一个764356 | 合计约1991830 | 95.0% | Lovevery那个尤其能说明问题。它没有用一个大标签,而是拆成394个小脚本依次往一个数组里推数据。从工程角度这是更先进的做法,可以边下边渲染;从字节角度它和一坨没有任何区别,只是分成了394份。那个离上限只剩23个字节的页面,95.0%的体积是这些分片。 ## 内联样式是另一路 数据的影子之外,还有一路是样式。 在线工具生成的样式往往带着一堆用不上的默认值,CSS在线编辑器生成的是一份相对默认值的差异清单 (https://zhangwenbao.com/css-editor-83-controls-default-diff-unit-trap-guide.html)那篇讲过这个坑。 内联首屏样式的完整逻辑和适用边界,关键渲染路径怎么优化 (https://zhangwenbao.com/critical-rendering-path-render-blocking-css-optimization.html)那篇讲得比本文细,包括什么情况下不该内联。 页面 | 内联CSS字节 | 占整页 | wix.com首页 | 1803676 | 57.3% | us.shein.com首页 | 658854 | 57.2% | bigcommerce.com首页 | 640929 | 49.1% | bigcommerce.com定价页 | 553149 | 38.5% | article.com首页 | 212708 | 34.9% | Wix那一页把180万字节的样式写进了HTML。这不是疏忽,这是刻意的:把首屏需要的样式内联进文档可以省掉一次网络往返,让内容更早出现在屏幕上。它是各家性能指南里都写着的正经做法。 ## 还有第三路:内联的矢量图 Cloudflare首页给了一个意外的样本。它总长1304713字节,其中930927字节是内联SVG,占71.4%。 图标到底该用内联矢量图还是位图是有账可算的,135字节的图标被压成560字节 (https://zhangwenbao.com/image-compressor-webp-lossless-icc-icon-size-guide.html)那篇量过几种格式在小尺寸上的真实开销。 把图标做成内联SVG的理由同样很正当:不用发额外请求、可以用CSS直接改颜色、不会有闪烁。代价是每一个图标的每一条路径数据都变成了HTML文档的一部分,要和你的商品链接抢同一份预算。 ## 把三路加起来看 保哥把内联样式、内联脚本和内联矢量图三项加总,除以页面总长,得到一个“影子占比”。 这几项瘦身对用户侧指标也有好处,WooCommerce性能优化6层架构把LCP从4秒压到1.5秒 (https://zhangwenbao.com/woocommerce-performance-6-layer-lcp-core-web-vitals-real-path.html)那篇的分层办法可以照抄。 字节这件事还有另一个算法,从页面碳足迹到爬虫抓取的同一套规范 (https://zhangwenbao.com/sustainable-low-carbon-seo-web-performance-crawl-economics.html)那篇把传输字节换算成了能耗,结论方向和本文一致。 页面 | 页面总字节 | 三类内联合计 | 影子占比 | lovevery.com首页 | 1974154 | 1923449 | 97.4% | lovevery.com组合装页 | 2097129 | 1994562 | 95.1% | anker.com分类页 | 2654871 | 2519378 | 94.9% | brooklinen.com首页 | 1571567 | 1491908 | 94.9% | uniqlo.com分类页 | 1769926 | 1648710 | 93.2% | us.shein.com首页 | 1150889 | 1064401 | 92.5% | ikea.com首页 | 1827147 | 1577036 | 86.3% | > 把页面推到抓取上限的从来不是内容,是内容的影子。实测里最重的七个页面,86%到97%的体积都不是给人读的那部分。 ## 一个黑色幽默 拆Brooklinen和Jackery的内联脚本时,保哥在里面看到了一段正则表达式,内容是Googlebot、Storebot-Google、bingbot、Baiduspider、YandexBot、DuckDuckBot这一串爬虫名字。那是电商平台的埋点管理器在识别爬虫,好让爬虫不要污染统计数据。 识别爬虫这件事今天比过去复杂得多,AI爬虫抓取量已超Googlebot 3.6倍 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)那篇给了当前的爬虫构成和应对思路。 这段代码本身有几万字节,它是把这个页面推向截断线的那份重量的一部分。一段专门用来识别Googlebot的代码,在替Googlebot把这一页缩短。 ## 影子占比比总大小更有诊断价值 如果只能记一个指标,保哥会选影子占比而不是总大小。理由是它直接告诉你该往哪儿使劲。 影子占比低而总大小高,说明你的内容是真的多,那就该考虑分页或者调整信息架构;影子占比高而总大小还行,说明你现在安全但增长空间被提前吃掉了;两个都高,说明你正在用一个会不断膨胀的机制承载一个会不断增长的内容量,这是最需要立刻处理的组合。 算这个指标不需要工具:把源代码里最长的那几个脚本标签的长度加起来,除以文件总大小。三分钟能算完,而它给出的信息比总大小多一整个维度。 ## 为什么这件事这么难被发现 三路影子有一个共同特征:它们在浏览器里完全不可见。你打开开发者工具看元素面板,看到的是渲染后的DOM树,那些内联JSON已经被框架消化掉了;你看网络面板,看到的是压缩后的传输大小;你跑性能评分工具,它关心的是渲染时间不是文档长度。 想看清源码的真实结构,一个能实时预览又能看原始文本的编辑器很省事,HTML编辑器三栏实时预览 (https://zhangwenbao.com/html-editor-html-css-js-live-preview-guide.html)那篇介绍了用法。 唯一能看见它的地方是查看网页源代码然后往下滚,或者像本文这样直接量字节。而这两件事都不在任何一条常规工作流里。 ## 为什么框架不替你解决 因为对框架来说这不是问题。把数据内联进文档是它能想到的最可靠的传递方式:不需要额外请求、不会有时序问题、不依赖任何外部状态。从框架的角度这是一个优雅的设计。 两个都没做错的组件在同一个地方打架是常态,装了SEO插件却冒出两个canonical (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)那篇是另一个同构的例子。 框架的作者没有理由知道谷歌的字节上限是多少,就像你没有理由知道框架内部用什么格式序列化数据。这个后果掉在两个都没做错的设计中间那条缝里,而缝里没人。 ## 能不能不要那份数据 大多数情况下不能,但大多数情况下可以让它小很多。 把内容当结构化数据来生产会顺带解决字段冗余的问题,内容工程与AI搜索时代的内容生产 (https://zhangwenbao.com/content-engineering-structured-content-ai-search.html)那篇讲了这套思路。 那份数据之所以大,通常是因为它是后端接口返回的原样。一个商品对象里可能有40个字段,而页面上真正用到的只有八个:标题、价格、主图、库存、评分、链接、颜色、尺码。剩下32个字段——供应商编号、入库时间、内部分类码、多个尺寸的图片地址——一个都不会出现在屏幕上。 裁字段是本文提到的所有动作里最费劲的一件,但也是收益最大的。前面那个耗材站砍掉了108万字节,占它总瘦身量的三分之二。 ## 另一条更省事的路 如果框架支持,把接管数据从内联脚本改成一次独立的网络请求,这份数据就有了自己的字节额度,不再占用父页面的份。 多一次往返值不值得,取决于你的缓存层怎么搭,TTFB怎么优化才不白费 (https://zhangwenbao.com/ttfb-multi-layer-cache-core-web-vitals-crawl-budget-seo.html)那篇把多层缓存对抓取和体验的双向影响算清了。 代价是多一次往返,首次交互时间会变差一点。这是个真实的取舍,不是免费的午餐。但对于那些商品数很多的分类页,这个取舍往往是划算的——因为分类页上的用户本来就要浏览一阵子才会点进商品,那一次往返藏得住。 ## 顺便说一句内联的边界 内联本身没有错,错的是把“内联能省一次请求”当成一条无条件成立的规则。省一次请求的收益是固定的,大概几十毫秒;内联的成本却是随内容线性增长的。 很多当年正确的决定今天已经翻过去了却没人复核,被低估的9个反直觉UI设计杠杆 (https://zhangwenbao.com/counterintuitive-ui-design-conversion-levers.html)那篇里有几个例子是同一个道理。 当被内联的东西小到几KB,这笔账怎么算都赚;当它涨到几十万字节,这笔账早就翻过去了,只是没有人回头重算过。本文实测里没有一个站是故意把180万字节的样式写进文档的,它们只是在很久以前做了一个当时正确的决定,然后再也没有复核。 ## 为什么优化性能反而会把页面推过线? 这一节是全文最别扭的部分。因为把页面撑到抓取上限的那三件事,每一件单独拿出来都是被官方推荐过的正经做法。 ## 三条建议,同一个文件 做法 | 它要解决的问题 | 它往HTML里加了什么 | 内联首屏关键样式 | 消除渲染阻塞,让内容更早显示 | 几十KB到100多万字节的CSS | 服务端渲染加客户端接管 | 首屏可见早,交互又跟手 | 整页数据的JSON副本 | 图标改成内联矢量图 | 省请求、无闪烁、可换色 | 每个图标的完整路径数据 | 改版是这类问题最集中的时点,改版不掉SEO的完整防护清单 (https://zhangwenbao.com/website-redesign-theme-switch-seo-protection-h-tag-schema-internal-link-cwv.html)那篇里的检查项建议加上文档字节数这一条。 性能这条线本身的收益是真实的,海外客户用低端机弱网打开你的独立站有多卡 (https://zhangwenbao.com/overseas-weak-network-low-end-phone-mobile-performance-optimization.html)那篇量过这些优化在真实设备上的差别。 没有一条是错的。第一条来自Chrome团队关于消除渲染阻塞资源 (https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources)的长期建议,配套的做法在web.dev那篇提取关键CSS (https://web.dev/articles/extract-critical-css)里写得更细。它们的问题在于三者共用一个容器,而这个容器有一条谁都没提的边界。 > 性能优化和抓取完整性在同一个HTML文件里争同一份预算,而且争抢的方式是单向的:性能这边每省一次网络往返,抓取那边就少一截余量。 ## 为什么这场冲突几乎从不被提起 因为两边的度量单位不一样。性能这边的单位是毫秒,抓取这边的单位是字节;性能这边的报表是实验室数据加真实用户数据,抓取这边压根没有报表。 跨部门的口径缝隙需要一份对账清单来兜,数据分析师与SEO对账清单的7个动作点 (https://zhangwenbao.com/data-analyst-seo-reconciliation-7-actions.html)那篇给了一套可以照抄的协作机制。 更根本的原因是两边的负责人通常不是同一个人,甚至不在同一条汇报线上。前端负责渲染指标,技术SEO负责收录与结构化数据。而这条冲突恰好横跨两者,落在中间那条缝里。 这跟保哥之前写过的很多口径问题是同一个形状:不是有人做错了,是两个都做对的人在同一个地方留下了一个谁都不负责的后果。 ## 一个真实的取舍现场 去年保哥接手过一个做3D打印耗材与配件的跨境独立站,欧美加澳洲三个市场,耗材22到45美元一卷,另外卖喷嘴、料盘、加热床这些配件,团队14个人。这个品类的SKU结构非常特殊:同一款耗材要按材质、直径、颜色三个维度铺开,光是一种PLA就能拆出60多个变体。 变体多的品类在分类页上的处理是个老问题,WooCommerce独立站SEO优化12步 (https://zhangwenbao.com/woocommerce-seo-12-step-roadmap.html)那篇里产品页和分类页那两节可以直接对照。 他们的耗材总览页要列出全部在售变体,因为客户就是按颜色挑的,你把颜色收进筛选器,跳出率立刻涨。这一页在改版前有412个商品卡片。 改版做了两件事:把首屏样式内联进文档,首次内容绘制从2.4秒降到1.3秒;同时换了新的前端框架做服务端渲染,交互延迟明显改善。这两件事上线之后的三个月里,团队看到的所有指标都在变好。 ## 问题是怎么冒出来的 不是通过监控。是通过一次很偶然的对话。 筛选和变体的展示方式会同时影响体验和字节,连点五个筛选之后用户已经忘了自己选过什么 (https://zhangwenbao.com/shopify-collection-applied-filters-overview-ux.html)那篇讲的是它的体验代价。 运营同事在做站内搜索优化时,想确认一下某个颜色的耗材有没有被正确收录,随手在搜索引擎里用site指令查了一下这个分类页下面的商品。她注意到有一批深色系的变体怎么都查不到,而那批变体在页面上排得比较靠后。 她第一反应是那些商品可能没上架,去后台查了一下,全部在售。第二反应是可能被canonical指到别处了,查了一下也没有。她卡在这里两天,因为她能想到的所有排查方向都指向“页面本身有问题”,而页面本身怎么看都是好的。 转机是她把这一页的源代码另存为本地文件,想用编辑器搜一下那几个颜色的名字。文件属性显示2.6MB。她当时的原话是:一个没有图片的HTML文件为什么会有2.6MB。 > 这个破局点的成本几乎为零:她不是在怀疑什么,只是需要一个能被搜索的文本。文件大小是操作系统顺手告诉她的。 ## 拆开之后的账 量完的结果是:那一页2712880字节,超出上限615728字节,也就是文件的77.3%处被切断。 全站爬一遍能顺手把链接结构的断点找出来,Screaming Frog全站审计的12类问题排查清单 (https://zhangwenbao.com/site-crawl-audit-desktop-crawler-screaming-frog-workflow.html)那篇给了完整流程。 图片标签被切掉之后连带影响的是图片搜索那条流量,Shopify图片SEO从命名到压缩的完整清单 (https://zhangwenbao.com/shopify-image-seo-guide.html)那篇讲了这条线怎么保。 元素 | 整页 | 线内 | 被切掉 | 商品卡片链接 | 412 | 301 | 111个,占26.9% | 商品列表结构化数据 | 1段 | 0 | 全部 | 分页导航链接 | 8 | 0 | 全部 | 111个商品卡片对不上她查不到的那批深色变体吗?对得上,而且比她发现的更多——她只注意到深色系,因为那是她自己负责的那条产品线。 分页导航那一行最疼。8个分页链接全在页脚,全部落在截断点之外。也就是说从这一页出发,Googlebot根本走不到第2页往后的任何商品。那些商品还能通过站点地图被发现,但站点地图只负责告诉搜索引擎这个网址存在,它不传递任何关于重要性的信号。 ## 改了什么,代价是什么 处理顺序按“改动成本从低到高”排,实际效果却几乎相反。 首屏时间涨0.3秒值不值得,最好用实验来回答,30个A/B测试方案 (https://zhangwenbao.com/ab-testing-ctr-conversion-optimization.html)那篇里有几个跟加载速度直接相关的测试设计。 动作 | 工程量 | 减掉的字节 | 把分页导航和结构化数据挪到文档前部 | 半天 | 0,但把风险清零 | 内联样式改成只留首屏用到的规则 | 三天 | 约39万 | 接管数据里剔除渲染用不到的字段 | 一周半 | 约108万 | 图标从内联矢量图改回雪碧图 | 两天 | 约11万 | 第一项减掉的字节是零,但它是全部四项里唯一一个能保证“以后再长也不会丢关键内容”的。把重要的东西往前排不解决体积问题,它解决的是排序问题,而排序才是决定你丢什么的那个变量。 四项做完之后这一页落到1201000字节左右,占预算57.3%。首次内容绘制从1.3秒回到1.6秒,涨了0.3秒。这个代价是真实的,得写出来。 ## 三个月后的数 被截掉的那111个商品,其中87个在六周内进入了索引;分类页在长尾颜色词上的展示量涨了不少,但保哥不打算把这个数字写成一个精确的百分比,因为同期他们还做了别的事,归因分不干净。 同期做了别的事就没法干净归因,哪条外链真撬动排名与6步实验设计 (https://zhangwenbao.com/backlink-attribution-experiment-design-rank-uplift.html)那篇讲的正是怎么在多个变量里隔出一个。 能干净归因的只有一件:商品列表的富媒体结果回来了。这件事只跟结构化数据在不在线内有关,没有第二个变量。 另一件说不上是收益还是教训的事:他们后来给这一页做了自动分页,每页96个商品。做完之后页面长度降到60多万字节,余量充足。但客户投诉挑颜色变麻烦了,加购率掉了。最后回滚成一页全展示加上前面那四项瘦身——绕了一圈才明白,问题从来不是商品太多,是每个商品在文件里占的位置太贵。 ## 这次复盘里最该记住的一句 > 发现它的人不是在排查,是在找一个能被搜索的文本。所有真正难被发现的问题,最后都是被一个跟它无关的动作顺手撞出来的。 最难发现的问题往往是被一个不相干的动作撞出来的,揪出购买路径上那些看不见的摩擦力 (https://zhangwenbao.com/invisible-friction-conversion-killers.html)那篇里的几个案例也是这么被发现的。 这一点值得展开一句。团队里没有人失职:前端做了性能优化并且拿到了结果,SEO在做站内链接结构并且做得不错,运营在盯商品收录。三条线各自的检查项里都没有“文档字节数”这一项,因为它不属于任何一条线。 ## 如果当时有一份预算表会怎样 会在改版上线的那一次构建里就被拦下来。那次改版把内联样式加进去,文档一次涨了39万字节,从原来的200多万涨到270万——一个只要有人看一眼数字就会警觉的跳变。 把定期检查交给定时任务是最省心的做法,用cron把独立站运维自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)那篇给了备份、sitemap和日志的完整脚本。 问题不是没人愿意看,是那个数字从来没有被显示在任何地方。它不在构建日志里,不在部署摘要里,不在任何一张周报上。 ## 这件事在哪一类团队最容易发生 技术能力强、迭代快、性能意识好的团队。这不是反话。 技术能力弱的团队用的是成熟模板,模板输出的HTML结构固定、体积可控,反而不会出事;技术能力强的团队才会自己上框架、自己做首屏优化、自己写渲染逻辑,而这三件事全是这个问题的诱因。 能踩到这个坑,某种意义上是团队水平的证明。但这句安慰改变不了那111个商品三个月没被抓到的事实,所以它只能当一句玩笑说,不能当一个理由。 ## 成本对照 整件事从发现到修完花了大约四周人力,跨了三个人。如果在改版那次就有一条构建断言,成本是半天。 预防和发现的成本差十几倍这件事在实验上同样成立,A/B测试样本量怎么算才能避免假胜利 (https://zhangwenbao.com/dtc-ab-test-sample-size-3-formulas.html)那篇算过提前算样本量能省多少返工。 两个数字之间差了十几倍,而且这还没算上那三个月里被切掉的111个商品少收的流量。这类问题的成本结构是固定的:预防很便宜,发现很贵,而中间那段时间是免费送给对手的。 ## 这条线到底该用哪把尺子量? 前面所有的数都是按解压后的字节算的。这个选择需要交代清楚,因为换一把尺子,结论会翻过来。 ## 官方原文里的两种说法 Gary那篇文章在同一段里用了两种表述。一处是“Googlebot目前对任意单个网址取回最多2MB”,另一处是“这对你的服务器通过线路发出的那些字节意味着什么”。 压缩协商这一层的坑不止一处,nginx出厂只压HTML这一种类型 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)那篇发现其余类型的字节是全额计入抓取成本的。 前一种听起来像是在说文件本身的大小,后一种听起来像是在说传输量。这两者在HTTP协议里本来就是分开定义的,Content-Encoding响应头 (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Encoding)标注的正是“实体内容被编码过,你收到的字节数不等于原始字节数”。而现代网站几乎全部开启了压缩传输,这两个数差得非常远。 ## 差多远 保哥对46个样本逐个记了传输字节和解压字节。 把HTML本身压一遍也有讲究,WordPress免插件压缩HTML加速 (https://zhangwenbao.com/wordpress-compression-html-code-to-improve-web-page-loading-speed.html)那篇讲了保留代码块和与GZIP叠加时该注意什么。 指标 | 压缩倍数 | 中位数 | 7.55倍 | 算术平均 | 8.47倍 | 最高(bigcommerce.com定价页) | 14.95倍 | 最低(ouraring.com首页) | 3.68倍 | 七倍半的中位数意味着什么?意味着一个解压后1.5MB的页面,在网络上只跑了两百KB。你在浏览器网络面板里看到的那个“200 kB”,和抓取上限量的那个数,相差一个数量级。 ## 换尺子之后的结论 > 46个样本里,传输字节超过2MB的页面:0个。解压后超过2MB的页面:4个。同一批页面,同一条线,换一把尺子量,超标数从0变成4。 同一件事换个口径结论就翻过去,这类事在行业清单里非常普遍,9条查得到出处、8条数字对不上 (https://zhangwenbao.com/best-practice-list-citation-drift.html)那篇追过一批来源。 这就是为什么本文全程用解压字节。不是因为确定官方就是这么算的,而是因为在两种可能的口径里,一个会漏报,一个会误报,而漏报的代价是你永远不知道自己丢了东西。 顺带一提,压缩倍数本身也是个不稳定的量。它取决于内容重复度——那些内联JSON因为字段名反复出现,压缩率特别高。Allbirds那个分类页压缩了13.00倍,正是因为它里面有大量结构相同的商品数据。越是把你推向上限的那类内容,越是在传输字节上看不出来。 ## 那响应头呢 官方明说限额包含HTTP请求头。这一项保哥也量了,22个站的头部平均2938字节,最大的是webflow.com的13975字节。 Set-Cookie这一堆多半来自同意管理和统计脚本,GDPR和CCPA同意横幅怎么不毁SEO数据 (https://zhangwenbao.com/seo-legal-compliance-gdpr-ccpa-consent-mode-cross-border-architecture.html)那篇讲了它们的取舍。 拿最大值算,它占2MB预算的0.67%。绝大多数情况下可以忽略。但有两种情况不能:一是你的余量本来就只剩几万字节;二是你的站点用了大量Set-Cookie,实测里chubbies.com的分类页一次响应带了14个Set-Cookie,头部接近4KB。 ## 一份可以直接抄的余量标准 综合以上不确定性,保哥给自己定的规矩是这样的。 阈值定得太紧没人执行、太松失去意义,页面速度到底怎么影响SEO排名 (https://zhangwenbao.com/page-speed-seo.html)那篇里给优化项排优先级的思路可以直接搬过来定这个值。 解压后HTML大小 | 状态 | 该做什么 | 低于1000000字节 | 安全 | 什么都不用做 | 1000000到1500000字节 | 观察 | 确认关键标签落点在前5%以内 | 1500000到1800000字节 | 警戒 | 安排瘦身,并把关键标签前移 | 超过1800000字节 | 危险 | 当作已经超标处理 | 1800000这个警戒值留了约14%的余量。这个余量不是拍脑袋来的,它对应三件很容易发生的事:一次营销活动往页面上加两个模块、一次多语言上线让每个文案变长、一次埋点升级给每个商品卡加两个属性。 ## 这张表怎么用才不会变成摆设 把阈值写进文档没有用,写进流程才有用。这张表的正确用法是把那个1800000填进一条构建断言里,让它在每次发布前自己跑一遍。 如果暂时做不到,退而求其次的做法是把它挂在改版和大促这两个时点上——这两件事是页面长度跳变最集中的场合,也是最容易被忽略的场合,因为那时候所有人都在盯别的指标。 ## 为什么不建议踩着2MB做优化 三个理由,按重要性排。 规则会变这件事这两年体现得特别明显,Core Web Vitals在AI搜索时代还值不值得投 (https://zhangwenbao.com/core-web-vitals-ai-search-industry-benchmark.html)那篇追过一轮指标口径的调整。 第一,官方明说这条线会随时间改变,而且暗示了它有可能往下走——原文那句“或者变小,希望是变小”是在说网页大小的趋势,但一条为了适应网页而设的线,跟着网页走是很自然的。 第二,你不知道自己什么时候会越线。页面长度不是由一次决策决定的,是由几十次小改动累加出来的,而每一次小改动的作者都不知道当时的余量是多少。 第三,也是最实际的:越线之后没有任何信号。你的所有其他阈值——图片大小、脚本执行时间、接口响应——都有工具会告诉你超了。只有这一条不会。 ## 一句给排期用的话 如果要向不熟悉这件事的人解释为什么按解压字节算,最短的说法是:压缩是给网络省钱的,不是给内容减肥的。压缩不会让你的文档变短,只会让它在路上占的地方变小,到了对面还得原样展开。 ## 顺便说一下压缩本身 虽然抓取上限大概率不看压缩后的字节,但压缩仍然值得认真做,理由跟本文无关:它直接影响用户侧的加载时间,也影响抓取的效率。服务器上没打开的压缩类型,会让相应的资源以原始体积传输。 压缩之外还有一批同样影响抓取效率的小事,从sitemap的lastmod到结构化数据的日期 (https://zhangwenbao.com/timestamp-converter-unix-epoch-sitemap-lastmod-guide.html)那篇讲的时间戳口径是其中之一。 这里要区分开的是两件事:压缩优化的是传输,前移和瘦身优化的是文档结构。前者让页面更快,后者决定页面完不完整。两件事都要做,但不能互相替代,也不能用其中一件的达标去证明另一件没问题。 ## 一个反直觉的推论 压缩率越高的页面,越容易出问题。 工具给出的页面体积口径各家不一样,Semrush完整使用指南 (https://zhangwenbao.com/semrush-complete-guide-overseas-dtc.html)那篇里提过怎么确认一个工具报的数到底是哪一种字节。 因为压缩率高说明内容重复度高,而内容重复度高的最大来源恰恰是那些结构化的内联数据——同样的字段名在几百个商品对象里出现几百遍。所以压缩率是一个反向指标:它越好看,说明你的文档里那份“内容的影子”越大。 实测里压缩倍数最高的两个页面,bigcommerce的定价页14.95倍、ahrefs首页14.82倍,解压后都在120万字节以上,而它们的传输字节只有九万多和八万多。光看网络面板,这两个页面轻得像一篇博客。 ## 这条推论怎么用 它给了一个几乎零成本的粗筛办法:把传输字节乘以8。 这类粗筛动作基本都能用免费工具完成,预算为零也能做好SEO的免费工具清单 (https://zhangwenbao.com/free-seo-tools-zero-budget-checklist.html)那篇整理过一批。 8是本文实测均值8.47向下取的整。如果乘完之后超过180万,就该认真量一次;如果乘完还不到100万,基本可以放心。这个粗筛不精确,但它只需要看一眼浏览器网络面板里的数字,做一次乘法。 > 做乘法这件事本身值得提醒一句:人脑对乘法的直觉很差。看到“传输220KB”的时候,没有人会自动想到“这一页可能有1.8MB”,因为220和1800之间那个跳跃不在直觉的射程里。 ## 浏览器工具为什么帮不上忙 开发者工具的网络面板确实会同时显示传输大小和资源大小两列,后者就是解压后的字节。但默认视图里资源大小那一列常常被折叠掉,而且它显示的是“1.9 MB”这种带单位的近似值,你没法用它去跟2097152做比较。 查看源代码和开发者工具看到的经常不是同一份东西,渲染对比器揪出爬虫和用户看到的页面不一样 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)那篇讲了怎么把两份摆在一起比。 更麻烦的是,网络面板显示的是浏览器最终拿到的那份文档,如果页面上有脚本在加载后修改了DOM,你查看源代码看到的和面板里量到的可能不是一回事。唯一没有歧义的量法是把原始响应存成文件,看文件大小。 ## 被截掉一截,对转化到底有多大影响? 写到这里必须回答一个更硬的问题:这件事值不值得占用你本来就不够用的排期。保哥的答案是分情况,而且分得很清楚。 ## 先把不影响的那部分划掉 截断影响的是搜索引擎看到的版本,不影响用户看到的版本。你的访客拿到的永远是完整文件,页面在浏览器里怎么好用还是怎么好用。 搜索侧和转化侧该各管各的指标,高转化电商网站的SEO加CRO双轴8模块 (https://zhangwenbao.com/high-conversion-ecommerce-cro-seo-90day-playbook.html)那篇把两条线的分工画得比较清楚。 所以下面这些指标不会因为截断而变差:加购率、结账完成率、站内搜索使用率、退货率、客单价。如果有人告诉你修好截断能提升转化率,那句话是错的。 ## 真正受影响的是三样东西 丢掉的东西 | 直接后果 | 多久能看出来 | 商品卡片链接 | 那些商品少了一个内部入口,权重分发断掉 | 数周到数月,且难归因 | 结构化数据 | 富媒体结果消失,搜索结果里没有价格和评分 | 几天,且可直接验证 | 分页与筛选链接 | 整个下级层次失去发现路径 | 数月,最难发现 | 商品结构化数据的字段这两年还在加,Google给商品结构化数据加了个category (https://zhangwenbao.com/merchant-listing-category-property-google-product-taxonomy.html)那篇讲的就是最近这一次变化。 评分和价格能不能出现在搜索结果里,全看那段结构化数据在不在,怎么给评论加上星级结构化数据 (https://zhangwenbao.com/shopify-ryviu-review-structured-data-guide.html)那篇讲了具体做法。 三样里只有第二样能干净归因。前面那个3D打印耗材站的复盘之所以只敢说富媒体结果这一件,就是因为另外两件的效果和同期别的动作缠在一起。 ## 富媒体结果和转化的关系 这是唯一一条能连到转化的链路,而且它连的是点击率不是转化率。搜索结果里带着价格、库存状态和评分的那一条,和只有标题描述的那一条,被点开的概率不一样。 要测富媒体结果对点击率的影响得先隔离变量,SEO实验设计与统计功效 (https://zhangwenbao.com/seo-ab-testing-experiment-design-statistical-power-single-factor.html)那篇讲了最小可检测效应该怎么定。 但这里必须节制。行业里流传的那些“富媒体结果提升点击率百分之多少”的数字,绝大多数经不起追问——分母是什么、对照组怎么选的、同期有没有别的变化,往往一条都答不上来。保哥不打算再往里加一个。 > 能说的只有一句:结构化数据落在截断点之外,等于你写了但没生效。这句话不需要任何效果数据来支撑,它本身就是个事实判断。 ## 分页链接为什么最疼 因为它的损失是成倍的。一个分类页丢掉8个分页链接,丢的不是8个网址,是这8个网址背后可能几百个商品的内部发现路径。顺带一提,商品列表本身该用ItemList类型 (https://schema.org/ItemList)来描述,它的position字段正是用来告诉搜索引擎“这一项在列表里排第几”的——而排第几这件事,在字节层面还有另一重含义。 内部发现路径塌掉之后补救成本很高,多级面包屑导航的3种方案加结构化数据 (https://zhangwenbao.com/shopify-blog-breadcrumb.html)那篇是另一条常被忽略的发现路径。 而且这类损失在报表上表现为“什么都没发生”。那些商品还在,还能被搜到(如果它们在站点地图里),只是它们在站内链接结构中的位置塌了一块。你不会看到一条曲线掉下去,你只会看到一条曲线一直没涨起来,而这两件事在图上长得一模一样。 ## 什么样的站需要现在就查 不是所有站都值得花这个时间。按保哥的经验,下面这几个特征命中两条以上就该查。 多语言站还有一整套自己的坑,国际化SEO和hreflang的多语言站避坑清单 (https://zhangwenbao.com/international-seo-hreflang-complete-guide.html)那篇是这方面比较全的一份。 多语言站的模板共用是这类问题的高发区,WooCommerce多语言多货币SEO的三层避坑 (https://zhangwenbao.com/woocommerce-multilingual-multicurrency-seo-hreflang-url-schema.html)那篇把语种差异的坑列了一遍。 特征 | 为什么危险 | 分类页一屏展示全部变体不做分页 | 页面长度直接跟SKU数成正比 | 用了服务端渲染加客户端接管的框架 | 数据副本会跟着商品数一起长 | 结构化数据由页面底部的脚本注入 | 落点靠后,且随页面变长而后移 | 做过首屏样式内联 | 一次性加进去几十万字节 | 多语言站点用同一套模板 | 某些语种文案更长,可能只有一个语种超标 | 最后那条是最阴的。保哥见过一个站英文版1.7MB安全、德文版2.1MB超标,因为德语复合词长。你在英文版上做的全部测试,一次都覆盖不到那个真正出问题的版本。 ## 还有一类站几乎不用查 纯内容站、博客、单页产品站、目录页数很少的品牌站,基本可以跳过。它们的页面长度由文案决定,而文案再长也很难写到100万字节——那大概是30多万个汉字。 判断的标准可以简化成一句:你这一页的长度是由人写出来的,还是由数据库条数决定的。前者天然有上限,后者没有。所有出事的页面都属于后者。 这条判据也解释了为什么分类页比商品详情页危险。商品详情页的内容量是固定的,加一个商品不会让它变长;分类页的内容量跟在售商品数成正比,而在售商品数只会增加。 ## 先量哪一页 按这个顺序:变体最多的那个分类页、商品数最多的那个筛选结果页、首页、语言版本里文案最长的那一版。前两个基本能覆盖九成风险。 筛选结果页同时还是重复内容的高发地,电商重复内容的8类成因地图 (https://zhangwenbao.com/ecommerce-duplicate-content-causes-diagnosis-canonical-strategy.html)那篇讲了它该怎么被治理。 筛选结果页往往是全站最长的页面,独立站搜索框怎么设计才不浪费这个高转化入口 (https://zhangwenbao.com/site-search-bar-ux-design-conversion.html)那篇讲的结果页设计会直接影响它的长度。 不需要全站扫。全站扫的成本会让这件事排不上,而排不上的检查等于不存在。先量四个页面,四个都安全就先收工,这是本节最实际的一条建议。 ## 一个反向的提醒 量完发现远低于上限的话,请到此为止,不要顺手做“页面瘦身优化”。 优化到什么程度该停手是个通用问题,AI时代CRO优化的4个策略 (https://zhangwenbao.com/ai-cro-optimization-strategies-2026.html)那篇讲了怎么给每一项优化定一个明确的完成条件。 页面长度本身不是排名因素,把一个800KB的页面减到400KB不会带来任何搜索侧收益。这件事的全部价值在于避免一个二元的、灾难性的、不报错的失败,而不在于把一个数字变小。 这个区分很重要,因为它决定了你该在什么时候停手。很多技术优化项目跑偏,就是因为把一个“及格线”当成了“越高越好的分数”。 ## 及格线和分数的区别 及格线是二元的:过了就没事,差一点就全丢。分数是连续的:多一分有多一分的好处。把及格线当分数追,会在一个收益早已归零的方向上持续投入。 把及格线当分数追这件事在归因模型上也常见,多触点归因模型怎么选才不被最后一次点击骗走预算 (https://zhangwenbao.com/dtc-multi-touch-attribution-model-selection.html)那篇讲了停手的判据。 这个行业里被当成分数追的及格线不少。页面体积是一个,请求数是另一个,HTML标签的语义化程度也常被这么对待。判断一件事属于哪一类,只要问一句:从60分提到90分,有没有任何一个具体的后果会改变?答不上来就是及格线。 ## 那什么时候它会变成分数 只有一种情况:当页面体积大到影响用户侧加载时间时。但那已经是另一个话题了,它的判据是真实用户的加载指标,不是2MB这条线。 用户侧的加载指标该看哪几个、看到什么程度算够,从响应式到Core Web Vitals的3类站点改造对比 (https://zhangwenbao.com/mobile-seo-optimization-guide.html)那篇给了对照。 两个话题共用同一个动作(把文档变小),但它们的停手条件完全不同。为抓取完整性做的瘦身,做到安全线以下就该停;为加载速度做的瘦身,只要用户侧指标还在改善就可以继续。混在一起做会导致两件事都说不清楚做完没有。 ## 这份字节预算表怎么落到构建流程里? 前面全是诊断,这一节是处方。按“做完能不能一劳永逸”排序,不按工程量排序。 ## 六件自查动作 第一件带早停:取四个页面另存为本地文件,看文件大小。变体最多的分类页、商品最多的筛选页、首页、文案最长的语言版本。五分钟,零成本,不需要任何工具。四个都在100万字节以下就可以收工——后面五件解决的是同一个病,而这一件已经证明你没得这个病。 这六件里有五件不需要任何付费工具,11个按性价比排序的速赢清单 (https://zhangwenbao.com/seo-quick-wins-prioritized-checklist.html)那篇的排序逻辑和这里一样,都是先做能早停的那件。 第二件:查看源代码,用浏览器的查找功能定位你的结构化数据,看它在文档的什么位置。十分钟。如果它在文档下半部分,不管当前页面多大,都把它移到head里去。这一件是全部六件里唯一一个能永久免疫的。 第三件:把分页导航和面包屑挪到主内容之前。半天。它们在视觉上仍然可以显示在页脚,用样式控制位置就行;要挪的是它们在文档里的顺序。 第四件:翻一遍那个最大的内联脚本,看看里面有多少字段是渲染用不到的。一到两周,最费劲的一件。通常能砍掉一半以上,因为那份数据往往是把后端接口的返回原样塞进去的。 第五件:把内联的关键样式限制在真正的首屏范围内。三天左右。很多站的“关键样式”是整套设计系统,不是首屏那几个组件。 第六件:给多语言站点逐个语种量一遍。半天。这一件不产生任何改动,只产生一张表,但它是唯一能发现“只有德文版超标”这类问题的动作。 ## 卡点挂在哪里 前面六件都是一次性的。要让这件事不复发,得有一个东西挡在改动路径上。 把一个数字放进例行流程比记在脑子里可靠,新网站SEO目标管理的3里程碑加量化任务清单 (https://zhangwenbao.com/new-website-seo-goal-management.html)那篇讲的是同一种思路。 如果暂时改不动构建流程,退一步用定时任务每天量一次也行,把sitemap、排名和清缓存交给定时任务 (https://zhangwenbao.com/cron-generator-crontab-expression-seo-task-automation-guide.html)那篇给了写法。 保哥试过的做法里效果最好的是这个:在构建产物里输出一个数字。构建流程跑完之后,对几个代表性页面各生成一次HTML,量它的字节数和关键标签落点,把这两个数写进构建日志,超过警戒值就让构建失败。 断言 | 阈值 | 失败时的提示 | 文档总字节 | 低于1800000 | 当前值与上次构建的差额 | 最后一段结构化数据的收尾位置 | 低于文档的5% | 它当前在第几个字节 | 最靠后的分页链接位置 | 低于文档的50% | 同上 | 为什么是刻度而不是别的形式?因为这个数字必须在有人做出改动的那一刻出现,而不是在季度巡检时出现。一个季度检查一次的指标,只能告诉你已经错了多久;一个跟着每次构建走的指标,能告诉你是哪次改动干的。 提示语里那个“与上次构建的差额”是关键设计。总量超标只能说明积累到头了,差额才能指出是谁加进来的。实践下来,看到“本次构建增加了217KB”的人,会去看自己改了什么;看到“当前1.83MB超标”的人,会去问这个阈值是谁定的。 ## 怎么跟人说这件事 说“我们的页面太大了”效果是零。页面大不大是个见仁见智的判断,而且负责性能的同事手上有一整套数据证明这个页面很快,你说不过他,因为他是对的。 跨职能沟通有一套通用的说法,网页设计师SEO协作的7个动作点 (https://zhangwenbao.com/web-designer-seo-collaboration-7-actions-ia-figma-typography-image-cta.html)那篇里那几句开场白可以直接照搬到本文这个场景。 保哥用的说法是这样的:这一页的HTML是2.6MB,Googlebot只读前2MB。我数了一下,第2MB之后有111个商品链接和全部8个分页链接。我想把分页链接和结构化数据挪到文档前面,挪完再看一次。 > 三个事实一个提议,没有一个字说这个页面做得不好。快和完整是两个独立的属性,一个页面完全可以又快又缺一截。 护住所有人的第二句:这个页面的性能优化是对的,问题不在它身上,在于我们没有一个地方记录过这份预算还剩多少。这句话把焦点从人挪到了“缺少一个仪表”上,而添一个仪表是没人需要反对的事。 ## 四条边界 第一条:这套方法只对HTML文档有效。图片、脚本文件、样式文件各有自己的额度,不占父页面的份。有人量完HTML就去优化图片体积,那是另一件事,跟这条线无关。 PDF走的是另一条64MB的线,PDF怎么做SEO与6个优化清单 (https://zhangwenbao.com/pdf-seo-complete-guide-google-indexing-6-real-optimizations.html)那篇讲的规则和HTML这条完全不同,别混着用。 规范链接是另一个经常被当成命令来用的提示,canonical标签是提示不是命令 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html)那篇列了8种误用,逻辑和本文的边界那节很像。 第二条:没超标不等于没问题,超标也不等于一定受伤。这一点前面用Anker和Allbirds的对照说过了。总大小是筛查指标,落点才是诊断指标,不能只看前者。 第三条:本文的全部数字来自2026年8月上旬对46个页面的一次快照。这些站随时会改版,你今天去量可能得到完全不同的结果。可以迁移的是方法和那条2MB的线,不能迁移的是任何一个具体百分比。 第四条,也是最容易被忽略的:如果一个页面从设计上就该分页,那么它超标只是这个设计问题的一个症状。先想清楚一页展示412个变体是不是必要,再决定要不要为了保住这个设计去做字节层面的腾挪。前面那个站绕了一圈才想明白,一页全展示确实是对的,但那是因为客户按颜色挑;如果换成一个用户根本不会翻到底的页面,那就该分页。 ## 三种常见的返工做法 见过团队在这件事上走过三条弯路,都不算错但都更贵。 第一条是先做整体瘦身再谈排序。瘦身要动很多人,排期一拖就是一个季度,而排序调整半天就能做完并且立刻消除风险。正确顺序是先排序后瘦身,因为排序解决的是丢什么,瘦身解决的是丢多少。 第二条是把这件事做成一个专项。一旦立项就要有目标、有里程碑、有复盘会,而它本质上只是一条构建断言。做成专项的结果通常是做完一轮之后没人维护,半年后原样复发。 第三条是把阈值定得太紧。有人量完之后把警戒线定在100万字节,理由是要留足余量。定得越紧越容易被绕过——第一次构建失败的时候大家还会认真看,第三次失败之后那条断言就被人注释掉了。 ## 最后一件不建议做的事 不要给Googlebot单独输出一个精简版HTML。 给不同来访者返回不同内容这条路历史上翻过车,JS判断移动端并自动跳转的SEO最佳实践 (https://zhangwenbao.com/js-judges-mobile-automatically-jumps-to-mobile.html)那篇复盘过其中一次。 技术上做得到,逻辑上也说得通——反正爬虫不需要那些交互数据。但它引入了一整类新风险:两个版本会随时间漂移,而漂移的方向你无法监控;一旦被判定为向搜索引擎和用户提供不同内容,代价远大于你省下的那点字节。 把重要的东西往前排是零风险的,给爬虫另做一份不是。在同样能解决问题的前提下,选那个不会在别的地方炸开的做法。 ## 什么时候需要重新量一次 跟着改动走,不跟着日历走。下面这几件事发生之后必须重量:换前端框架或者升级大版本、给商品卡片增加新字段、上线新语种、接入新的第三方脚本、把分页改成一页全展示、做一次视觉改版。 改动之后指标异动的排查顺序有讲究,GA4直接流量突然暴增的六类成因排查决策树 (https://zhangwenbao.com/ga4-direct-traffic-spike-diagnosis.html)那篇的决策树写法值得抄。 要让检查跟着改动走而不是跟着日历走,文件变动触发是个思路,inotify怎么用才能文件一变就触发 (https://zhangwenbao.com/linux-inotify-file-monitoring-inotifywait-incron-realtime-sync.html)那篇讲了实现。 最容易漏的是接入第三方脚本。因为那不是你写的代码,改动记录里可能只有一行“接入某某工具”,而它往页面里塞了多少字节,通常连接入的人都不知道。 ## 把这件事交给谁 这是个组织问题,而且是这类跨界问题里最典型的一个。它的检测在构建流程里,属于前端;它的后果在收录和结构化数据上,属于SEO;它的诱因是性能优化,属于另一个KPI。 前端和SEO在一个数字上达成一致就够了,服务器配置对SEO影响的20项必看清单 (https://zhangwenbao.com/website-server-configurations-seo-impact.html)那篇里也有好几项是这种需要两边共管的。 保哥的建议是把断言放在前端的构建流程里,把阈值的解释权放在SEO这边。前端负责让这个数字在每次构建时出现,SEO负责说明这个数字为什么是这个值。两边都不需要理解对方的全部逻辑,只需要在一个数字上达成一致。 ## 关于这套方法本身的自反 这篇文章讲的是“被截断的内容不会有人告诉你”,那它自己的证据链有没有被截断的地方? 把自己的证据链摊开写清楚是笨办法但有效,AI搜索的归因数据平台为什么不会给你 (https://zhangwenbao.com/ai-attribution-referral-incrementality-influence.html)那篇也用了同样的写法。 有,而且至少有三处。第一,46个样本全部是2026年8月上旬的一次快照,任何一个站在这之后改版,本文对它的描述就失效了。第二,抓取用的是普通浏览器身份,如果某个站对Googlebot返回的是另一份HTML,本文量到的就不是Googlebot看到的那一份。第三,2MB这条线是否按解压字节计算,官方文档并没有说死,本文是按更保守的口径推的。 > 这三处不确定性里,前两处会让个别数字失准,第三处会让整篇文章的结论方向发生变化。所以它被单独拿出来写了一整节,而不是塞在脚注里——一个可能推翻结论的前提,不该出现在比结论更小的字号上。 ## 最后一句 这件事在优先级列表上的位置其实不高。它不影响用户体验,不影响转化路径,多数站量完之后会发现自己很安全。 五分钟能做完又值得做的事不多,谷歌SEO技术清单的5大核心方向 (https://zhangwenbao.com/google-seo-technology-requirements.html)那篇里还有几件成本同样低、同样容易被跳过的。 它值得做的唯一理由是:检查它只要五分钟,而它出问题的时候不会有任何人告诉你。符合这两个条件的事情在这个行业里不多,遇到一件就顺手做掉。 ## 常见问题解答 ## 页面超过2MB会不会导致整页不被收录? 不会。官方原文写得很明确,Googlebot不会拒绝这个页面,它只是在2MB的位置停止取回,然后把已经拿到的那部分当作完整文件交给索引系统。页面照样会被索引,只是索引的是被切过一刀的版本。这也是这个问题特别难被发现的原因——覆盖率报告不会变红,抓取统计里那次请求是200,你的所有监控都显示一切正常,只有排在后面的那些内容在谷歌那边不存在。 ## 这2MB算的是压缩前还是压缩后的字节? 官方文档在同一段里用了两种表述,一处像是在说文件本身,一处像是在说线路传输量,没有把话说死。实测46个页面的压缩倍数中位数是7.55倍,这意味着按传输字节算超标的是0个,按解压字节算超标的是4个。保哥的选择是按解压字节算,理由不是确定官方就这么算,而是在两种可能的口径里,一个会漏报一个会误报,而漏报的代价是你永远不知道自己丢了东西。 ## 怎么快速判断自己的页面有没有风险? 最快的办法不需要任何工具:在浏览器里打开那一页,右键查看网页源代码,全选另存为本地文件,看文件属性里的大小。低于100万字节可以直接收工。这个动作要挑对页面,优先量变体最多的分类页和商品数最多的筛选结果页,这两类基本能覆盖九成风险。首页反而不是最危险的,因为首页的商品数通常是固定的,分类页会跟着SKU一起长。 ## 为什么我的页面没有图片却有2MB? 因为撑起体积的多半不是内容,是内容的影子。用了服务端渲染加客户端接管的框架,会把这一页渲染时用到的数据原样序列化成JSON再内联进同一个文件,于是同一份商品列表在文件里存在两次。实测里最极端的一个这样的标签单独就有2384424字节,比整条抓取上限还长287272字节。另外两路是内联的首屏样式和内联的矢量图标,某些站单这一项就占页面的57%。 ## 把结构化数据放在页面底部有问题吗? 规范上完全没问题,从来没有哪条规则要求结构化数据必须写在head里。它的问题是把一件本来零风险的事,变成了一件跟页面长度绑在一起的事。实测里有个头部品牌的分类页,唯一一段结构化数据的起点在2670014字节,落在截断点之外57万字节,等于写了但没生效。把它移进head是全部检查动作里唯一一个能永久免疫的,成本大约十分钟。 ## 页面瘦身能不能提升排名? 不能,页面长度本身不是排名因素。如果你量完发现远低于上限,请到此为止,不要顺手做一轮“页面瘦身优化”。这件事的全部价值在于避免一个二元的、灾难性的、不报错的失败,不在于把一个数字变小。把800KB减到400KB不会带来任何搜索侧收益,而这个区分很重要,因为它决定了你该在什么时候停手。 ## 能不能给爬虫单独输出一个精简版页面? 技术上做得到,但不建议。它引入了一整类新风险:两个版本会随时间漂移,而漂移的方向你没法监控;一旦被判定为向搜索引擎和用户提供不同的内容,代价远大于省下的那点字节。相比之下,把分页链接和结构化数据往文档前面挪是零风险的,效果也一样。在同样能解决问题的前提下,选那个不会在别的地方炸开的做法。 ## 多语言站点需要每个语种都量吗? 需要,而且这是最容易被漏掉的一环。同一套模板下不同语种的文案长度差别可能很大,保哥见过英文版1.7MB安全、德文版2.1MB超标的情况,原因只是德语复合词更长。你在英文版上做的全部测试,一次都覆盖不到那个真正出问题的版本。这一件不产生任何代码改动,只产生一张表,半天就能做完,但它是唯一能发现这类问题的动作。 ## 权威参考资料 ## 浏览器自动翻译把yes改成forks,问卷数据却看不出异常 - URL:https://zhangwenbao.com/browser-auto-translate-rewrites-page.html - 分类:技术SEO - 发布:2026-08-07 | 更新:2026-08-07 - 摘要:德语站退货率高出6.8个点,页面却一个字都没错——问题出在浏览器把已经是德语的页面又翻了一遍。本文讲清楚谁在改写你的页面、为什么合法值比报错更难发现,以及六件按风险排序的修复动作。 - 关键词:跨境独立站,国际SEO,多语言站,浏览器兼容 > **TLDR**:摘要:一家手工陶瓷餐具站的德语版退货率比英语版高6.8个点,其中41%勾的是与描述不符,可参数表、图片、翻译逐项查过全对。真相是德语页面的语言标记还写着英语,德国买家的浏览器把它当外语又翻一遍,参数表里“可用于洗碗机”被换成了个意思更弱的说法。皮尤2024年那份在线问卷也栽在同一机制上:是非题的yes显示成了forks,而代码里根本没这个词。本文拆清楚谁在改写你的页面、为什么合法值比报错更难发现、怎么用三条证据评估影响面,以及六件按风险排序的修复动作和一个会自己喊疼的探针。 > 摘要:一家手工陶瓷餐具站的德语版退货率比英语版高6.8个点,其中41%勾的是与描述不符,可参数表、图片、翻译逐项查过全对。真相是德语页面的语言标记还写着英语,德国买家的浏览器把它当外语又翻一遍,参数表里“可用于洗碗机”被换成了个意思更弱的说法。皮尤2024年那份在线问卷也栽在同一机制上:是非题的yes显示成了forks,而代码里根本没这个词。本文拆清楚谁在改写你的页面、为什么合法值比报错更难发现、怎么用三条证据评估影响面,以及六件按风险排序的修复动作和一个会自己喊疼的探针。 ## 德语站退货率高了6.8个点,可页面上一个字都没错? ## 一家做手工陶瓷餐具的站,德语市场卖得不错 这家站卖手工陶瓷餐具,单只碗45美元起,成套的餐具组能到320美元,主力市场是美国,德国和法国各有一个本地化版本,团队十来个人。三个语言版本用的是同一套模板,内容由专业译者翻,上线两年多。 多语言站到底是翻译还是重做,决定了后面所有的坑,从翻译外包走到原生再创作的多语言内容生产线 (https://zhangwenbao.com/multilingual-content-localization-production-pipeline-vs-translation.html)那篇把两种模式的成本和风险摆得很清楚。 德语市场的销量一直不错,客单价甚至比英语站还高一点。问题出在后端。 ## 德语站的退货率比英语站高6.8个点 这个差距持续了很久,久到已经被当成常识:大家默认德国消费者退货更积极,欧洲的退货政策也更宽松,所以差几个点很正常。 退货率高出一截先别急着归因到消费习惯,跨境电商退货率怎么从尺码、产品图到物流降下来 (https://zhangwenbao.com/cross-border-ecommerce-reduce-return-rate-prevention.html)那篇把常见成因按可控性排了序,可以照着逐项排除。 直到有人把退货理由拉出来分了个类。 ## 退货理由里“与描述不符”占了41% 如果是消费习惯造成的差异,退货理由应该分散在尺寸不合适、颜色不喜欢、临时改主意这些常见项上。实际分布不是这样:德语站有41%的退货勾的是“与描述不符”,而英语站这一项只有12%。 退货理由的分类口径值得单独设计,退换货政策页怎么写既做下单前的信任背书又接住售后搜索 (https://zhangwenbao.com/dtc-return-refund-policy-page-seo-trust-conversion-design.html)里那份理由清单可以直接拿去改自家的选项。 “与描述不符”是一个很具体的指控,它说的不是买家改主意,是页面写的和收到的东西对不上。这条线索一出来,问题就从消费习惯变成了产品页本身。 ## 第一轮排查:参数表、图片、尺寸全对 团队把德语站的产品页逐项对了一遍。直径、高度、容量、重量、材质、产地,全部和英语站一致,也和实物一致。图片是同一批,没有换过。 产品详情页该有哪些模块、每个模块承担什么信任任务,工业品详情页14个模块与三层信任阶梯 (https://zhangwenbao.com/b2b-pdp-14-module-high-conversion-blueprint.html)那份结构拆得很细,排查时可以当对照表用。 连小数点后的单位换算都查了——英寸换厘米、盎司换毫升,四舍五入的方向都对。 ## 德语翻译是专业译者做的,还复核过 第二个怀疑对象是翻译。这个也很快排除了:德语内容是找本地译者做的,交付时有一份术语表,上线前市场部的德国同事通读过一遍。 翻译过关不等于本地化过关,出海独立站关键词本地化的5个翻译陷阱与人审6步 (https://zhangwenbao.com/overseas-indie-keyword-localization-translation-traps-native-review.html)讲的正是专业译者也会漏掉的那几类问题。 后台里那份德语文案,随便挑一句出来读都很地道。问题是没有人想到要去看用户屏幕上显示的是不是这一句。 ## 第三轮怀疑的是物流 陶瓷易碎,运输破损是最自然的解释。可破损属于另一个退货理由项,占比只有7%,而且德法英三个市场差别不大,用的还是同一家转运。 排查顺序要从最容易证伪的开始,独立站结账页放弃率为什么超过七成、9个真实成因与5步诊断 (https://zhangwenbao.com/dtc-checkout-abandonment-9-real-causes.html)那套诊断顺序的思路可以直接搬到退货归因上。 查到这里,能想到的方向都试过了,事情就这么挂了大半年。 ## 客服把用户截图存成工单附件的那个习惯 转机来自一个很不起眼的流程习惯。客服团队处理纠纷时,如果买家发来页面截图,会把截图存进工单附件,理由是万一后面要走平台仲裁,手上得有证据。 客服系统里沉淀的东西比多数人想的多,DTC出海客服怎么搭多语种、四层SLA和工单分流 (https://zhangwenbao.com/dtc-overseas-customer-service-multilingual-4-layer-sla-ticket-routing.html)里那套工单结构决定了哪些证据能被翻出来。 这个习惯存了两年多,攒了几千张截图,从来没有人系统看过。它不是为了排查问题设计的,它只是碰巧把用户那一侧的画面留了下来。 ## 某天有人发现截图和后台不一样 一位客服在处理一单退货时,顺手把买家发来的产品页截图和自己后台看到的页面并排放着,想指出对方看错了。结果她自己愣了一下:参数表里有一行不一样。 不是排版不一样,是那一行的用词不一样。 ## 洗碗机那一行,写的不是他们写的词 德语版参数表里有一项写的是“可用于洗碗机”,用的是行业里通行的那个复合词。而买家截图上那一行,词换了,换成了一个意思接近但含义更弱的表达,读起来更像“清洗时需注意”。 同一个词在不同语言里的分量差得很远,德语版页面上加粗的那个词是个介词,翻译校验一路全绿 (https://zhangwenbao.com/minor-language-emphasis-markup-anchor-drift.html)就是一次很像的漏检。 对一个正在犹豫要不要买一套三百美元陶瓷餐具的人来说,这两个说法是两个决定。 ## 用户没有截错图,页面确实是那样显示的 第一反应当然是买家P图或者截了别家的图。但同一周里又翻出两张类似的截图,来自不同订单、不同时间,改动的位置一模一样。 想知道两边看到的是不是同一页,得有工具,渲染对比器怎么揪出爬虫和用户看到的页面不一样 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)那篇讲的比对方法,换成用户与后台的比对同样成立。 三个不认识的人不会P出同一处改动。到这一步只剩一个可能:页面在到达他们眼睛之前,被什么东西改过。 ## 复现这件事花了两天 难就难在复现。团队里所有人的浏览器打开德语站,看到的都是正确的那一行。换设备、换浏览器、清缓存、开无痕,都是对的。 直到有人把系统语言、浏览器界面语言和翻译设置全部调成德语用户的典型配置,那一行才终于变了。 ## 它只在特定条件下出现 条件比想象中窄:浏览器界面语言是德语、开着自动翻译、并且页面被浏览器判定成了另一种语言。三个条件同时满足才触发,缺一个都看不到。 按访问者特征分流的逻辑最容易造出这种只在特定人群里出现的问题,按IP自动跳转语言版本正在让半数页面进不了索引 (https://zhangwenbao.com/international-seo-ip-redirect-geolocation-language-switcher-ux.html)是另一个典型。 这解释了为什么两年多没人发现——公司里没有一个人的浏览器是这个配置,而符合这个配置的正是他们最重要的那批德国买家。 ## 为什么不是所有德国买家都受影响 这也解释了为什么退货率只是高了6.8个点,而不是高得离谱。满足那三个条件的买家只占德语站访客的一部分,其余人看到的页面完全正常。 影响面不是全有或全无,而是一个说不清楚的比例——这恰恰是它最难被察觉的原因。如果所有人都看到错的版本,问题第一周就爆了;只有一部分人看到,它就变成了一个说不清的背景噪声。 ## 那句话仍然是通顺的德语 最要命的一点在这儿。被改写之后那一行不是乱码,不是问号,不是英语原文,而是一句语法完整、拼写正确、读起来毫无异样的德语。 > 如果它显示成一串问号,两年前的第一个买家就会告诉你。它没有出错,它只是换了个意思。 ## 那两年里其实有过一次预警 复盘的时候他们翻出一封一年多前的客服邮件:一位德国买家问,你们页面上写的到底能不能进洗碗机,我这边看到的说法和产品册子上不一样。客服当时的回复是以产品册子为准,问题就结了。 用户那一侧的语言现实往往和你的设想对不上,德语页面下面挂着一半英语评论,这段字你管不了也不能装作没看见 (https://zhangwenbao.com/minor-language-user-review-language.html)讲的是同一种错位。 这封邮件把答案原原本本地摆在了桌上,只是当时没有人有理由把它当成一个系统性问题。一个孤立的疑问和一个模式之间,差的就是有没有人把它和别的疑问放在一起。 ## 这就是整件事最难缠的地方 系统层面没有任何异常:服务器返回200,页面加载正常,埋点记录着用户浏览了产品页、点了加购、完成了下单。数据库里那一行文案从头到尾没被改过一个字节。 同一批数据在不同条件下意思会变,26天的A/B测试跨过一场清仓,赢下来的11.4%是两段市场的加权中间值 (https://zhangwenbao.com/ab-test-field-period-external-shock.html)那篇讲的是时间这一维,本文讲的是显示这一维。 所有能报警的地方都没有报警,因为所有能报警的地方看的都是发出去的那份内容,没有一个地方看的是收到的那份。 ## 一句yes怎么会变成forks? ## 皮尤那份在线问卷收到过一条很奇怪的反馈 皮尤研究中心每次做完在线调查,都会请受访者留一句对问卷本身的意见:题目清不清楚、有没有意思、立场中不中立。这类反馈通常很平淡。 问卷类数据的坑通常不在题目上而在名单上,调研里没有一个非会员,结论却是写给非会员看的 (https://zhangwenbao.com/survey-data-eligibility-criteria-conclusion-boundary.html)拆的是入选条件那一关。 2024年那一波里冒出来一条不太一样的:你们把YES拼成了FORKS,好多处都是。本节的全部经过与数据出自皮尤研究中心:一个故障怎么把问卷里的yes换成了forks (https://www.pewresearch.org/decoded/2025/03/21/how-a-glitch-in-an-online-survey-replaced-the-word-yes-with-forks/)这一篇。 ## 接着又来了几条一模一样的 如果只有一条,多半会被当成个别人的笔误或者玩笑。可紧接着又来了几条:有人说每一道是非题的“是”都显示成了forks,也就是变成了forks和no二选一;有人说我的电脑对你们的选项有点问题,本该是yes的地方显示的是forks,很怪。 三个互不相识的受访者,报告的是同一处、同一种改动。这个组合和前面那家陶瓷站遇到的一模一样。 ## 这不是他们独有的问题 皮尤去查了一圈,发现这事早就在别处发生过。至少从2023年初开始,好几家机构的在线问卷和表单里都出现过同样的现象,本该是yes和no的选项,变成了forks和no。 搜索引擎那一侧的自动翻译是另一条相关的线,Google自动翻译正在悄悄抢走你的国际流量、外贸站怎么识别和防御 (https://zhangwenbao.com/google-translated-results-international-traffic-defense.html)讲的是流量层面的影响。 有人在Reddit的一个专门收集软件怪事的版块贴过截图,来源是好几家不同机构的问卷。也就是说,这是一个跨站点、跨组织的共性问题,只是没人把它当回事。 ## 根因是两个问题叠在一起 皮尤最后查清楚了,是两件事撞在了一块儿,任何一件单独发生都不会有事。 这种“两个小毛病相乘等于一个大事故”的结构,在故障排查里非常典型,也是为什么单看任何一方都查不出问题。 ## 第一个问题:页面被浏览器当成了西班牙语 他们那份问卷是英文的,可某些浏览器认为这一页可能是西班牙语,于是弹出了“要不要翻译成英语”的提示,或者干脆自动翻了。 语言这件事在国际站上牵扯的东西比想象中多,国际化SEO和hreflang怎么做、多语言站的避坑清单 (https://zhangwenbao.com/international-seo-hreflang-complete-guide.html)可以先当一份总览读。 误判的源头是页面上一个弹层:点击“查看更多填写说明”会弹出一小块内容。这个弹层的脚本带来了一些语言标记上的混乱,部分浏览器据此判定这一页含有别的语种。 ## 一个弹层脚本引发的误判 值得琢磨的是,这个弹层本身完全正常,它的功能是显示填写说明,帮受访者理解题目。它不是广告,不是第三方插件,是问卷自己的一部分。 装上去的组件越多,互相打架的概率越高,Shopify装太多App拖慢店铺还烧钱、应用栈精简与冲突排查 (https://zhangwenbao.com/shopify-app-stack-bloat-performance-cost-conflict-audit.html)那套排查方法对任何平台都成立。 把整份问卷推向翻译的,是一个为了让问卷更好懂而加的功能。这类反噬在前端里不算罕见,只是很少有人有机会追到根上。 ## 第二个问题:翻译服务自己有个错 第二件事更离奇。如果你告诉某个主流翻译服务“yes”是一个西班牙语单词,再让它翻成英语,它给出的结果是forks。 机器处理语言时的系统性偏差不止翻译一处,多语言AI可见性怎么做、翻译内容为什么在AI检索里吃亏 (https://zhangwenbao.com/multilingual-ai-visibility-geo-optimization.html)给了另一个角度的例子。 这不是逻辑推理能推出来的结果,就是一个具体的、可复现的错误条目。皮尤在文章里放了截图,任何人都能自己试一遍。 ## 两个问题合在一起才出事 于是链条闭合了:浏览器误以为页面是西班牙语,自动把它“翻译”成英语;由于页面本来就是英语,绝大部分内容翻完还是原样,只有yes这一个词被换成了forks。 整页只错了一个词,而这个词恰好是每一道是非题的一半选项。 ## 还有一处更隐蔽的改写 同一次翻译还动了另一个地方。有一道题问的是“到今天为止,你更偏向共和党还是民主党”,其中那个表示“偏向”的动词被换成了“阅读”,整句话变成了“你更多地阅读共和党还是民主党”。 词形变化是机器最容易出错的地方,小语种最想抢的那族词在英语里两个后缀就够、德语里要写五遍 (https://zhangwenbao.com/minor-language-comparative-superlative-keyword-forms.html)把这件事讲得很具体。 原因和forks是一路的:那个英文动词的拼写正好是某个西班牙语动词的一个变位形式,而那个西班牙语动词的意思是“读”。 ## 没有一个人报告了这一处 forks那处被好几个人报告了,因为forks在那个位置太荒谬,读到就知道不对。而“阅读共和党还是民主党”这句话,读起来只是有点别扭。 越是不显眼的措辞越没人追究,独立站文案里最贵的字是“更”、一句比较级要你拿出整套对比测试 (https://zhangwenbao.com/expert-endorsement-substantiation-by-claim-wording.html)讲的是同一类被忽略的字。 > 荒谬的错误会被举报,别扭的错误只会被将就着答完。而被将就着答完的那些,正好都留在了数据里。 ## 大小写也被动过 皮尤在复现时还注意到一些更细的变化,比如某些句子开头的大小写不对了。这类改动没有任何人在反馈里提过。 字符层面的细微改动经常在别处冒头,URI编解码器怎么处理中文URL、UTM参数转码与乱码网址还原 (https://zhangwenbao.com/uri-codec-percent-encoding-encode-decode-guide.html)那篇处理的也是这一层的问题。 能被用户发现并主动告诉你的,永远是改动幅度最大的那一小部分;剩下的没人说,不是因为没发生,是因为不值得说。 ## 这个错为什么会一直躺在那儿 值得多想一层的是:翻译服务里那个把yes译成forks的条目,为什么没被修掉。原因大概是它触发条件太窄——正常人不会把英文的yes当成西班牙语词去翻译,只有机器在误判语言的时候才会这么干。 只有在特定条件下才触发的错误最难发现,一个尾逗号就能让整页结构化数据失效 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html)就是这类问题的另一个形态。 一个只有在另一个系统出错时才会被触发的错误,等于永远不会被自然发现。它需要两个系统同时不对劲才现形,而任何一方单独测试都测不到。 ## 这种“两方各自正常”的结构很常见 拿独立站举例:你的模板输出的价格带三位小数,支付网关只取两位;单独看,模板没错,网关也没错。只有当某个币种的最小单位恰好落在第三位时,才会出现一分钱的对不上。 两个组件各自都对、合起来出问题,装了SEO插件却冒出两个canonical和两套结构化数据怎么归一 (https://zhangwenbao.com/cms-seo-plugin-theme-tag-conflict-duplicate-canonical-title-og-schema-cleanup.html)是最常见的一例。 这类问题的排查难点在于责任分不清楚,两边都能拿出证据说自己没错。而事实是两边确实都没错,错的是没有人负责的那条缝。 ## 回到陶瓷站那一行 那家陶瓷站的情况和这个是同一个机制,只是方向反了一遍:他们的德语页面被浏览器判定成了别的语言,于是被“翻译成德语”,而页面本来就是德语,翻完之后大部分不变,只有少数几个词被换成了同义词。 页面语言和数据层语言可以是两回事,小语种页面正文越本地化越好,结构化数据里却要反着写回国际格式 (https://zhangwenbao.com/minor-language-structured-data-inlanguage-locale-schema.html)讲的正是这层分工。 换掉的那几个词里,恰好有一个是关系到能不能进洗碗机的技术承诺。 ## 方向反过来,问题反而更隐蔽 值得比较一下两边的差别。皮尤那边是英语页面被当成西班牙语翻成英语,改动落在一个荒谬的词上,很快被举报。陶瓷站那边是德语页面被当成外语翻成德语,改动落在一个同义词上,没人觉得不对。 被翻成一门你不懂的语言,你会立刻发现;被翻成你本来就在用的那门语言,你可能永远发现不了。后者才是多语言站真正的风险形态。 ## 为什么是这类词最容易被换 翻译服务处理复合词和行业术语的时候,最容易给出一个“意思接近但不完全等价”的替代。日常用语反而不太出问题,因为常见搭配的训练数据足够多。 术语在不同语言里的对应关系需要专门做,多语言市场关键词调研的跨文化语义与本地化变体 (https://zhangwenbao.com/multilingual-keyword-research-cross-cultural-localization-query-language.html)那套流程可以顺带把术语表建起来。 坏消息是,产品页上最重要的那些话,恰恰全是行业术语:材质、认证、耐受温度、可否机洗、是否食品级。翻译最不擅长的那一类词,正好是你页面上最不能出错的那一类词。 ## 代码里根本没有forks这个词 ## 供应商反复确认了三遍 皮尤收到第一条反馈之后,立刻找了负责编程问卷的供应商。对方当场检查了一遍问卷程序,确认forks这个词在代码里一次都没出现过。 查不出来的时候回到最原始的记录,AI爬虫到底有没有抓你的站、日志分析一步步挖真相 (https://zhangwenbao.com/seo-log-file-analysis-guide.html)示范的就是这种从原始记录反推的路子。 后来又查了两遍,结论一样。这不是敷衍——问卷程序是他们写的,全文搜索一个单词是几秒钟的事,答案不可能有第二种。 ## 上线前的测试做得很扎实 更值得说的是测试。那份问卷在发出去之前,做过相当完整的人工测试:好几位工作人员像真实受访者一样从头到尾答了很多遍,找错别字、找逻辑错、找题目跳转和随机化有没有问题。 检查清单越完整越容易产生已经查全了的错觉,企业网站SEO审计到底该查什么、从抓取到AI可见度的完整框架 (https://zhangwenbao.com/enterprise-website-seo-audit-framework.html)里那份清单也标了自己的盲区。 他们还特意在不同设备和不同浏览器上都看过,确认显示正常。这套流程比绝大多数独立站的上线前检查严格得多。 ## 没有一个测试者见过forks 结果是零。所有测试都通过了,所有人看到的都是正常的yes。问卷就这么发了出去。 测试没有失职,测试只是测了测试者能看到的那个页面。这句话拆开看很平常,合起来是这类问题的全部答案。 ## 测试用的是测试者的浏览器 这是所有人工测试的共同前提,也是它最大的盲区。测试者的浏览器界面语言、系统区域设置、翻译偏好、装了哪些扩展、开没开某些实验特性,全都是测试者自己的。 环境不同结果就不同,这在渲染问题上表现得最明显,JS渲染的页面Google抓不到先从这几种情况查起 (https://zhangwenbao.com/javascript-rendering-seo-csr-ssr-debugging.html)讲的正是不同环境下的差异。 而这些设置恰恰是触发条件的一部分。测试再多遍,只要环境不变,触发不了就是触发不了。 ## 复现是靠一次偶然 皮尤最后能查清楚,靠的是团队里一位成员在测试问卷时终于亲眼看到了forks。在此之前,他们已经在网上搜过、问过供应商全公司有没有人见过,答案都是没有。 把偶发现象归类是排查的第一步,Google抓取报告怎么读、五类问题URL的占比与排查顺序 (https://zhangwenbao.com/google-crawling-issues-url-mistakes-diagnosis.html)给了一套按占比排序的方法。 那一次看到之后,线索才终于有了实体:她当时用的是某个主流浏览器,而她此前用同一个浏览器测过很多次,都没出现。 ## 退出重进,问题就消失了 更麻烦的是它不稳定。那位成员退出问卷再重新进去,同一个浏览器,异常就没了。这种“看到了但抓不住”的状态,是排查里最消耗耐心的一种。 时有时无的现象背后往往有一个条件开关,人机验证屏被谷歌当正文索引、页面掉收录还把规范网址判给了别的站 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)就是这样一次。 他们据此判断:这个问题很罕见,因为整个团队前前后后走过几十遍甚至上百遍流程,才撞上这么一次。 ## 罕见不等于影响小 这里有个很容易滑过去的推理跳跃。“我们跑了一百遍才见到一次”推不出“用户里只有百分之一会遇到”,因为你和用户不是在同一个概率空间里抽样。 单看一页没问题、放到全站就是另一回事,大量没用的页面拖垮流量、索引膨胀的诊断与处置 (https://zhangwenbao.com/index-bloat-mechanism-sitewide-diagnosis-decision-matrix.html)讲的是同一种规模效应。 > 你跑一百遍是同一个环境重复一百次,用户是一百个不同环境各跑一次。前者的罕见程度说明不了后者。 ## 三个条件同时满足才触发 回到陶瓷站那边,触发条件后来被拆得很清楚:浏览器界面语言是德语、翻译功能处于开启状态、页面被判定成了非德语。 触发条件藏在请求本身里的例子不少,老用户打不开的那个页面、SEO工具全都返回200 (https://zhangwenbao.com/request-header-too-large-400-431-cookie-seo-blindspot.html)那次问题就出在工具不带Cookie这一条。 对公司里的人来说,这三个条件几乎不可能同时成立,因为大家的浏览器是英文或中文界面。对德国本地买家来说,前两个条件是出厂默认,第三个由页面自己提供。 ## 你的用户里可能有一整片人天天满足这三个条件 这就是罕见与不罕见的分界。在团队的环境里它是万分之一,在目标市场的真实环境里它可能是常态。 监控看不到的那部分往往集中在同一类对象上,盯了三年网站速度、页面上近一半资源在监控里是一排零 (https://zhangwenbao.com/cross-origin-timing-allow-origin-web-vitals-blind-spot.html)是很好的对照。 一个故障的发生率不是一个数字,是一个分布;而你所在的位置往往正好在这个分布最安全的那一端。 ## 这件事对测试流程的启示 结论不是要求测试者装十种浏览器。真正可行的是把几个关键环境变量列出来,在测试清单里明确写出该用哪一组:界面语言、区域设置、翻译开关、常见扩展。 测试环境要贴近真实用户环境,DTC出海网络分线5场景实战、广告支付客服远程抓包的独立IP避坑 (https://zhangwenbao.com/dtc-overseas-network-segmentation-5-scenario-ip-isolation.html)里那套环境隔离思路可以借用。 一组配置多花不了十分钟,而它覆盖的是你最主要的那个海外市场。这笔账很好算。 ## 比配置更省事的一招 如果连这个都嫌麻烦,还有个更轻的替代:把客服收到的用户截图当成一类数据来管。那家陶瓷站两年多的答案就藏在这堆截图里,只是从来没人翻过。 要知道对方看到了什么,先得知道内容是怎么一步步生成的,搜索引擎抓取和渲染DOM分几步、看懂才知道哪里丢内容 (https://zhangwenbao.com/dom-crawling-rendering-indexing-seo-optimization.html)把这个过程拆开了。 用户截图是唯一一份记录了“用户那一侧实际画面”的材料。它不需要你搭任何系统,只需要有人偶尔看一眼。 ## 这类问题最难的其实是归属 技术上定位清楚之后,还有一道更现实的关:这件事归谁管。它跨了前端、内容、本地化、客服四个口子,任何一个单独拎出来都能说不归自己。 没有归属的问题会一直漂着,哪怕所有人都同意它确实存在。陶瓷站后来的做法是把它挂到本地化负责人名下,理由很简单:损失体现在德语站的退货率上,谁的指标受损谁负责。 ## 按指标归属比按技术归属好使 按技术栈分工,这件事会在前端和本地化之间踢来踢去,因为改的是前端属性、影响的是本地化效果。按受损指标分工就没有争议,指标是谁的,事就是谁的。 这个分法还有个额外好处:负责人有动力去查这件事到底值多少钱,而不是把它当成一个技术债默默放着。 ## 它为什么长期没人看 因为它被归类成了纠纷证据,不是产品数据。存它的目的是万一要仲裁,而不是万一要排查。归类决定了它被放在哪个文件夹里,也决定了谁会打开那个文件夹。 很多问题查不出来,不是因为证据不存在,是因为证据被存在了一个不会有人为了这个问题去翻的地方。 ## 顺手说一句复现这件事的标准 皮尤那次能定案,靠的是终于复现了一次。复现在这类问题里的地位很特殊:它不是锦上添花,是唯一能把猜测变成结论的那一步。 没有对照就容易把噪声当信号,量出74%的页面对爬虫和用户不一样、补上对照后只剩2.2% (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)那次复盘就是靠加对照才定的案。 复现的标准也要说清楚:不是“我也遇到了类似的怪事”,而是“在明确写下的这组条件下,每次都能看到同一处改动”。前者是轶事,后者才是证据。 ## 复现不出来时的次优选择 如果实在复现不了,退而求其次的做法是收集足够多的独立目击。三个互不相识的人报告同一处、同一种改动,这个组合本身就有相当的证明力。 陶瓷站那边就是先靠三张截图站住脚,才有人愿意花两天去调环境复现。先有一个说得过去的理由,才会有人给你排时间,这是所有内部排查的现实。 ## 那两年到底损失了多少 粗算一笔:德语站退货率高出6.8个点,其中“与描述不符”这一项占了大头。按他们的德语站年订单量和平均客单价推,两年多下来光是退货处理和运费就是六位数美元,还不算被劝退的那些人。 把损失算成钱是推动修复的前提,DTC电商SEO怎么汇报老板才看得见价值 (https://zhangwenbao.com/dtc-ecommerce-seo-reporting-stakeholder-communication.html)里那套四板块的写法可以直接借来写这份账。 被劝退的那部分永远算不出来,因为一个看到“清洗时需注意”而放弃下单的人,不会在任何一张表里留下记录。 ## 已经收上来的数据还能不能用? ## 故障查清楚之后,还有个更难的问题 修掉bug只是第一步。真正让人头疼的是第二步:在故障存在的那段时间里已经收上来的数据,还算不算数。 一个数字能代表多少人,取决于它经过了哪几道门,满意度调查那个92%只覆盖了7.4%的买家 (https://zhangwenbao.com/satisfaction-survey-denominator-gates.html)把六道门逐一拆开了。 这个问题没法直接回答,因为你不知道谁看到了被改写的版本。皮尤的处理办法很值得抄,一共三件事,每一件都不依赖你能观测到故障本身。 ## 第一件:数一数有多少人提到了它 最直接的一个数:在所有受访者里,有多少人在反馈里提到了这个异常。答案是0.2%。 提及类指标的天然偏低是个通病,网站收录速度实操指南与三平台300站实测对比 (https://zhangwenbao.com/seo-kpi-guide.html)里那些靠主动上报的数据也有同样的问题。 这个数字看着让人松一口气,但它只能当下限用,不能当结论用。 ## 他们自己写明了两条保留 皮尤在文章里主动写了两句:看到异常的人未必都会在反馈里提;还有些人可能一看到这种明显的错误就直接放弃不答了,那么他们连留反馈的机会都没有。 把自己这个数字的两个漏洞写在同一段里,这是判断一份材料值不值得信最实在的标准。愿意主动说清自己哪儿测不准的人,通常在别处也不会糊弄。 ## 第二件:和去年同一批题目比分布 这一步是精华。那份问卷里每一道是非题,上一年的同类调查都问过。他们把受影响的每道题目在两年的回答分布拉出来对比,只看两年里都是在线作答的那部分人。 跨期比较之前先确认口径没变,跨年数据能不能直接比、一条五年趋势线上有三处口径变更 (https://zhangwenbao.com/trend-line-break-in-series-comparability.html)给了识别断点的做法。 如果forks让一部分人误答,或者让某类人退出,那么今年的分布应该会和去年拉开距离。实际结果是两年非常接近。 ## 为什么要限定“只看在线作答那部分” 因为电话作答的人根本不可能遇到这个问题,把他们混进来会稀释信号。做对照的时候,先把不可能受影响的那部分剔出去,剩下的对比才有力度。 把不该进来的先剔出去,剩下的对比才有力度,GA4里的机器流量怎么揪出来再拦掉 (https://zhangwenbao.com/spam-traffic-ga4-detect-filter-prevent.html)讲的就是这个清理动作。 这个动作在独立站也一样:查移动端的问题,就别把桌面端的数据混进同一个分母。 ## 第三件:看中断率 第三条证据用的是另一个完全独立的指标:有多少人登录了问卷但没答完。这一年是53人,占在线登录者的2%;上一年是89人,4%。 半途放弃的信号常常藏在控件上,下拉框看着规整,却在独立站表单里吃掉你的询盘和订单 (https://zhangwenbao.com/form-dropdown-control-selection-conversion.html)那篇把这类中断的成因拆得很细。 如果forks把人吓跑了,中断率应该上升。实际上它比没有这个故障的那一年还低了一半。 ## 三条证据指向同一个方向 提及率很低、分布和去年一致、中断率不升反降。三条各自都不足以定案,合在一起给出的图景相当一致:这次故障没有对数据产生实质影响。 皮尤据此决定正常分析和发布,同时把整件事的来龙去脉公开写了出来。 ## 这三步的共同点 值得单独指出:这三件事没有一件是去测量故障本身的。第一件测的是有多少人抱怨,第二件测的是结果分布,第三件测的是完成行为。 能不能用现成数据回答新问题,取决于当初的框架设计,先把测量框架设计清楚再动GA4事件 (https://zhangwenbao.com/measurement-framework-before-ga4-setup.html)讲的正是这一层。 > 当你没法直接观测一个东西时,就去观测它一定会留下影子的地方。三个不同的影子指向同一个形状,那个形状就八九不离十。 ## 换到独立站,这三步分别是什么 皮尤的做法 | 独立站的对应动作 | 数据从哪来 | 数有多少人提到 | 翻工单与评价里提到页面显示异常的比例 | 客服系统 | 和去年同题分布比 | 同一SKU在故障期与非故障期的转化率、加购率对比 | 分析工具 | 看中断率 | 结账流程各步的流失率、表单放弃率 | 埋点 | 用错指标比没有指标更麻烦,GA4核心指标解析的4个常见错误 (https://zhangwenbao.com/google-analytics-metrics-misuse-guide.html)把几个最容易误读的口径讲清楚了。 三列都不需要新建任何东西,用的全是手上现成的数据。 ## 陶瓷站那次的三个数 他们后来照着这个套路复了一次盘。工单里明确提到页面文字不对的,两年多一共11单,占德语站订单的千分之零点几,低得几乎可以忽略。 多少差异才算真差异,是有公式可算的,独立站A/B测试样本量怎么算、避免假胜利的3个公式 (https://zhangwenbao.com/dtc-ab-test-sample-size-3-formulas.html)可以拿来给这几个数定门槛。 而后面两个数完全不是这样:德语站的“与描述不符”退货占比是英语站的三倍多,加购到下单的转化率也比英语站低了将近两个点。第一个数说没事,后两个数说有事,而后两个数不需要任何人开口。 ## 三个数不一致的时候信哪个 信不需要用户主动开口的那个。提及率天然偏低,因为它要求用户既发现异常、又愿意花时间告诉你、还得找得到告诉你的入口,三道门下来能剩多少可想而知。 行为数据比自报数据更耐得住推敲,别只看热图哪里红、从行为数据读懂用户心理的研究方法 (https://zhangwenbao.com/read-user-psychology-from-behavioral-data.html)讲的正是这个取舍。 而转化率、退货率、流失率这些是行为留下的痕迹,不需要任何人动嘴。 ## 皮尤那次为什么提及率就够用 因为他们的问卷主动、明确地问了每个人一句对问卷本身的意见,那道题就摆在那儿。这大幅降低了反馈门槛,所以0.2%这个数比一般场景下更可信。 一个指标可信不可信,取决于它的采集方式,SEO数据分析从指标体系到异常诊断的完整路径 (https://zhangwenbao.com/seo-data-analysis-guide.html)把采集与解释分开讲了。 而多数独立站没有这样一个入口。没有专门问过的地方,沉默不代表满意,只代表没地方说。 ## 如果没有去年同期的数据怎么办 皮尤那套第二步的前提是同一批题目上一年问过。很多站没有这个条件——页面改过版、SKU换过、分类重整过,跨年比较根本对不上。 替代方案是换一个维度做对照:不比时间,比语言版本。同一款产品在英语站和德语站的转化率、加购率、退货率放在一起看,两边的差距如果远超其他品类的常规差距,那就是信号。 ## 横向对照有时候比纵向更干净 纵向比要求时间上可比,横向比要求人群上可比,两个都不完美。但横向比有一个纵向比没有的好处:两边的数据是同时产生的,不存在期间世界变了这个问题。 手上有两条路的时候,优先选那条你更清楚它哪里不准的路。知道偏差在哪,比偏差小更重要。 ## 如果影响确实存在,数据该怎么处理 顺带说一种皮尤没遇上但你可能遇上的情况:三条证据都指向有影响。那时候不是把数据全扔掉,而是把受影响的范围圈出来。 圈定范围需要能批量核对的工具,GSC URL检查API怎么在2000条配额下做批量收录监控 (https://zhangwenbao.com/gsc-url-inspection-api-bulk-index-monitoring.html)给了一条可落地的管线。 圈的办法是找一个能区分“受影响”和“未受影响”的字段。比如语言版本、浏览器语言、故障起止日期,用它把数据切成两半,未受影响那一半照常用,受影响那一半单独标注。 ## 标注比删除更有用 删掉是最省事的处理,也是损失最大的。被标注的数据仍然可以回答一部分问题,比如趋势方向和人群构成;被删掉的数据什么问题都回答不了。 这也是为什么故障的起止时间必须记准。没有准确的时间边界,你连圈都圈不出来,只能一刀切。 ## 还有一个能顺手加的入口 成本最低的做法是在产品页底部加一行小字,问一句“这一页有没有哪里看着不对”,点开是一个两行的输入框。它一年可能只收到几十条,但那几十条里有一半是你在别处永远看不到的。 页面上多一个小入口带来的变化经常超出预期,博客文章配个AI摘要按钮、点击数据为什么能涨691% (https://zhangwenbao.com/blog-ai-buttons-ux-geo-guide.html)就是一个实测例子。 那家陶瓷站后来加了这一行,上线第一个月收到37条,其中4条描述的正是被改写的那几个词。 ## 谁在你和用户之间改写页面? ## 浏览器的自动翻译只是其中一个 把这件事想明白之后会发现,页面从你的服务器发出去到落在用户眼睛里,中间要经过好几层,每一层都有权改它。翻译只是最容易被抓到的那一层,因为它改的是文字。 中间层能不能正确理解你的页面,取决于结构写得规不规范,语义化HTML到底影响AI抓取吗、拿样本页跑一遍就知道 (https://zhangwenbao.com/semantic-html-content-extractability-engineering.html)用实测回答了这个问题。 下面这份清单不算长,但基本覆盖了常见的改写者。列出来的目的不是让你去对抗它们,而是让你知道自己的页面到底会被谁动手。 ## 浏览器内置的翻译 主流浏览器都自带这个功能,触发条件是它判定页面语言和用户偏好语言不一致,这一点在Chrome帮助:更改浏览器的语言与翻译网页 (https://support.google.com/chrome/answer/173424)里写得很直白。判定依据主要是页面上的语言标记和内容采样,两者都可能出错。 它改的范围是整页可见文本,包括按钮文案、表单标签、下拉选项、错误提示。也就是说,你精心打磨的行动号召按钮,用户看到的可能是一句机器翻回来的话。 ## 装在浏览器里的翻译扩展 比内置的更激进。有些扩展会自动翻译所有非母语页面,有些会把原文和译文并排显示,还有些会在鼠标划过时弹出翻译。它们的改写强度和范围因扩展而异,完全不受你控制。 自动转换类工具的误伤在中文里同样常见,中文简繁转换器怎么用、台湾香港用语本地化与那个会转错的头发 (https://zhangwenbao.com/chinese-converter-simplified-traditional-localization-guide.html)是个很具体的例子。 这类扩展在跨境购物人群里的安装率不低,尤其是买家习惯从多国站点比价的品类。 ## 广告拦截器会删掉一些元素 拦截器按规则匹配删除元素,而规则是社区维护的,误伤时有发生。被误删的常见对象包括:类名里带promo、banner、sponsor的区块,以及某些浮动的优惠提示。 页面上哪些块算主体内容、哪些像附加物,判断标准并不只有你一家在用,主体内容占比与模板稀释的7大陷阱 (https://zhangwenbao.com/main-content-ratio-boilerplate-dilution-page-layout.html)讲的正是这套判断。 如果你的限时折扣条恰好用了一个像广告的类名,那么装了拦截器的用户根本看不见它,而你的埋点会记录成“曝光了但没点”。 ## 隐私扩展会动链接和脚本 有些隐私工具会清理URL上的追踪参数,有些会拦截统计脚本。前者会让你的渠道归因失真,后者会让一部分用户在数据里彻底消失。 链接被改写之后会衍生出一堆等价地址,同一个页面11种URL写法都返回200、查重复内容时一条都不会报 (https://zhangwenbao.com/url-path-normalization-case-slash-duplicate-seo.html)讲的是这一层的后果。 这类改写不影响用户看到的内容,但会系统性地改变你看到的数据,而且被改掉的那批人往往是同一种人。 ## 密码管理器会往表单里塞东西 自动填充会往输入框里写值,有时候还会插入自己的图标和浮层。在结账表单里,它偶尔会填错字段,比如把公司名填进地址第二行。 由此产生的地址错误会变成物流问题,而物流问题最后会变成“与描述不符”之外的另一类退货。 ## 企业代理与安全网关 B2B场景里尤其要注意。很多公司网络会经过安全网关,网关可能改写页面、剥离脚本、甚至替换证书。你的询盘表单在某些公司网络里提交不了,就是这么来的。 请求在到达应用之前会先过好几层,Apache .htaccess的6层综合治理、重写缓存canonical与HSTS (https://zhangwenbao.com/apache-htaccess-seo-6-layer-rewrite-cache-canonical-hsts.html)把这几层的先后顺序讲清楚了。 这类问题的特征是集中在少数几个客户身上,反复出现,而你在自己网络里怎么都复现不了。 ## 系统级的显示设置 深色模式的强制反色、系统字体替换、放大到200%的显示缩放,这些都会改变页面的实际呈现。它们不改文字内容,但会改变可读性和布局。 样式层出问题的形态往往是看不见而不是报错,关键渲染路径怎么优化、阻塞渲染的CSS和JS拖慢首屏的机制 (https://zhangwenbao.com/critical-rendering-path-render-blocking-css-optimization.html)把这条链讲清楚了。 其中最容易出事的是强制深色:浅色文字配浅色背景,反色之后可能变成深配深,直接看不见。 ## 读屏器读到的是另一套内容 无障碍工具不读你的视觉布局,它读的是结构和标签。如果你的参数表是用视觉排版拼出来的,读屏器读出来的顺序可能完全对不上。 不看画面只看结构的读者越来越多,AI浏览器为什么是弯路、智能体读的是无障碍树不是页面截图 (https://zhangwenbao.com/ai-agent-accessibility-tree-not-pixels.html)那篇讲的正是这批读者。 这一层的改写不是替换,是重排。同样一页内容,视觉上是一张表,被读出来可能是一串没有归属的数字。 ## AI浏览器和代理读的也不是你那张页面 新一代的AI浏览器和自动化代理在读页面时,用的同样是结构化的那一层,不是渲染出来的画面。你在视觉上做的强调、对比、层级,对它们基本不存在。 入口在碎裂,读者的构成也在变,AI浏览器之战打响后出海独立站的流量该往哪接 (https://zhangwenbao.com/ai-browser-wars-search-distribution-fragmentation-traffic.html)给了一份对流量结构的判断。 这意味着显示层和数据层的分裂在AI时代只会更明显,因为读者里多了一批只看数据层的读者。 ## 还有一层是你自己请来的 第三方脚本也算改写者:评价插件、客服挂件、推荐位、A/B测试工具、同意管理弹层。它们由你主动装上,但装上之后就按自己的逻辑改动页面。 你请来的服务也可能在背后替你做决定,AI引用归零监控却没报警、托管主机可能正悄悄拦AI爬虫 (https://zhangwenbao.com/managed-wordpress-blocks-ai-crawlers-citation-loss.html)就是一次这样的经历。 其中最容易出事的是那些会替换文案的:多语言插件、动态定价挂件、库存提示组件。它们和浏览器翻译的区别只有一个——出了事你还能找到人。 ## 它们的执行顺序也会变 更细的一层是时序。这些脚本谁先跑谁后跑,取决于加载顺序和网络状况,而不同用户的网络状况不一样。于是同一个页面在不同人那里可能呈现出不同的最终状态。 自动化链条上的东西会随时间走形,那套AI自动化不是哪天突然坏的、它从第二周就开始走形 (https://zhangwenbao.com/ai-automation-runtime-rot-guardrails.html)讲的是同一类渐变。 这解释了很多“偶发”的界面异常:它们不是随机的,是时序敏感的,而时序在你这台机器上永远是那一种。 ## 这些层的共同点 把它们排在一起会发现一个规律:它们全都在你的服务器之外,全都不受你的代码控制,而且全都不会给你任何回执。 同一个地址返回不同内容这件事,缓存层也在做,决定收录哪一版页面的不是你的配置、是10分钟前路过的那个用户 (https://zhangwenbao.com/vary-header-cache-fragmentation-googlebot-version-seo.html)说的就是它。 > 你的服务器只知道自己发出了什么,它永远不知道对方收到的是什么。中间那几层不给回执,也不欠你回执。 ## 这么多层,先管哪一层 清单列完难免让人发怵,但真正需要处理的只有少数几层。排优先级的标准有两条:这一层影响多少人,以及这一层你有没有可用的抓手。 按这两条筛,多语言站的第一优先级永远是翻译层——它影响的是整个目标市场,而你手上正好有语言标记这个抓手。广告拦截器影响面也不小,但抓手很弱,只能改类名,收益不确定。 ## 抓手强弱决定了值不值得做 密码管理器和安全网关这两层,影响面小、抓手也弱,一般不值得专门处理,出问题时按个案解决就好。读屏器和AI代理这一层的抓手很强,就是语义化标签,而且顺带还能提升可访问性。 把清单按影响面和抓手强弱画成四个格子,该做的那两格自己就跳出来了。这比按技术难度排优先级靠谱得多。 ## 你唯一能控制的是交给它们的信号 既然改不了它们,能做的就只有一件事:把信号给准,让它们不误判、不乱改。这些信号包括页面的语言标记、局部内容的翻译开关、语义化的标签结构、以及一些明确的元数据。 把内容当结构化数据来生产,本质上就是在给中间层发准信号,内容工程、AI搜索时代内容人的新手艺 (https://zhangwenbao.com/content-engineering-structured-content-ai-search.html)讲的是这套思路的全貌。 这批信号的成本很低,多数是几行属性。而它们的作用是把“中间层会怎么处理我的页面”从一件随机的事,变成一件大致可预期的事。 ## 下一节讲这批信号具体怎么给 先记住一个判断顺序:先修语言标记,再圈定不许翻译的内容,最后才考虑更激进的手段。多数站修完第一步问题就消失了大半。 那家陶瓷站的整个事故,根子就在第一步上——他们的多语言方案换了内容,却没换那一个属性。 ## 为什么合法值比报错更难对付? ## 故障的输出只有两种 把这两年遇到的这类问题归拢一下,会发现一个很朴素的分类:故障要么吐出一个系统认不出的值,要么吐出一个系统认得出、但意思变了的值。 格式合法和语义正确是两回事,JSON格式化工具怎么把JSON-LD结构化数据调试这件事讲透 (https://zhangwenbao.com/json-formatter-jsonld-structured-data-debug-guide.html)里那些能通过校验但意思不对的例子很有代表性。 这两种故障的命运天差地别,而决定命运的不是故障本身有多严重。 ## 非法值会被立刻发现 页面显示成乱码、字段里出现一串问号、价格变成负数、日期变成1970年,这些都会在几小时内被报上来。因为它们过不了任何一道校验,也过不了任何一个人的眼睛。 校验能拦住的都是格式层面的错,自定义表单怎么做必填校验、服务端JS和HTML5三层防护 (https://zhangwenbao.com/dedecms-custom-form-settings-required-items.html)讲的正是这三道拦得住和拦不住的东西。 这类故障看起来吓人,实际上是最容易处理的一类:它自带报警。 ## 合法值可以活很多年 另一种就麻烦了。一个通顺的德语词、一个格式正确的日期、一个在合理区间里的数字,它们过得了校验,过得了肉眼,也过得了所有监控。 不报错的浪费能持续很久,算抓取预算才发现服务器把没改过的页面对爬虫重发了几百遍 (https://zhangwenbao.com/conditional-request-304-etag-crawl-budget-seo.html)是同一种安静的损耗。 > 会报错的故障是在替你干活,它替你把问题喊了出来。不报错的那种什么都不说,只是安静地改变结果。 ## forks其实是个幸运的特例 皮尤那次之所以能查清楚,很大程度上是运气好:forks这个词出现在“是”的位置上实在太荒谬,荒谬到有三个人特地写了反馈。 如果它变成的不是forks而是“确认”“同意”这类词,大概率一个人都不会说,那份数据到今天还是干净的、可发布的、无人质疑的。 ## 而“清洗时需注意”完全合法 陶瓷站那一行就是这种情况。改写之后的说法在德语里毫无破绽,甚至在某些产品上还是更准确的描述。 它唯一的问题是:它说的不是你想说的那句话,而这一点只有你自己知道,可你恰恰是唯一看不到它的人。 ## 换个说法:错误的可见度和它的严重程度无关 把这条规律说透一点:一个错误能不能被发现,取决于它离“合法”有多远,而不是取决于它造成的损失有多大。这两件事在直觉里被绑在一起,实际上完全独立。 价格显示成负数,损失可能是零,因为没人会去下单;一句技术承诺被换成意思更弱的说法,损失可能是两年的退货成本,而它长得毫无破绽。 ## 所以报警的顺序天然是错的 系统会按“离合法有多远”来排报警顺序,而你需要的是按“损失有多大”排。这两个顺序几乎不重合,甚至经常是反的。 能自动报警的问题都是不太重要的问题,这句话听起来别扭,但在这一类故障里基本成立。重要的那些得靠你主动去找。 ## 怎么判断一个字段有多危险 有一条很好用的经验规则:看这个字段的取值空间有多大。取值空间越大,故障越不容易被发现,因为任何改动后的结果都还落在合法范围里。 把页面上的字段一次性列全,是判断风险的前提,结构化数据审计工具怎么一次扒清五种格式的字段缺漏 (https://zhangwenbao.com/schema-extractor-structured-data-audit-guide.html)给了现成的做法。 按这条规则可以给页面上的字段排个序。 ## 布尔字段最安全 字段类型 | 取值空间 | 被改写后能否被系统识破 | 典型例子 | 布尔 | 2个值 | 基本能,非此即彼 | 是否有货 | 枚举 | 几个到几十个 | 看情况,落在集合外才会被发现 | 尺码、颜色 | 数字 | 连续区间 | 只有超出区间才会被发现 | 容量、重量 | 自由文本 | 近乎无限 | 基本不能 | 材质说明、使用须知 | 枚举类字段在变体场景里最容易失控,WooCommerce变体SEO的Schema、canonical与URL三层治理 (https://zhangwenbao.com/woocommerce-product-variations-seo-schema-canonical-url-deep-dive.html)把这类字段的边界讲清楚了。 这张表最实用的读法是倒着读:你最该盯的不是最重要的字段,是取值空间最大的字段,因为那些字段坏了不会有人告诉你。 ## 数字字段的陷阱在单位上 数字看起来安全,其实有个专属陷阱:单位。一个写着28的数字,是28厘米还是28英寸,取决于旁边那个单位符号,而单位符号是文本,属于最危险的那一类。 数字旁边那个符号才是最容易出错的地方,把跨境多市场价格排得像本地店的货币格式化做法 (https://zhangwenbao.com/currency-formatter-cross-border-price-localization-schema-guide.html)讲了小数位、符号位置与价格字段该怎么配。 更糟的是很多站为了排版好看,把单位放进了另一个标签甚至用图标表示。数字没被动,单位被动了,结果一样错。 ## 所以最该防的是哪几类内容 按上面的排序,产品页上最需要保护的其实是这几类:材质与成分说明、使用与保养须知、认证与合规声明、尺寸单位、以及所有的是非型承诺。 商品分类这类字段一旦标错会一路错下去,Google给商品结构化数据加了个category、页面标记和数据源的分类终于对上了 (https://zhangwenbao.com/merchant-listing-category-property-google-product-taxonomy.html)讲的是同一件事。 它们的共同点是取值空间大、语义敏感、而且直接决定买家的判断。营销文案反而没那么要紧,翻歪一点不至于造成退货。 ## 反过来利用这条规律 既然大取值空间的字段查不出来,那就人为造一个取值空间极小的字段出来专门用来查。这就是下面这个做法的思路。 判断一个标记有没有用,最好的办法是拿实测说话,Schema结构化数据对AI搜索到底有没有用、官方说法加实测 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)就是这么做的。 具体做法:在页面上放一个用户看不见的小元素,里面写一句固定的、绝不该被改动的字符串。 ## 放一个会自己喊疼的哨兵 这个字符串挑选有讲究:它要足够像一句正常的话,能被翻译工具当成翻译对象,同时又必须是你完全掌握的一个定值。比如一句简单的产品短语,加上一个固定的编号。 一个全球唯一的编码能省掉很多歧义,跨境电商GTIN怎么申请、从商品条码到谷歌购物收录 (https://zhangwenbao.com/cross-border-product-gtin-guide.html)讲的是编码这种定值的价值。 然后写几行脚本,在页面加载完之后读一次这个元素的文字,和预期值比一比,不一样就上报。不一样就意味着这一页在这个用户那里被改写过。 ## 它能告诉你什么 上报的信息里带上浏览器语言、页面语言标记、以及改写后的实际内容,你就同时拿到了三件事:这个用户被改写了、改写发生在什么环境下、改成了什么样。 那家陶瓷站上线这个哨兵之后,头一周就发现德语站有11.3%的会话触发了改写,法语站是6.7%,英语站接近零。这个数字之前是不存在的,不是因为没人查,是因为没有任何地方能查得到它。 ## 哨兵该写成什么样的一句话 写法上有两个要求互相拉扯:它得像一句正常的话,翻译工具才会去碰它;它又得是一个你能精确比对的定值,脚本才判得出来。 探针也好实体也好,写法决定了机器认不认,Schema结构化数据怎么做、@graph与知识图谱怎么搭 (https://zhangwenbao.com/schema-org-advanced-graph-entity-knowledge-panel-mechanism.html)那篇讲的是让机器读懂的写法。 折中的写法是一句普通的产品短语后面跟一串固定编号,比如一句关于材质的短句加上一组数字。短句负责吸引翻译工具动手,编号负责让你一眼看出它被动过。 ## 别把哨兵写成一串乱码 有人会想直接放一串随机字符,这样比对最简单。问题是翻译工具通常不会去翻一串没有语义的字符,于是哨兵永远不触发,你会以为一切正常。 这一条其实是本文那条主规律的又一次应用:探针必须长得像被监测对象,否则它测的是它自己。 ## 成本与副作用 成本是一个隐藏元素加十几行脚本,加上一个接收上报的接口。半天能做完。副作用要注意两条:隐藏元素别用会被判定为隐藏文本的写法,免得踩搜索引擎的规则;上报要节流,别每次加载都打一条。 该做什么不该做什么最好有数据支撑,Schema官方第一次公开全网使用数据、哪些结构化数据该做 (https://zhangwenbao.com/schema-org-usage-statistics-priority-guide.html)给了一份优先级参考。 做法上稳妥的选择是用无障碍属性把它标成装饰性内容,并且只对一定比例的会话采样上报。 ## 把显示层和数据层对上要做哪几件事? ## 六件事,按改动风险从低到高排 这份清单和别的清单排序方式不太一样。这里面每一件都要碰前端,而碰前端有伤到收录和体验的可能,所以顺序按风险排:先做那些不可能出事的,再做需要权衡的。 地基类的配置最好在早期就理顺,独立站CMS第一年SEO隐性失分的12项排查 (https://zhangwenbao.com/cms-seo-first-year-hidden-loss-checklist-cross-platform.html)列的正是这类改起来便宜、拖久了变贵的项。 前三件基本零风险,后三件要想一下。全部做完大约两三天工。 ## 第一件:把页面的语言标记改对 根标签上那个语言属性,必须和页面实际内容的语言一致。德语页面写德语,法语页面写法语。这是浏览器判断要不要翻译的第一依据,也是最容易被漏掉的一处。 那家陶瓷站的整个事故就出在这里:多语言方案把内容换成了德语,那个属性却还停在英语上。写法上的细节,包括一页里混用多语言时局部该怎么标,W3C国际化:HTML页面的语言声明该怎么写 (https://www.w3.org/International/questions/qa-html-language-declarations)那份问答讲得最清楚。 ## 多语言插件最常漏的就是这一个 不是插件不做,是很多站在做本地化时用的是最省事的办法:复制一份模板改内容。模板头部那一行属性写死在主题文件里,改内容的人根本碰不到它。 插件方案的默认值决定了你会漏掉什么,WordPress独立站做小语种SEO、从插件选型到内容本地化的4步 (https://zhangwenbao.com/wordpress-minor-language-seo-localization.html)把选型时该问的问题列出来了。 越是自己动手做的多语言站,越容易踩这一条,因为它不在任何一份内容清单上。 ## 怎么查:一分钟能查完所有语言版本 打开每个语言版本的任意一页,在页面源码里搜根标签的语言属性,看它写的是什么。或者用命令行抓一次页面源码,直接看头几行。 改一处看一处是最快的验证方式,HTML编辑器怎么用、三栏实时预览改一处看一处 (https://zhangwenbao.com/html-editor-html-css-js-live-preview-guide.html)适合用来快速验证这类属性改动。 三个语言版本三分钟。查出来不对的话,改动量通常也就是模板里的一处变量。 ## 顺带说清楚它和hreflang的区别 做国际站的人容易把这两件事混在一起。它们完全不是一回事:hreflang是给搜索引擎看的,说的是“这一页还有哪些语言版本,分别在什么地址”;根标签上那个语言属性是给浏览器和辅助技术看的,说的是“这一页本身是什么语言”。 hreflang本身也有一堆容易写错的地方,hreflang标签怎么落地、return tags对称与x-default实操避坑 (https://zhangwenbao.com/hreflang-implementation-return-tags-x-default-canonical-mistakes.html)是配完之后该逐条对的清单。 hreflang配得再完美,也挡不住浏览器把你的德语页当英语页去翻译,因为浏览器压根不读hreflang。两者要各配各的,谁也替不了谁。 ## 还有一处也常漏:局部语言标记 一页里如果混着两种语言,比如德语页面上引用了一段英文原文,那段英文最好单独标出自己的语言。不标的话,翻译工具面对语言混杂的页面更容易做出奇怪的判断。 本地化数据里有不少是继承来的默认值,小语种的本地化数据看着有的多半是借的、看着空的反而是对的 (https://zhangwenbao.com/minor-language-locale-data-inheritance.html)讲的就是这类看不见的继承。 皮尤那次的根因就带着这个味道:一个弹层引入了语言标记上的混乱,浏览器于是判定整页含有别的语种。局部标清楚,是给判定逻辑减少歧义。 ## 第二件:给关键区块加不翻译标记 标记的作用是告诉翻译工具“这一块别动”。它是元素级的,可以只标那一行参数、那一个按钮、那一段合规声明,标准写法见MDN:translate全局属性 (https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/translate),取值和继承规则那一段值得读一遍。 该标的通常有这么几类:品牌名与型号、认证与合规声明、材质与成分、尺寸单位、以及所有是非型的技术承诺。 ## 粒度必须是元素,不能是整页 有个更省事的做法是给整页加禁止翻译,对应的元标记写法在Google搜索中心:特殊标签说明 (https://developers.google.com/search/docs/crawling-indexing/special-tags)里,很多人第一反应就是这个。但这一步跨得太大:你挡住的不只是坏的翻译,还有好的翻译。 页面级的开关代价通常比想象中大,已收录页面加noindex后多久从搜索结果消失、6大场景实测 (https://zhangwenbao.com/when-does-noindex-page-remove-from-google-search-results.html)是另一个该慎用页面级开关的例子。 一个不懂德语的访客本来可以靠浏览器翻译大致读懂你的页面,整页禁掉之后他一个字都读不了,只能关掉。这个代价通常比被误译几个词还大。 ## 判断标不标的一条线 可以用这个标准:这句话被翻歪了,会不会导致用户对产品做出错误判断。会,就标;只是读起来别扭,就别标。 按这条线筛下来,一个产品页通常只有五到十处需要标,工作量很小。 ## 第三件:把关键承诺换成不易误译的写法 这一件不动代码,只动文案。翻译工具在长复合词和行业术语上最容易出错,在短句和常用词上最稳。所以把关键承诺改写成短句,出错概率会显著下降。 文案怎么写既是品牌问题也是工程问题,出海DTC的品牌声音体系怎么搭、让产品页客服和社媒听着像同一个人 (https://zhangwenbao.com/dtc-brand-voice-tone-of-voice-system.html)讲的是前者。 举例来说,与其用一个长复合词表示“可用于洗碗机”,不如写成一句主谓齐全的短句。写得更啰嗦一点,换来的是被改写的概率下降,这笔账在关键字段上很划算。 ## 第四件:埋一个哨兵并采样上报 上一节讲过做法:放一个用户看不见的固定字符串,加载完读一次,和预期值比一比,不一样就上报。半天工,能第一次让你看到改写的真实发生率。 探针要长期跑就得自动化,独立站怎么用cron把备份、sitemap、缓存和日志自动化 (https://zhangwenbao.com/linux-cron-shell-independent-site-automation-ops-backup-sitemap-ssl.html)里有可以直接改的脚本骨架。 要注意的是采样率和上报频次,别把它做成一个每次加载都打点的东西,那会白白吃掉一部分性能预算。 ## 第五件:把客服截图纳入月度抽查 这一件零技术成本。规矩定成每月从客服工单里随机抽二十张用户截图,和后台页面并排看一遍,重点看参数表和按钮文案。 用户交上来的材料能派的用场比想象中多,怎么用AI把用户评论变成高转化的产品描述 (https://zhangwenbao.com/ai-transform-reviews-into-product-descriptions.html)是另一种把这批材料用起来的方式。 一次二十分钟。它的价值不在效率,在于它是唯一一份直接来自用户屏幕的证据,而其他所有监控看的都是服务器那一侧。 ## 第六件:加一个“这页哪里看着不对”的入口 在产品页底部放一行小字,点开是两行输入框。这个入口一年可能只收到几十条,但那几十条描述的都是你在任何报表里看不到的现象。 它和第五件是一对:截图抽查是你主动去找,反馈入口是等用户送上门,两个方向合起来覆盖面才够。 ## 六件事排成一张表 动作 | 工作量 | 改动风险 | 能挡住什么 | 修正页面语言标记 | 1小时 | 无 | 绝大多数误判触发的自动翻译 | 关键区块加不翻译标记 | 半天 | 低 | 剩下那部分的关键字段被改写 | 关键承诺改写成短句 | 1天 | 无 | 术语类误译 | 埋哨兵并采样上报 | 半天 | 低,需注意采样 | 让改写第一次变得可观测 | 客服截图月度抽查 | 每月20分钟 | 无 | 所有类型的显示层异常 | 加页面反馈入口 | 2小时 | 低 | 用户愿意说出来的那部分 | 同语言多地区是国际站另一个高频坑,同一种英语卖到美英澳、怎么不自己跟自己打架 (https://zhangwenbao.com/international-seo-same-language-multi-region-en-us-gb-au-duplicate-content-hreflang.html)那份清单和本表可以并排放着用。 ## 哪几件必须一起做 第一件和第四件建议同一批上线:修完语言标记之后,哨兵能立刻告诉你修得对不对,比任何自查都直接。 那家陶瓷站的顺序就是这样:先改属性再埋哨兵,一周后德语站的改写率从11.3%掉到0.4%,剩下那点来自装了翻译扩展的用户,那部分改不了,也不该改。 ## 改完之后怎么验证真的生效了 属性改完不能只看源码,得看行为。验证方法有三层:第一层看源码,确认属性值对了;第二层用目标语言的浏览器配置实际访问一次,看还弹不弹翻译提示;第三层看哨兵的上报数据有没有掉下来。 三层缺一不可,因为前两层证明的是配置对了,只有第三层证明的是真实用户那边的情况变了。 ## 别在测试环境验证这件事 测试环境和线上环境在这件事上经常不一致,尤其是当多语言方案的一部分逻辑跑在CDN或者边缘节点上的时候。稳妥的做法是改完直接在线上验,反正这类改动的回滚成本几乎为零。 凡是依赖真实用户环境才能触发的问题,都必须在真实环境验证,这条没有例外。 ## 三个月后的账 德语站“与描述不符”的退货占比从41%降到18%,整体退货率从高出英语站6.8个点收窄到2.1个点。加购到下单的转化率涨了1.4个百分点。 国际站的结构决定了后面所有改动的成本,出海独立站国际SEO怎么选域名结构、ccTLD子目录还是子域名 (https://zhangwenbao.com/international-seo-domain-structure-cctld-subdirectory-subdomain.html)是最该早想清楚的一件。 这些数字里没有一项来自新增流量,全部来自本来就已经到站、只是看到了一句被改过的话的那批人。 ## 这套排查在什么时候不管用? ## 只对“内容被改写”这一类有效 第一条边界要划清楚:本文讲的是文字内容在传输之后被换掉,不包括布局错乱、图片加载失败、脚本报错这些。 跨语言最难的其实不是标签而是实体对齐,国际化SEO最难的不是hreflang、实操对不上的5大根因 (https://zhangwenbao.com/multilingual-entity-seo-cross-lingual-reconciliation.html)讲的是另一类跨语言问题。 后面那几类各有各的成熟排查手段,而且它们大多会在监控里留下痕迹。本文针对的是那类不留痕迹的:所有系统都认为一切正常,只有用户看到的不是你写的。 ## 哨兵只能证明有,不能证明没有 第二条边界关于那个哨兵。它触发了,说明这一页确实被改写过,这个结论很硬。它没触发,只能说明那一个字符串没被动,说明不了整页干净。 探针给的是相对值,判断高低还得有参照,转化率、排名周期与流量占比的行业基准数据 (https://zhangwenbao.com/seo-industry-benchmarks-data-reference-guide.html)可以当量级校验用。 翻译工具的处理范围受多种因素影响,某些情况下它会跳过短文本或者跳过某些标签里的内容。哨兵放在哪里、写成什么样,都会影响它的灵敏度。 ## 放哨兵的位置有讲究 稳妥的做法是放两个:一个在主体内容区里,和产品描述在同一层级;另一个在参数表附近,和最关键的那批字段共处一个容器。两个都不触发,可信度才够。 这一条也提醒了一件事:任何探针测的都只是探针所在的那个位置,把它的结论推广到全页需要额外的假设。 ## 装了扩展的用户你管不了 第三条边界更硬一些。浏览器内置的翻译尊重页面上的标记,你给的信号它基本会听。第三方翻译扩展不一定,有些扩展的设计目标就是无视一切限制强行翻译。 读者构成变了,能管和不能管的边界也跟着变,AI爬虫抓取量已超Googlebot 3.6倍、SEO策略要怎么变 (https://zhangwenbao.com/ai-crawlers-surpass-googlebot-seo-strategy.html)给了一份新的边界判断。 这部分用户你管不了,也不该管。他主动装了一个把所有页面都翻掉的工具,说明他确实需要它,你去对抗只会让他连内容都读不到。 ## 能做的是把他们标出来 哨兵可以顺带告诉你这部分人有多少。那家陶瓷站修完属性之后剩下的0.4%就是这批人,比例很小,而且他们的退货率并不比别人高——说明扩展翻译的质量对他们够用。 知道有一部分人你管不了,和不知道自己管不了哪些人,是两种完全不同的状态。 ## 明码标价那一部分 第四条边界是成本。这套东西的总投入大约三天工时,加上每月二十分钟的截图抽查。它没有大的隐性成本,但也不是零。 地基类改动的收益要按长期算,独立站网站架构怎么搭、搭错了谷歌爬虫根本找不到你的产品页 (https://zhangwenbao.com/ecommerce-website-architecture-flat-vs-deep-crawl-depth-seo.html)是另一件典型的地基工程。 真正的支出是注意力:多了一个需要有人定期看一眼的东西,而这类东西在公司里的存活率从来不高。 ## 它和常规的前端监控是什么关系 很多站已经有前端错误监控了,收集脚本报错、资源加载失败、接口超时。那套东西和本文说的哨兵不冲突,但也替代不了——它监控的是出错,而本文讲的这类问题从头到尾不出错。 错误监控的前提是有异常抛出,而内容被改写这件事不会抛出任何异常。两套东西盯的是两类完全不同的失败。 ## 如果只能上一套,先上哪个 先上错误监控。它覆盖的问题类型更多,投入产出更直接,而且是所有站都该有的基础设施。哨兵属于第二梯队,适合那些多语言市场占比高、或者已经被这类问题坑过的站。 判断标准可以定得很简单:如果你的非英语市场贡献了三成以上的营收,那哨兵值得排期;如果只有个位数,先放着。 ## 怎么让它活过三个月 可行的办法是把月度抽查挂到一个本来就存在的会上,比如客服月会,占五分钟。凡是需要新开一个会才能做的事,基本都活不过半年。 能自动跑的东西才活得久,多语言大站hreflang手写维护不动、用AI写脚本从爬虫结果自动生成sitemap (https://zhangwenbao.com/ai-script-hreflang-xml-sitemap-multilingual.html)就是把人工活变成自动活的例子。 哨兵那部分更好办,它是自动的,只要上报有数据,它就一直在工作。 ## 别说“用户的浏览器有问题” 接下来说措辞。第一句不能说的是这个。它把责任推给了用户,而且不准确——浏览器做的是它被设计要做的事,用户什么都没做错。 说完这句,讨论就会滑向“那我们也没办法”,然后不了了之。 ## 也别说“这是浏览器厂商的锅” 第二句同理。即使它在技术上完全成立,也推不动任何改进,因为你不可能等对方修。 把原因归到一个你影响不了的地方,本质上等于宣布这件事没法解决,而它明明可以用一行属性解决掉大半。 ## 该怎么说这件事 可以直接用的版本大概是:我们的德语页面在头部声明的语言是英语,所以德国买家的浏览器会把它再翻一遍,参数表里有几个词被换掉了。改一个属性就能修,我想这周排进去,改完埋个探针看看还剩多少。 把要求说到能直接执行的程度,对方才动得起来,结构化数据怎么配合SEO落地、附常见避坑 (https://zhangwenbao.com/seo-schema-guide.html)的写法就是尽量少留解释空间。 三句话:一个事实、一个后果、一个带工时的提议。关键是那个提议小到不需要开会决定,一旦需要开会决定,它就会排到季度末。 ## 这件事和国际SEO的关系 还有一层值得提:修正语言标记这件事,顺带也把国际SEO的地基补上了。搜索引擎判断一个页面服务哪个语种的用户,除了看hreflang,也会参考页面本身的语言信号。 国际站的问题正在从标签层往知识层走,国际SEO进入AI时代、为什么hreflang挡不住跨市场知识污染 (https://zhangwenbao.com/international-seo-global-knowledge-integrity-cross-market-ai.html)讲的是下一层的挑战。 信号自相矛盾的页面,被匹配到错误语种的搜索结果里去的风险更高。所以这一行属性改对,收益是双份的:用户那一侧不再被误译,搜索那一侧的匹配也更干净。 ## 但别指望它能救排名 话也要说回来,这不是一个能立竿见影拉排名的动作。它属于地基类改动,作用是让别的优化不至于建在歪的地基上。 把期待值放对位置很重要,AI时代英文SEO的12步落地路线与5类避坑 (https://zhangwenbao.com/english-seo-ai-mode-12step-overseas-dtc-playbook.html)里对每一步的收益都做了区分。 那家陶瓷站修完之后,德语站的自然流量没有明显变化,涨的是转化率和退货率这两个指标。把它当成体验修复来做,期待值才是对的。 ## 皮尤那份材料的立场 最后是自我审查。皮尤把整件事公开写出来,包括承认自己上线前测了很多遍都没发现,这在商业上是纯支出,没有任何好处。 愿意公开自己不利数据的材料本来就少,小语种内容里写本地的事占多少、30门语言拆下来乌兹别克语4%英语53% (https://zhangwenbao.com/minor-language-content-local-topic-share.html)那份拆解也是同一种诚实。 而这类主动公开的复盘恰恰是这行里最稀缺的材料。大多数机构遇到这种事的处理方式是修掉、不说、当没发生过,于是下一家还得从头踩一遍。 ## 这篇文章自己的显示条件 > 这篇讲“你看到的不是我发出的”的文章,自己也活在同一个机制里。如果你此刻正开着浏览器的翻译功能读这一页,那么你看到的这句话,未必是我写下的那句。这不是修辞,是这套系统的默认行为。 读者是谁、用什么读,可以从日志里读出来,AI Agent抓取日志解码、8类UA实测与22周访问账本 (https://zhangwenbao.com/ai-agent-crawler-log-decoding-8-ua-traffic-attribution.html)给了一套辨认方法。 ## 如果只记一句 那就记这句:你的服务器只知道自己发出了什么,永远不知道对方收到的是什么;而在这两者之间,站着好几个都有权改写、且都不会给你回执的中间层。 语言这条线上的变化还在继续,多语言模型铺到七十多种语言那天、受益最多的不是字母最像英语的那几门 (https://zhangwenbao.com/multilingual-bert-seventy-languages-minor-language-seo-watershed.html)是个值得记住的分水岭。 要把这段距离缩短,靠的不是更强的监控,是在现场放一个会自己喊疼的东西。 ## 常见问题解答 ## 怎么最快判断我的站有没有这个问题? 三分钟就能做完。打开每一个语言版本的任意一页,查看页面源码,看根标签上的语言属性写的是什么,和这一页实际内容的语言对不对得上。对不上就是高风险,这是所有误判触发自动翻译的第一来源。如果都对得上,再做第二步:把浏览器界面语言切成目标市场的语言,开着翻译功能访问一次,重点看参数表和是非型的技术承诺有没有被换词。第三步是翻客服工单里的用户截图,随便抽二十张和后台并排看。三步下来多数站要么确认没事,要么直接找到问题。查不出来的情况很少,多半是触发条件只覆盖极小比例的用户,那就得靠埋探针。 ## 给整页加禁止翻译到底行不行? 不建议。整页禁翻译确实能挡住误译,但它同时也挡住了正常翻译,代价是一个不懂你页面语言的访客将完全无法阅读,只能关掉页面。跨境站的现实是相当一部分流量来自不是你目标语种母语的人,他们靠浏览器翻译勉强读懂内容后照样下单。把这条路堵死,损失通常比被误译几个词还大。正确的粒度是元素级:只标那些被翻歪之后会导致用户做出错误判断的内容,比如认证声明、材质成分、尺寸单位、是非型承诺。照这个标准筛,一张产品页需要标的地方通常不超过十处,其余部分照常允许翻译。 ## 哨兵会不会被搜索引擎当成隐藏文本? 有这个风险,所以写法要讲究。不要用把文字定位到屏幕外或者字号设成零这类典型的隐藏手法,那些正是隐藏文本判定要抓的模式。稳妥的做法是把它标成装饰性内容,用无障碍属性明确告诉辅助技术和爬虫这一块不承载信息,同时让它在视觉上不占位。另一个更保险的替代方案是不放在正文里,而是放在一个属性值里,用脚本读属性而不是读可见文本,这样它压根不是页面文本的一部分。要提醒的是,哨兵的目的是探测改写,不是欺骗任何人,把它做得越透明越安全,别为了提高触发率去玩文字游戏。 ## 用户装的翻译扩展我真的一点办法都没有吗? 基本没有,而且这件事不值得花力气去对抗。扩展是用户主动装的,它的设计目标往往就是无视页面上的一切限制强行翻译,你加什么标记它都可能不理。更重要的是,装了这类扩展的人说明他确实需要翻译,你去对抗只会让他连内容都读不到。能做的有两件:一是用探针把这部分人的规模测出来,心里有个数;二是观察他们的转化和退货是不是明显异常。那家陶瓷站修完语言标记之后剩下的0.4%就是这批人,他们的退货率并不比别人高,说明扩展翻译的质量对他们够用,那就不必再管。 ## hreflang已经配好了,为什么还会出事? 因为这两件事的读者不一样。hreflang是给搜索引擎看的,告诉它这一页还有哪些语言版本、分别在什么地址;根标签上的语言属性是给浏览器和辅助技术看的,告诉它们这一页本身是什么语言。浏览器在决定要不要弹出翻译提示时,压根不读hreflang。所以hreflang配得再完美,也挡不住浏览器把你的德语页当成英语页去翻译。两者要各配各的,谁也替不了谁。顺带一提,如果一页里混着两种语言,比如德语页面上引用了一段英文原文,那段英文最好单独标出自己的语言,这能减少浏览器判定时的歧义。 ## 每月只抽二十张截图,会不会漏掉? 会漏,但这不是它的用途。抽查的作用是给你一个持续的、低成本的观察窗口,不是穷举。如果一个改写问题的发生率高到值得处理,它在二十张里出现的概率就不低;如果二十张里连一次都碰不到,那它的影响面大概率也不值得你专门排期。真要提高覆盖,比加大抽查数量更有效的是加装探针,因为探针覆盖的是全部会话而不是有截图的那一小撮。两者的分工是这样的:探针告诉你有多少比例被改写了,截图告诉你具体改成了什么样。前者给规模,后者给内容,缺一个都不好判断要不要动手。 ## 发现历史数据受影响,已经上线的决策要不要回滚? 先别急着回滚,先把受影响的范围圈出来。找一个能区分受影响和未受影响的字段,比如语言版本、浏览器语言或者故障的起止日期,用它把数据切成两半。未受影响那部分照常用,受影响那部分单独标注而不是删除——被标注的数据仍然能回答趋势方向和人群构成这类问题,被删掉的什么都回答不了。至于决策要不要改,判断标准是那个决策依赖的具体结论有没有落在受影响的那一半里。多数情况下会发现影响面比担心的小,真正需要推翻的结论并不多。这也是为什么故障的起止时间必须记准,没有准确边界就只能一刀切。 ## 只做英文单语站,这套东西对我有用吗? 有用,但侧重点不同。单语站被自动翻译改写的概率确实低得多,因为触发条件通常是页面语言和用户偏好语言不一致。但本文讲的另一半照样成立:广告拦截器会删掉像广告的元素,隐私扩展会剥掉追踪参数和统计脚本,密码管理器会往表单里填错字段,企业安全网关会改写页面,系统的强制深色模式会让浅色文字消失。这些都不挑语言。判断优先级的办法是看你的用户构成:如果相当比例的流量来自公司网络或者技术人群,那么拦截器和网关这两类的影响会比翻译大得多,探针同样能测。 ## 权威参考资料 ## 第三方评测背书写进结构化数据,一半属性挂不上去 - URL:https://zhangwenbao.com/third-party-review-schema-entity-linking.html - 分类:技术SEO - 发布:2026-08-06 | 更新:2026-08-06 - 摘要:产品被某个评测站写过一篇长测,能不能把这条背书写进JSON-LD让机器知道?答案分两种情况,结论正好相反。而就算真被评测过,能用的属性也比大多数人以为的少得多。 - 关键词:结构化数据,技术SEO,AI引用,JSON-LD > **TLDR**:摘要:想在商品页上声明“某某评测网站评测过这件东西”,能用的属性其实没几个。把十个候选属性拿到schema.org官方词汇表里逐个核对,只有五个挂在Product上是合法的,citation、about、mentions、isBasedOn、itemReviewed全部无效。再往大了数,一千六百多个属性里,对Product合法的只有七十二个。 > 摘要:想在商品页上声明“某某评测网站评测过这件东西”,能用的属性其实没几个。把十个候选属性拿到schema.org官方词汇表里逐个核对,只有五个挂在Product上是合法的,citation、about、mentions、isBasedOn、itemReviewed全部无效。再往大了数,一千六百多个属性里,对Product合法的只有七十二个。 做户外装备的一个客户问过保哥一件事:他们有款头灯被一个专做装备长测的站写过,评分不低,还配了实测数据。能不能把这条背书写进产品页的JSON-LD,让机器知道有人测过? 这个问题得拆成两半回答,因为两半的结论正好相反。 ## 评测网站压根没写过你,这条标记算什么? 先说没写过的情况。有些人的想法是:反正JSON-LD是给机器看的,页面上又不显示,编一条好评塞进去,机器读到了就算数。 这条路是死的,而且死得很难看。 Google对评价摘要结构化数据的规定 (https://developers.google.com/search/docs/appearance/structured-data/review-snippet?hl=zh-cn)里有两条卡得很死。第一条是禁止跨站聚合,英文原文写的是“Don't aggregate reviews or ratings from other websites”,中文版更直接:请勿汇总来自其他网站的评价或评分。第二条是可见性要求,原文是“Make sure the review content you mark up are readily available to users from the marked-up page”,翻成人话就是:你标记了什么,用户在这一页上就得能看到什么。 两条合起来的意思很清楚:标记不是一个可以单独存在的图层,它是页面内容的机器可读副本。页面上没有的东西,标记里也不该有。 只在JSON-LD里写一句好评、页面上找不到任何对应内容,这在Google那里有个专门的名字,叫spammy structured markup。轻的处理是整段标记被忽略,重的是吃一个结构化数据的人工处罚,整站的标记都不再被信任。 更麻烦的是这件事不只是SEO问题。在美国市场,虚构第三方背书涉及虚假广告,那个风险比丢几个富媒体位置大得多。这一层不展开,找法务比找SEO有用。 ## 想说“某某评测过我们”,schema.org里有几个属性能用? 再说评测网站确实写过的情况。这时候标记是可以做的,但先得知道该用哪个属性——这一步比想象中窄得多。 我把schema.org官方词汇表下载下来,离线跑了一遍。词汇表里一共1010个类、1676个属性,每个属性都带着domainIncludes(允许挂在哪些类型上)和rangeIncludes(值可以是什么类型)两项声明。Product的继承链很短,就两层:Product直接继承Thing。 然后我列了十个大家可能会想用的属性,逐个查它们的domainIncludes里有没有Product或Thing。 属性 | 挂在Product上 | domainIncludes写的是 | review | 合法 | Brand、CreativeWork、Event、Offer、Organization、Place、Product、Service | subjectOf | 合法 | Thing | sameAs | 合法 | Thing | mainEntityOfPage | 合法 | Thing | aggregateRating | 合法 | Brand、CreativeWork、Event、Offer、Organization、Place、Product、Service | citation | 无效 | CreativeWork | about | 无效 | CreativeWork、Event、DefinedTerm等六个 | mentions | 无效 | CreativeWork | isBasedOn | 无效 | CreativeWork | itemReviewed | 无效 | AggregateRating、Review | 十个里只有五个能用。这个比例不是巧合。整张词汇表1676个属性里,对Product合法的只有72个,占4.3%;其中59个是domainIncludes里直接写着Product的,另外13个是只写了Thing、因而对任何类型都合法的。 那13个通用属性值得单独记一下,因为它们是唯一一批“挂在哪都不会错”的:additionalType、alternateName、description、disambiguatingDescription、identifier、image、mainEntityOfPage、name、owner、potentialAction、sameAs、subjectOf、url。 你会发现subjectOf就在这份名单里。这就是它能用来关联评测的原因——它不是给Product特批的,它对整个schema.org世界都开放。 ## citation为什么挂不上Product? 这条值得单独讲,因为它是最容易被误用的一个,而且写错了不会有任何报错。 schema.org对citation属性的定义 (https://schema.org/citation)写得很明白,它的domainIncludes只有一个值:CreativeWork。CreativeWork是文章、网页、书籍、视频这一类“被创作出来的东西”的总称,Product不在这条继承线上——它俩的唯一交点是最顶上的Thing。 所以citation表达的是“本文引用了那篇文献”,主语必须是一篇内容。商品不是内容,商品是被内容谈论的对象。这两件事在schema.org的建模里方向完全相反。 写错的后果不是报错,是静默失效。解析器读到一个domain不匹配的属性,通常的处理是丢掉它,然后接着往下读。你的验证工具一片绿,标记本身却少了一块。JSON-LD的语法校验能抓住尾逗号这类硬错误 (https://zhangwenbao.com/json-ld-validator-syntax-debug-guide.html),但抓不住这种“语法完全正确、语义挂错了地方”的问题。 那citation该挂在哪?挂在WebPage节点上。WebPage是CreativeWork的子类,完全合法。这就带出了正确的分工: - Product上写subjectOf,表达“这件商品是那篇评测的对象”; - WebPage上写citation,表达“本页引用了那篇外部文献”。 两个可以同时写,也可以只写subjectOf。它们描述的是同一件事的两个侧面:一个是商品与评测的关系,一个是页面与文献的关系。 ## subjectOf该怎么写才不出错? schema.org对subjectOf属性的定义 (https://schema.org/subjectOf)里,rangeIncludes写的是CreativeWork和Event两种。Review的继承链是Review到CreativeWork再到Thing,所以把一个Review节点放进subjectOf里,类型是对得上的。 下面这段是可以直接改的骨架: { "@context": "https://schema.org", "@graph": [ { "@type": "WebPage", "@id": "https://你的域名/产品页/#webpage", "url": "https://你的域名/产品页/", "citation": { "@id": "评测原文URL#review" } }, { "@type": "Product", "@id": "https://你的域名/产品页/#product", "name": "产品名", "brand": { "@type": "Brand", "name": "品牌名" }, "subjectOf": { "@type": "Review", "@id": "评测原文URL#review", "url": "评测原文URL", "headline": "评测文章的标题", "datePublished": "2026-03-14", "itemReviewed": { "@id": "https://你的域名/产品页/#product" }, "author": { "@type": "Organization", "name": "评测网站的名称", "url": "评测网站首页" }, "publisher": { "@type": "Organization", "name": "评测网站的名称" } } } ] } 有几个地方需要说明。 author必须写成Organization,不能写成Person,除非那篇评测确实署了个人名。author的rangeIncludes只有Organization和Person两种,写成一个裸字符串虽然很多解析器容忍,但那样机器就没法把它和评测方这个实体对上号了。 Review节点里的itemReviewed反过来指回Product的 @id,这一笔很多人会省掉。它的作用是把关系闭合:Product说“我是那篇评测的对象”,Review说“我评的就是它”。单向声明和双向闭合在图结构里是两回事,后者才构成一条真正的边。itemReviewed的rangeIncludes是Thing,所以指向Product完全合法。 评测原文的URL必须是真实存在、能打开的那一个。如果拿不出真实链接,这套标记就别上——挂一个假的 @id上去,是负资产不是资产。 还有一个属性值得知道:positiveNotes和negativeNotes。它俩的domainIncludes是Product和Review两个,也就是说编辑型评测的优点缺点可以直接挂上去。这两个属性在中文资料里几乎没人提,保哥也是这次核词汇表才注意到。 ## 别拿sameAs代替subjectOf sameAs的语义是“指向能唯一确认这个实体身份的页面”,典型的值是维基百科条目、官方社交主页、Wikidata条目。它回答的是“这个东西是谁”,不是“谁谈论过这个东西”。 把一篇评测文章塞进sameAs,等于告诉机器“那篇评测就是我这件商品本身”。这是身份层面的错误声明,比不写更糟。 ## 这条评分能不能并进aggregateRating? 不能。这是本文里唯一一条该当成红线的规矩。 aggregateRating的语义是“页面上展示的全部评价的汇总”。把一个第三方媒体给的分数并进自家用户评分里算平均,同时踩中了前面那两条:既是跨站聚合,又是页面上看不到对应内容。 正确做法是让它们各走各的:自家用户评论走aggregateRating加review数组,第三方评测走subjectOf。两条线不交叉,机器读到的是两类不同来源的证据,反而比混算更清晰。 顺带说一句aggregateRating本身的硬要求:ratingValue是必填的,ratingCount和reviewCount至少要有一个。这两条经常被CMS插件写漏,评论系统那一侧的配置 (https://zhangwenbao.com/ecommerce-product-reviews-seo-guide.html)另有一篇讲得比较细。 ## 写了能拿到星标吗? 大概率不能,但原因和你想的不一样。 先澄清一个流传很广的说法:2019年Google收紧自我评价的时候,限制的范围其实很窄。官方原文是这么写的:“If the entity that's being reviewed controls the reviews about itself, their pages that use LocalBusiness or any other type of Organization structured data are ineligible for star review feature”。 翻过来就是一句话:只针对LocalBusiness和Organization这两类,Product不在里面。 所以从政策上讲,商品页的星标资格并没有被那次调整拿掉。 但现实是另一回事。电商的星级评价现在很大程度上走Merchant Center的商品评价数据源,页面上的JSON-LD未必能触发展示。你写了标记不等于会出星,这中间隔着Google自己的展示逻辑,那部分不由你控制。 更关键的是,subjectOf这条根本就不是富媒体属性。它不产生任何搜索结果里的视觉变化。如果你做这件事的动机是拿星标,那从一开始就走错方向了。 ## 排名会因此变好吗? 不会。结构化数据不是排名因素,它影响的是展现资格,这一点Google说了很多年。 做完这套标记,你在搜索结果里的位置不会动。这话说得可能有点扫兴,但把预期摆正比什么都重要。保哥见过一个团队花两周给全站产品页补评测关联,两个月后拿着排名曲线来问为什么没变——那两周的力气本身没白费,只是他们盯错了指标。 它真正可能有价值的地方在别处。 ## AI那边到底看不看JSON-LD? 这个问题现在有实测答案了,而且答案不太好听。 searchVIU在2025年10月做的一组对照测试 (https://www.searchviu.com/en/schema-markup-and-ai-in-2025-what-chatgpt-claude-perplexity-gemini-really-see/),设计了八个场景,分别在ChatGPT、Claude、Perplexity、Gemini和Google AI Mode上跑。测试的核心是:把同一条信息分别只放在可见HTML里、只放在JSON-LD里、只放在Microdata或RDFa里,看这些系统实时抓取一个页面时,各自能取到多少。 引擎 | 八个场景里取到价格的 | 纯schema场景 | Gemini | 4个(50%) | 全部失败 | ChatGPT | 3个(37.5%) | 全部失败 | Claude | 0个 | 全部失败 | 能取到的那几个,信息全都同时出现在可见HTML里。只放在结构化数据里的,几乎一条都没取到。 这个结果和很多人的直觉相反,但它其实很好理解:这些系统实时抓一个页面时,走的是接近浏览器的读取路径,读的是渲染后的文本。JSON-LD是给索引管线准备的,不在那条路径上。 所以结论要分开说:结构化数据的作用发生在索引层和知识图谱层,不发生在实时抓取层。它间接影响的是Google AI Mode、Copilot这类深度依赖自家图谱的产品;至于ChatGPT和Perplexity那种现抓现读的场景,你得靠可见文本。Schema对AI搜索到底有没有用 (https://zhangwenbao.com/schema-markup-ai-search-truth.html)这个话题站内单独写过一篇,可以对着看。 ## 那这套标记的价值到底在哪 讲到这里,价值的边界其实已经很清楚了。 你在自己页面上写的一切,本质上是单向声明。机器对单向声明天然打折,因为声明的成本太低——谁都可以说自己被权威媒体评测过。 真正让这条背书成立的,是评测网站那一侧:那篇文章存在、能被抓取、写了你的产品名。这是可以被交叉验证的一手证据。你的标记只是把这条证据指出来,让机器不用靠猜。 所以优先级应该是这样排的: - 先想办法拿到真实的第三方评测或提及,这一步占了这件事九成的价值; - 页面上如实引用,放一段原文片段、评测日期,加一条指向原文的外链; - 最后补schema,把这条关系写成机器可读的形式。 顺序反过来做——只补schema、前两步不做——性价比接近零。实体之间的关系怎么审 (https://zhangwenbao.com/integrity-graph-relationship-completeness-ai-visibility-audit.html)是更大的一个话题,评测关联只是其中一条边。 ## 页面上要先有真东西 虽然subjectOf不是富媒体属性、不受评价摘要那套显示规则约束,但页面上如果完全看不到这次评测的任何痕迹,标记的可信度和实际效果都接近零。 最低限度要做的:一段引用原文的片段、评测方的名字、评测日期、一条指向原文的链接。这四样东西同时也是给用户看的——一个真被权威媒体测过的品牌,本来就该把这件事写在页面上,不是吗。 这里有个小陷阱:不少团队会把评测引用做成一张图片,好看是好看,机器什么也读不到。既然前面已经说清楚了实时抓取只认可见文本,那这段引用就必须是真正的文字。 ## 一次把评测关联这件事做完 把上面的东西压成一份可以照着做的顺序。 第一步,确认那篇评测真的存在,把URL记下来,用无痕窗口打开一次确认能访问。这一步听起来多余,但被引用的评测文章下线、改版换URL是常事。 第二步,页面上补可见内容:引用片段、评测方名称、日期、外链。 第三步,写标记。Product上挂subjectOf,Review节点里带上itemReviewed、author、url、datePublished,评测方给了分数才写reviewRating,没给分就整块删掉,留headline加author加url就够了。 第四步,验证。这一步很多人用错工具:这套标记在富媒体结果测试里不会有任何反馈,因为它本来就不触发富媒体结果。要验结构正确性得用schema.org官方的结构化数据验证器 (https://validator.schema.org/),它检查的是词汇本身对不对,跟能不能出富媒体没关系。两个工具都跑一遍最稳。 第五步,如果你想自己核一遍某个属性到底能不能挂在某个类型上,不用查文档,直接下词汇表。schema.org给开发者提供的词汇表下载 (https://schema.org/docs/developers.html)里有完整的JSON-LD版本,一点五兆左右,用几行代码就能查domainIncludes: import json g = json.load(open('schemaorg-current-https.jsonld', encoding='utf-8'))['@graph'] props = {n['@id']: n for n in g if 'rdf:Property' in ( n.get('@type') if isinstance(n.get('@type'), list) else [n.get('@type')])} def domain_of(p): v = props['schema:' + p].get('schema:domainIncludes') v = v if isinstance(v, list) else [v] return [x['@id'] for x in v] print(domain_of('citation')) # ['schema:CreativeWork'] print(domain_of('subjectOf')) # ['schema:Thing'] 这段代码是本文那张属性表的来源,跑一次不到一秒。比在论坛上问“这个属性能不能这么写”快得多,也可靠得多。 ## 常见问题解答 ## 评测网站没写过我们的产品,能不能先把标记写上? 不能。Google的评价摘要规则里有两条硬要求:禁止汇总来自其他网站的评价或评分,以及标记的评价内容必须在这一页上让用户看得到。页面上没有对应内容、只在JSON-LD里写一条好评,属于典型的欺骗性标记,轻则整段标记被忽略,重则吃结构化数据的人工处罚。在美国市场还牵扯虚假背书的合规风险。 ## citation和subjectOf有什么区别,该用哪个? 差别在于它们能挂在什么类型上。查schema.org官方词汇表,citation的domainIncludes只有CreativeWork,挂在Product上是无效属性;subjectOf的domainIncludes是Thing,任何类型都能用。正确分工是Product上写subjectOf表示这件商品是那篇评测的对象,WebPage节点上写citation表示本页引用了那篇文献,两个可以同时写。 ## 能把第三方评测的分数并进aggregateRating吗? 不能,这是最常见的违规写法之一。aggregateRating的语义是页面上展示的全部评价的汇总,把一个第三方媒体分数和自家用户评分混算,既是跨站聚合又是页面上看不到对应内容,两条规则一起踩。正确做法是让两条线各走各的:用户评论走aggregateRating,第三方评测走subjectOf。 ## 写了subjectOf能不能拿到搜索结果里的星标? 不能,它根本不是富媒体属性,不产生任何搜索结果里的视觉变化。顺带澄清一个流传很广的说法:2019年Google收紧自我评价时,限制只针对LocalBusiness和Organization两类,Product并不在其中。但电商的星级评价现在很大程度上走Merchant Center的商品评价数据源,页面上的JSON-LD未必能触发展示。 ## AI到底读不读JSON-LD? 实时抓取一个页面的时候基本不读。searchVIU在2025年10月的对照测试里设计了八个场景,Gemini取到4个、ChatGPT取到3个、Claude一个都没取到,而且纯粹只放在结构化数据里的场景全部失败。能被取到的信息全都同时出现在可见HTML里。结构化数据真正起作用的地方在索引层和知识图谱层,不在实时抓取层。 ## 怎么确认某个属性能不能挂在某个类型上? 下载schema.org官方词汇表的JSON-LD版本,查那个属性的domainIncludes里有没有你的类型或者它的某个祖先类。比如Product的继承链只有Product到Thing两层,所以domainIncludes里写着Thing的属性对它都合法。整张词汇表1676个属性里,对Product合法的只有72个。 ## 权威参考资料 ## 404页面有多贵?114个大站说一句没有就要66KB - URL:https://zhangwenbao.com/404-page-crawl-budget-byte-audit.html - 分类:技术SEO - 发布:2026-08-05 | 更新:2026-09-06 - 摘要:商品下架、改版留下的旧地址,爬虫每天还在敲。敲一次,服务器把整张站点外壳端出来告诉它这里没有东西——导航、页脚、几十个第三方脚本一个不少,这笔字节全额记在抓取预算上。 - 关键词:技术SEO,抓取预算,HTTP状态码 > **TLDR**:摘要:对131个国际电商站各要了14个地址,其中11个是编出来的、这世上根本不存在。首页能进的114个站里,103个老老实实回了404或410,只有11个嘴上说“有”。状态码这一关几乎人人及格,可代价藏在别处:一句“没有”,压缩后中位数还要传66.1KB,解压开是363KB,最大的那个站解压后5.73MB。这个数字是首页的0.83倍——服务器说“我没有这个东西”,花掉的带宽跟它把整个首页端出来差不多。 > 摘要:对131个国际电商站各要了14个地址,其中11个是编出来的、这世上根本不存在。首页能进的114个站里,103个老老实实回了404或410,只有11个嘴上说“有”。状态码这一关几乎人人及格,可代价藏在别处:一句“没有”,压缩后中位数还要传66.1KB,解压开是363KB,最大的那个站解压后5.73MB。这个数字是首页的0.83倍——服务器说“我没有这个东西”,花掉的带宽跟它把整个首页端出来差不多。 事情的起因很土。上个月帮一个做宠物用品的独立站看抓取日志,发现Googlebot有相当一部分请求打在一批早就删掉的商品地址上。这不稀奇,改版之后总有这种尾巴。稀奇的是把那些请求的响应大小拉出来一看,每一条都在两百多KB。 一个已经不存在的页面,凭什么还要传两百多KB? 于是就有了这次普查。131个国际电商站,每个站要14个地址:两个是真实存在的(首页和robots.txt,当对照组),十一个是随手编出来的、这世上不可能存在的路径,还有一个是把同一个不存在的地址再要一遍。想知道的事情很简单——当你朝一个站要一件它没有的东西,它是怎么回答你的,以及这句回答要花多少钱。 ## 一个不存在的地址,站点要花多少字节来回答? 先说结论,再说怎么来的。首页能正常打开的有114个站,其中103个对不存在的地址给出了404或410。这103个站的错误页,压缩之后传输量中位数67722字节,也就是66.1KB;解压开是371962字节。 66KB听起来还行?那就换个参照物。同一批站的首页,用同样的方式量一遍,错误页跟首页的传输量之比中位数是0.83。有12个站的错误页比自己的首页还大。 口径 | 中位数 | 最大 | 超过100KB的站 | 压缩后(真正走网线的字节) | 66.1KB | 521KB(rab.equipment) | 30个 | 解压后(浏览器要解析的字节) | 363KB | 5.73MB(misen.com) | 88个 | 解压后超过1MB的有16个站,超过512KB的有38个。排在最前面的那几个,misen.com 5729744字节、burrow.com 4649467字节、dreametech.com 3308733字节、eufy.com 2604079字节、casetify.com 2587949字节。这些数字后面跟着的都是知名品牌,不是什么野路子小站。 顺便说一句,2.6MB这个量级已经越过了Googlebot抓取体积的常见讨论线 (https://zhangwenbao.com/crawl-size-checker-2mb-googlebot-fetch-limit-guide.html)。一个用来告诉爬虫“这里什么都没有”的页面,体积够得上一次正经的正文抓取。 ## 先证明这把尺子本身是准的 在往下走之前得先过一关。任何“A和B不一样”的结论,前提都是“A和A自己一样”。所以每个站上都多要了一次同一个不存在的地址,看两次回来的字节对不对得上。 结果:114个站里,两次字节完全相同的40个,相差不到2%的74个,一个不稳的都没有,抖动的中位数是0字节、最大216字节。另外还编了第二个完全不同的不存在路径,两个路径的状态码114比114全部一致。 更狠的一层对照是跨轮的。这次普查前后跑了两轮,中间隔了将近一个小时。两轮都返回404的65个站,字节相对差的中位数是0.0000,差得最多的philips.com也只有0.9%。同一个站隔一小时问两次,它说“没有”的方式一个字节都不带变的。 这一步不能省。之前量爬虫和用户看到的页面差异那次 (https://zhangwenbao.com/page-content-jitter-baseline-seo-diff-false-positive.html)就吃过亏——不补对照组,量出来的74%差异有七十多个百分点是页面自己的抖动。这回先把零点钉死,后面所有的差异才站得住。 ## 状态码这一关,是不是其实大家都过了? 是,而且过得比预想的漂亮。114个可判定的站里: - 返回404的102个 - 返回410的1个(zwilling.com,唯一一个用410 Gone (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/410)的) - 返回200的11个 诚实率90.4%。这跟很多人的印象不太一样——业内讲软404讲了十几年,好像遍地都是。至少在这批体量的电商站上,状态码这道题基本都做对了。 更有意思的是稳定性。六种不同形态的不存在路径都试了:根目录下的、带尾斜杠的、塞进/products/里的、塞进/collections/里的、四层深的、带.html后缀的。六种形态返回404的站数分别是102、101、103、101、103、102,上下浮动不超过2个站。站点对“不存在”的判断跟路径长什么样几乎没关系,这说明这个逻辑写在很靠前的地方,多半是平台或框架的默认行为,不是谁一条条配出来的。 这跟同一个页面十一种写法都返回200 (https://zhangwenbao.com/url-path-normalization-case-slash-duplicate-seo.html)那次量到的结论是一枚硬币的两面:路径归一化跑在你写的所有规则之前,存在的东西被它放宽,不存在的东西也被它统一挡住。 所以真正值得聊的不是“有没有回404”,而是回这个404的时候顺手做了些什么。 ## 那几百KB里装的到底是什么? 把错误页的HTML拆开数了数:103个站的404页面上,<a>标签数量中位数97个、最多1703个;<script>标签中位数39个、最多230个。 这就说清楚了。那几百KB不是错误信息,是整张站点外壳:头部导航、巨型下拉菜单、页脚的全部链接、语言切换、货币切换、Cookie横幅、客服挂件、埋点脚本、A/B测试脚本、推荐引擎、评价挂件。用户走错门,站点把整个商场的平面图连同全部导购一起塞给他。 体感上这挺贴心。可对爬虫来说,它拿到的是一份跟另外几千个页面高度雷同的模板,正文区域写着“页面不存在”。 ## 八个站,说“没有”比说“有”还贵 按解压后的字节算,错误页跟首页之比超过1的有8个站;按压缩后的传输量算是12个。最极端的几个: 站点 | 404页字节 | 首页字节 | 比值 | sostrenegrene.com | 72263 | 38314 | 1.89 | dji.com | 317079 | 168217 | 1.88 | casetify.com | 2587949 | 1464059 | 1.77 | montbell.com | 139927 | 88445 | 1.58 | 怎么会有这种事?首页通常是全站优化最狠的一个页面,图片懒加载、脚本延迟、首屏内联,能砍的都砍过。而404页面没人管,它继承的是那套没被优化过的原始模板,该加载的一样不少,该延迟的一个没延迟。优化过的页面和没人管的页面放在同一个站上,差距就是这么来的。 ## 响应快不快 耗时这一栏反倒还行:404的响应时间中位数509毫秒,首页是815毫秒。最慢的几个是segway.com 2940毫秒、braun.com 2478毫秒、assos.com 2326毫秒。 比首页快是意料之中的,毕竟不用查数据库。但两三秒的错误页仍然值得警觉,那说明这个页面在渲染时还在跑一整套业务逻辑。慢查询和抓取预算那笔账 (https://zhangwenbao.com/mysql-slow-query-log-signal-noise-ttfb-crawl-budget.html)在这里同样成立,只是账单开在了一个不存在的地址上。 ## 压缩之后真正传出去的是多少? 这一节是自己给自己纠的偏,写出来是因为踩这个坑的不会只有保哥一个。 第一轮跑完,手上的数字是“错误页平均621745字节”。这个数听着骇人,六十多万字节。差点就这么写出去了。 问题在于,HTTP客户端默认会替你把响应解压,你拿到的len(body)是解压之后的长度。而抓取预算、带宽账单、CDN流量费,算的全是压缩之后真正走网线的那些字节。这两个口径在这批站上差了5.5倍。 所以又跑了一轮,这次不解压,直接数原始字节流: - 压缩后中位数67722字节,解压后中位数371962字节,压缩比中位数0.18 - 用Brotli的75个站,用gzip的21个,用zstd的1个,一点不压的5个站 - 压缩后超过100KB的30个站,超过500KB的只剩1个(rab.equipment,521KB) 纠偏之后结论没有反转,只是变得能站住脚了:66KB依然是一个不小的数,尤其考虑到它对应的信息量是“没有”这两个字。但5.73MB那种说法只能用在“浏览器要解析多少”这个语境里,不能拿去算带宽。 那5个完全不压缩的站要单独说一句。压缩类型的配置盲区 (https://zhangwenbao.com/content-encoding-negotiation-gzip-brotli-crawl-budget-seo.html)在别处也常见,nginx出厂只压HTML这一种类型,其余的全额计费。放在错误页上,不压缩意味着它的传输量直接等于解压后的体积。 ## 同一个站,为什么 .css的“没有”比网页的“没有”便宜两百倍? 这是这次普查里最硬的一组对照,因为它发生在同一个站、同一次会话、同一个CDN后面,唯一的差别只是要的东西后缀不一样。 同样是不存在的地址,请求/xxx和请求/xxx.css,中位数分别是: 请求形态 | 字节中位数 | 耗时中位数 | 网页路径(/xxx、/products/xxx等六种) | 371983 - 385587 | 271 - 342毫秒 | 不存在的 .css | 1970 | 256毫秒 | 不存在的 .js | 1708 | 241毫秒 | 不存在的 .jpg | 338402 | 468毫秒 | 中位数上 .css只要1970字节,跟网页路径差了将近两百倍。但平均数是280157字节——这个巨大的落差说明样本裂成了两半。逐站看确实如此:52个站的资源形态明显更省,51个站两者一样大,一个反过来的都没有。 省下来的那一半是怎么做到的?服务器在路由的最外层就按后缀判断了:这个请求要的是静态文件,静态文件目录里没有,直接吐一个几十字节的空响应,连应用框架都不惊动。brompton.com是个漂亮例子,不存在的 .css回21字节、.js回22字节、.jpg回一个78字节的透明GIF,而同一个站不存在的网页路径回215528字节。 另一半没这么做的站,请求走进了框架的兜底路由,然后框架尽职尽责地渲染了整张错误页——哪怕请求头上明明白白写着我要的是一个样式表。省得最多的几个站落差惊人(按.css、.js、.jpg三种形态的平均算):misen.com从5729744字节掉到1909828,ouraring.com从1226885掉到26743。后者才是这条路径该有的样子。 ## 还有一件更别扭的事:类型也对不上 顺手统计了返回的Content-Type: - 请求 .css,回text/html的54个站,占52.4% - 请求 .js,回text/html的54个站,占52.4% - 请求 .jpg,回text/html的98个站,占97.0% 图片这一项几乎全军覆没。101个站里只有一个(brompton.com)老实回了image/gif。也就是说,浏览器去要一张图,服务器回了一份几百KB的网页,还盖着“这是网页”的章。浏览器当然不会把它当图片渲染,最终效果是一个碎图图标,代价是几百KB的传输和一次完整的服务端渲染。 这个坑在nginx配置的静默副作用 (https://zhangwenbao.com/nginx-config-silent-seo-side-effects-audit.html)里属于同一族:配置本身不报错,reload每次都通过,只有在“请求一个不存在的东西”这条冷门路径上才现原形。爬虫报的死链和Googlebot实际抓的从来不是同一批 (https://zhangwenbao.com/relative-url-resolution-crawler-googlebot-broken-link-seo.html),一部分原因也在这儿。 ## 说“有”的那十一个站,麻烦在哪? 11个站对不存在的地址返回了200。名单:aliexpress.com、govee.com、iittala.com、innisfree.com、kotn.com、narwal.com、on.com、prose.com、shein.com、temu.com、zalando.com。 两个最大的跨境平台都在里面,这一点挺说明问题的。 它们的表现分三类。第一类是跳走:aliexpress.com跳了三次最后落到一个404页面上、govee.com和iittala.com各跳一次回首页。跳到首页这种做法,Google官方文档里点名说过 (https://developers.google.com/search/docs/crawling-indexing/http-network-errors),会被判成软404,因为地址变了、状态码却是200,搜索引擎只能自己猜。 第二类是原地返回一个壳:innisfree.com回了1802字节的空HTML,temu.com 2910字节,on.com 4348字节,narwal.com 4973字节。这些都是单页应用,路由在浏览器里,服务端根本不知道这个地址存不存在,先把壳发给你再说。前端框架站的渲染模式选择 (https://zhangwenbao.com/react-nextjs-framework-seo-rendering.html)在这里直接决定了状态码能不能给对。 第三类最贵:govee.com回了3273316字节、shein.com回了1133975字节,都是200。一个不存在的地址,换来3.2MB的200响应。 ## 它们的noindex和canonical都写了什么 这11个站里,页面上带noindex的只有kotn.com一个。canonical方面,govee.com指向https://us.govee.com、shein.com指向https://sg.shein.com/、prose.com指向/,其余的干脆没有canonical。 值得说明的是,没有一个站的canonical指回这个不存在的地址自己。所以这批200不至于变成无限的索引空间——canonical至少把它们归并到了首页那一边。但canonical是提示不是命令 (https://zhangwenbao.com/canonical-tag-common-mistakes-hint-not-directive.html),Google会自己选规范页;人机验证屏被当成正文索引 (https://zhangwenbao.com/bot-check-screen-deindex-canonical.html)那个案子就是这么翻车的。真正该做的是把状态码给对,而不是指望后面几道闸兜住。 对照一下正常返回404的那103个站:带noindex的21个,带canonical的72个,两样都没有的21个。404页面本身不需要noindex,状态码已经把话说完了,这21个属于多做了一步也不亏。反过来,接口和feed这类没有head标签的地址 (https://zhangwenbao.com/machine-readable-endpoints-x-robots-tag-noindex-audit.html)就只能靠响应头说话,状态码在那里更是唯一的表达手段。 ## 平台默认值替你做完了这道选择题 按建站平台分组,压缩后的传输量中位数是这样: 平台 | 站数 | 404传输量中位数 | 说“有”的站 | Shopify | 59 | 81091字节 | 2 | Magento | 3 | 98115字节 | 0 | 认不出平台 | 18 | 54383字节 | 9 | Salesforce Commerce | 10 | 35062字节 | 0 | BigCommerce | 2 | 37488字节 | 0 | Next.js | 10 | 25081字节 | 0 | Next.js那一组是最省的,中位数25KB,只有Shopify的三分之一。原因不神秘:Next.js有一个约定俗成的not-found页面,默认长什么样就是什么样,很多团队根本没动过它,于是它保持了一个极简的形态。而Shopify主题里的404模板挂在完整的layout下面,导航、页脚、全套挂件一个不少。 说“有”的11个站里,有9个落在“认不出平台”这一组。这一组基本是自研或者重度定制的站,恰恰是最容易漏掉这条路径的一类——用现成平台的时候,这道题平台替你答了;自己写的时候,就得自己记得答。 ## 缓存头也是默认值的产物 顺手看了404响应的Cache-Control:写private, no-store的46个站,压根没这个头的14个,其余是各种no-cache组合。 这意味着绝大多数站的错误页是每次现做的,同一个不存在的地址被要一万次,服务端就渲染一万次。对一个内容永远不变的响应来说,这个默认值不太合理。多层缓存那套逻辑 (https://zhangwenbao.com/multilayer-cache-purge-order-and-receipt.html)在这里可以反过来用:错误页恰恰是最适合被边缘节点缓存的东西。 ## 把问的节奏放慢,答案会变吗? 会变,而且变得很不讲道理。这一节是方法论,但它同时是这次普查里最贵的一个教训。 第一轮用的是4个并发、每个请求之间隔0.35秒,跑完发现36个站返回429,也就是“你要得太快了”。这些站的数据全废了。 于是把节奏放慢到2个并发、间隔1.6秒,整批重跑。结果: - 429的站从36个降到6个 - 37个站从被拒变成能进 - 但有7个站反过来了:快的时候能进,慢下来反而被拒(allbirds.com、aloyoga.com、avocadogreenmattress.com、awaytravel.com、baseus.com、beistravel.com、swarovski.com) 如果只看前两条,很容易得出“放慢就能绕过限流”这个结论。第三条把它否掉了。限流不是一条你放慢就一定能压到线下的曲线,它按时间窗计数,你慢下来只是换了一个窗口落脚,运气不好照样撞上。 这件事对做SEO的人有直接的用处。限速规则拒掉的第4个请求要是robots.txt,全站抓取会停十几个小时 (https://zhangwenbao.com/nginx-rate-limit-robots-txt-crawl-rate-seo.html);抓取速率被调低的那几天,服务器日志里可能一条错误都没有 (https://zhangwenbao.com/slow-server-truncated-response-crawl-rate-seo.html)。爬虫也是这样,在别人的限流窗口里碰运气。 还有一层:那17个始终没进去的站(403十个、418一个、429六个),它们只能算“判不了”,不能算“没有404页面”。把判不了的样本混进分母是一种很常见的作假,哪怕是无意的。 ## 三个数先量出来,再谈改 这件事的排查成本极低,低到没有理由不做。三条命令,一分钟: curl -s -o /dev/null -w "%{http_code} %{size_download}\n" \ -H "Accept-Encoding: gzip, br" https://你的域名/zwb-not-exist-9x8 curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}\n" \ https://你的域名/zwb-not-exist-9x8.css curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}\n" \ https://你的域名/zwb-not-exist-9x8.jpg 第一条看状态码和传输量,第二三条看后缀路径有没有被短路掉。注意size_download在带Accept-Encoding时给的是压缩后的字节,正是你要的那个口径。用curl -I查响应头有它自己的坑 (https://zhangwenbao.com/curl-head-get-response-header-diagnosis-seo.html),这里必须用GET。 拿到三个数之后对号入座: 症状 | 该改哪里 | 大概能省多少 | 状态码是200 | 先修状态码,其它都是后话 | 决定性的 | 状态码对,传输量 > 100KB | 给错误页做一套精简模板,砍掉巨型导航和第三方挂件 | 本批实测可降到25KB一档 | .css/.jpg也返回整张HTML | 在服务器层给静态后缀加一条兜底规则,不进应用 | 单次省掉99%以上 | Content-Type与后缀对不上 | 同上,顺带把类型给对 | 省的是浏览器的困惑 | Cache-Control是no-store | 允许边缘节点缓存错误页 | 省的是服务端渲染次数 | ## 错误页该长什么样 不用做成极简的白底黑字,那样用户体验会掉。合理的做法是给404单独一套模板:保留品牌头部、一个搜索框、几条主要分类的链接,其余全砍。参照本批数据,25KB那一档是完全做得到的,而且视觉上并不寒酸。 要砍的重点是第三方挂件。中位数39个<script>里,真正跟“告诉用户走错了”有关的一个都没有。评价挂件、推荐引擎、A/B测试框架、客服机器人,在一个不存在的地址上全都无事可做,却照样被下载和执行。 ## 删了商品之后到底该回什么 顺带说个常被问的:商品下架了,地址该回404还是410?404的意思是“我不知道这里有没有东西” (https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404),410的意思是“确实有过,我确认它没了”,两者的正式定义都写在RFC 9110的状态码那一章 (https://www.rfc-editor.org/rfc/rfc9110.html)里。哪些死链必须修、哪些纯属白费功夫 (https://zhangwenbao.com/broken-links-seo-worth-fixing-triage-guide.html)那篇讲过判据:有替代品就301到替代品,没有替代品且确定不回来就410,拿不准就404。 本批103个说“没有”的站里只有zwilling.com一个用了410。这不是说其他人做错了,只是说明这个区分在实践中基本没人做——而对搜索引擎来说,410确实能让它更快地把这个地址从索引里拿掉。 ## 把它挂进哪个流程 这不是一次性的活。改版、换主题、上CDN、换框架版本,都可能把这条路径改回去。合适的做法是把上面三条curl写进上线后的冒烟检查,跟可索引性体检 (https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html)放在一起跑。死链检测 (https://zhangwenbao.com/deadlink-checker-404-redirect-link-health-guide.html)查的是“该活的活没活”,这一项查的是“该死的死得干不干净”,两边合起来才是完整的。顺带把站点地图里那些已经坏掉的网址 (https://zhangwenbao.com/magento-sitemap-url-audit-dead-links-redirects.html)一起筛一遍,那批地址正是爬虫撞上错误页的主要来源。 保哥这些年见过最离谱的一次,是一个站把404模板挂在了带商品推荐的layout下面。推荐引擎每次都要查一遍数据库,于是每一个爬虫撞上的死链,都在数据库上开了一次全表扫描。分面导航生成的海量URL (https://zhangwenbao.com/faceted-navigation-seo-crawl-budget-index-control.html)撞上这种配置,就是一场没有尽头的自我攻击。 ## 常见问题解答 ## 返回404的页面还需要加noindex吗? 不需要。状态码404本身已经告诉搜索引擎这个地址不该进索引,再加noindex是重复的。本批103个正常返回404的站里有21个加了,属于多做一步不亏,但没加的82个也不构成问题。真正需要noindex的是那些状态码给不对、只能返回200的场景,而那11个返回200的站里恰恰只有一个加了。 ## 错误页几百KB,真的会影响SEO吗? 影响的是抓取预算,不是排名。Google关于大型网站抓取预算的说明 (https://developers.google.com/search/docs/crawling-indexing/large-site-managing-crawl-budget)里把软404单列成一项浪费,理由正是这个:爬虫每天在你站上的额度是有限的,花在错误页上的字节和请求数就是从正经页面那里挪走的。对几百个页面的小站这笔账可以忽略,但对商品动辄上万、改版频繁、死链存量大的电商站,这是一笔实打实的开销。判断标准很简单:去日志里看爬虫每天撞多少次404,乘以你刚量出来的那个传输量。 ## 怎么判断我的站是不是软404? 用curl请求一个绝对不存在的地址,看返回的状态码。是200就是软404,无论页面上写着什么。要特别注意跳转到首页这种做法,最终状态码是200、地址也变了,这在搜索引擎那里同样算软404。Search Console的覆盖率报告里也有专门一栏,但它是抽样的、有延迟,自己curl一下更快。 ## 单页应用没法在服务端判断地址存不存在,怎么办? 三条路。一是给路由做服务端渲染或预渲染,让服务器知道哪些地址是有效的;二是用框架自带的not-found约定,让构建期就生成正确的错误响应;三是退而求其次,在边缘节点上维护一份有效地址清单,命中不了的直接由CDN返回404。第三条最容易落地,代价是清单要跟着内容更新。 ## 不存在的图片和CSS返回整张HTML,除了浪费流量还有别的害处吗? 有。浏览器拿到一份Content-Type是text/html的响应去当样式表用,会直接拒绝应用,控制台报一条MIME类型不匹配。如果这个样式表恰好是首屏关键的那一份,页面会以裸HTML的形态渲染一瞬间。更麻烦的是这类问题在本地开发环境几乎不出现,因为开发服务器的静态目录和线上不是一回事。 ## 把错误页缓存起来会不会导致真实页面上线后还显示404? 会,所以缓存时间要短,几分钟到一小时是常见的取舍,同时上线流程里要有清缓存这一步。更稳的做法是只在CDN层缓存、不在浏览器层缓存,这样你随时可以主动刷掉。风险确实存在,但跟每次都回源渲染一整套模板相比,多数站点的天平是倒向缓存这一边的。 ## 410用起来有什么风险? 410表示“确认没了、别再来了”,语义比404强。风险在于它不可撤销的味道太重——如果这个商品以后还会上架、或者这个地址只是暂时下线,用410会让搜索引擎更快地把它清出索引,回来的时候要重新爬一遍。判据是“这个地址还有没有回来的可能”,没有就用410,有就用404。 ## 权威参考资料 ## 可索引性一键体检怎么用?页面被什么挡在索引外一次查清 - URL:https://zhangwenbao.com/indexability-checker-noindex-canonical-redirect-diagnosis-guide.html - 分类:技术SEO - 发布:2026-07-26 | 更新:2026-07-26 - 摘要:保哥笔记可索引性一键体检使用教程。逐条打桩实测这款工具的六项判定:状态码与重定向链、robots.txt规则组与最长匹配、meta robots、X-Robots-Tag响应头、canonical归属与hreflang自引用。 - 关键词:技术SEO,索引,收录诊断 > **TLDR**:摘要:可索引性一键体检把状态码、重定向链、robots.txt判定、meta robots、X-Robots-Tag、canonical这六处信号合并成一次请求,服务器以Googlebot的身份去抓,然后告诉你这一页能不能进索引。我们把它的后端接口逐条打了桩,主业是可靠的——robots规则组和最长匹配算得准,被拦时能把生效的那条规则原样端出来。 但有四处判定会给出与真实情况相反的结论:meta标签把content写在name前面,工具读不到noindex,直接放绿灯;X-Robots-Tag带爬虫名前缀时它照单全收,把只对某个爬虫生效的指令算到Googlebot头上;重定向目标写成相对路径时它会把你送到网站根目录,然后报一个并不存在的404;canonical只是域名大小写不同,它判你指向了别处。这四条都不是概率问题,是代码路径,本文给出每一条的复现方式和该怎么绕。 > 摘要:可索引性一键体检把状态码、重定向链、robots.txt判定、meta robots、X-Robots-Tag、canonical这六处信号合并成一次请求,服务器以Googlebot的身份去抓,然后告诉你这一页能不能进索引。我们把它的后端接口逐条打了桩,主业是可靠的——robots规则组和最长匹配算得准,被拦时能把生效的那条规则原样端出来。 但有四处判定会给出与真实情况相反的结论:meta标签把content写在name前面,工具读不到noindex,直接放绿灯;X-Robots-Tag带爬虫名前缀时它照单全收,把只对某个爬虫生效的指令算到Googlebot头上;重定向目标写成相对路径时它会把你送到网站根目录,然后报一个并不存在的404;canonical只是域名大小写不同,它判你指向了别处。这四条都不是概率问题,是代码路径,本文给出每一条的复现方式和该怎么绕。 页面不被收录这件事,麻烦在于它没有报错。服务器不会给你发邮件,Search Console的提示往往滞后一两周,而页面本身在浏览器里打开一切正常。真正把它挡在外面的东西,一半藏在HTTP响应头里,另一半藏在你以为不会出问题的地方——比如一个上线时被顺手改掉的robots.txt,或者CDN配置里多出来的一行响应头。 保哥笔记的可索引性一键体检 (https://zhangwenbao.com/tools/indexability-checker.php)做的就是把这些散落的信号一次性收齐。这篇教程不打算复述它的界面,而是把它的判定逻辑逐条拆开:哪些结论可以直接信,哪些结论需要你再看一眼原始值,以及在什么情况下它会给出与事实相反的答案。 ## 这款工具一次请求到底查了哪几层? 它的工作方式很直接:你给一个网址,服务器带着Googlebot的User-Agent去抓,不跟随重定向地逐跳走完整条链,再单独去根目录取一次robots.txt,最后把页面HTML里的几个关键标签解析出来。整个过程只发生在服务器端,跟你本地的浏览器、插件、登录状态都没关系——这一点很重要,因为很多掉索引的排查之所以绕远路,就是因为在自己浏览器里看到的和爬虫看到的不是同一份东西。 信号可以按“谁能挡住收录”分成三层,工具的结论也是按这个顺序推的。 层级 | 具体信号 | 能否单独阻断收录 | 藏在哪里 | 传输层 | 状态码、重定向链 | 能,4xx与5xx直接出局 | HTTP响应行 | 许可层 | robots.txt规则、meta robots、X-Robots-Tag | 能,任意一处noindex即出局 | 根目录文件、HTML头部、响应头 | 归属层 | canonical、hreflang自引用 | 不能,但会把收录资格让给别的地址 | HTML头部或Link响应头 | 把这张表记住,比记住工具的按钮位置有用得多。因为无论你用哪款工具,排查顺序都应该是从上往下:传输层没通,下面查了也白查;许可层被拒,归属层写得再漂亮也进不去。 工具最终会输出三种结论:可以被收录、能抓到但有需要确认的地方、无法被收录。前两种之间的界线其实挺微妙,后面会专门说。 ## 它用Googlebot的身份去抓,这一点意味着什么? 工具发请求时带的User-Agent是Googlebot的标准写法。这个设计有它的道理,也有你需要知道的副作用。 好处是它能触发那些“按爬虫身份区别对待”的逻辑。有些站会给爬虫返回不带弹窗、不带同意条的精简版本;有些付费墙会对爬虫开放全文;还有些安全设备会专门给非浏览器UA一个验证页。用真实浏览器去看,这些差异全都看不见,而搜索引擎看到的恰恰是另一份内容。工具帮你站到了爬虫的位置上。 副作用有两个,都值得留意。 第一,声称自己是Googlebot但IP不是Google的,属于伪装UA。规矩一点的站会做反向DNS校验,发现对不上就返回403或者验证页。所以当你测别人的站拿到403时,先别急着下结论说对方屏蔽了搜索引擎,很可能只是它在拦冒充者。这时候换个思路:用普通浏览器UA的工具再测一次,两边结果不同就说明对方在做UA区分。 第二,如果某个站真的给Googlebot和普通用户返回了实质不同的内容,那是Google明令禁止的伪装行为,风险在站方而不在你。但作为诊断者,你至少能通过这个差异发现问题的存在——这在接手一个来路不明的老站时非常有用。 还有一个容易忽略的点:它抓的是不带任何Cookie、不带登录态、不带地域偏好的裸请求。会员可见的内容、按地区跳转的内容、A/B测试分流的内容,工具看到的都是默认分支。这跟爬虫的真实处境基本一致,但和你在自己浏览器里看到的往往不是一回事。 ## robots.txt这一块它算得准吗? 先说它做对的部分,这部分是这款工具最值钱的地方。 robots.txt的规则判定不是“谁写在前面听谁的”,而是一套有明确优先级的算法:先在文件里找适用于当前爬虫的规则组,找不到就退回通配组;然后把所有能匹配这个路径的规则挑出来,取路径最长的那一条;长度相同时,Allow压过Disallow。RFC 9309对这一点写得毫不含糊——最具体的匹配必须被采用,而最具体的定义是“字节数最多的那一条”。 我们拿本站被屏蔽的一个内部路径去打桩,工具的返回是这样的:判定为不允许抓取,命中规则原样输出为Disallow: /_audit,并且标明生效的规则组是通配组。这三样信息凑齐了,才叫可用的诊断——只说“被robots挡住了”而不告诉你是哪一行挡的,你还得回去在几百行文件里人肉找。 换成正常的文章页去测,它返回允许抓取、没有规则匹配这个路径,同时把robots.txt里声明的sitemap地址一并带回来。这几项都对。 顺带说一个很多人栽过跟头的细节:Disallow: /admin挡住的不只是后台,而是所有以admin开头的路径,/administrator-guide.html这种正常文章也会被一起拦掉。工具会把生效的规则原样打出来,你一眼就能看见是不是这条在作怪。这类“以为只挡了一个目录,实际挡了一片”的事故,在改版后的站上出现频率高得出奇。 ## robots.txt取不回来的时候,默认放行对吗? 这就要说到第一处需要你留个心眼的地方了。 工具取robots.txt的方式是:拼出根目录地址,发一次请求,只有返回200才把内容拿去解析,其余情况一律当成“没有robots.txt,默认全部允许”。界面上会老实告诉你“robots.txt返回404,视为全部允许”——文案是诚实的,问题在于这个默认对404成立,对500不成立。 RFC 9309把这两种情况分得很清楚。4xx属于Unavailable,规范允许爬虫在没有规则可依时抓取全站;而5xx属于Unreachable,原文的要求是爬虫必须假定完全禁止抓取,只有在这种状态持续足够长时间(规范举的例子是30天)之后,才可以退回到当作不可用来处理。 方向是反的。你的服务器如果正在闹脾气,robots.txt跟着一起返回503,工具会告诉你“视为全部允许,这一页可以被收录”,而Googlebot那边的实际反应是暂时把整个站的抓取停掉。这种时候你拿着一个绿灯去汇报“技术上没问题”,会很尴尬。 还有一个同源的问题:工具取robots.txt时不跟随重定向。而把robots.txt做301的站并不少见,尤其是那些把静态文件统一托管到CDN或者做了裸域到www归一的站。我们用同样的取法复现了一次——某个营销云平台的裸域robots.txt,不跟随重定向时拿到的是一个301和167字节的空壳,跟随一跳之后能读到的是356条Disallow规则。差别是从零条规则到三百多条规则。 规范这边的要求是明确的:爬虫至少应该跟随五次连续重定向,即使跨主机也一样,只要在五跳内拿到文件就必须按初始主机的上下文解析并遵守。所以当你测的站robots.txt有跳转时,工具给出的“没有规则限制”是个空判断,你得自己把最终地址取出来看一遍。 ## 页面里的两处noindex,工具都读得到吗? noindex可以写在HTML的meta标签里,也可以写在HTTP响应头的X-Robots-Tag里。工具两处都查,也都把原始值打了出来——但这两处的解析各有一个盲区,而且错的方向正好相反:一处该报不报,一处不该报却报。 ## meta robots的属性写反了,工具还认得出来吗? 这是本次实测里最该警惕的一条,因为它的错误方向是漏报——工具给你绿灯,而页面实际上被彻底屏蔽了。 我们放了一个探针页,页面头部只写了一行: <meta content="noindex,nofollow" name="robots"> 属性顺序反过来了,content在前,name在后。HTML规范对属性顺序没有任何要求,浏览器、解析器、搜索引擎都一视同仁,这行标签和常见写法在语义上完全等价,Google会老老实实地把这一页排除出索引。 工具的返回是:metaRobots为空字符串,noindex为false。翻译成界面语言就是“meta robots未设置”加上一个绿色的“可以被收录”。 根子在它的提取正则上——那条正则要求先出现name属性、后出现content属性,顺序一颠倒就匹配不上。同样的模式还用在description和canonical的提取上,所以这几项都存在相同的盲区。 什么样的站会把属性写反?比通常想象的多。模板里用变量拼标签的、SEO插件与主题各输出一半的、前端框架按对象键顺序序列化属性的,都可能生成这种顺序。它在源码里看着完全正常,肉眼也挑不出毛病,恰恰是最容易被工具漏掉的一类。 绕开的办法只有一个:结论显示绿灯但页面就是不收录时,回头在源码里直接搜noindex这个词,而不是相信工具那一栏的“未设置”。搜词的成本是三秒钟,省下的可能是两周的排查。 ## X-Robots-Tag带爬虫名前缀,会不会被算错? 上一条是漏报,这一条正好相反,是误报。 X-Robots-Tag这个响应头允许指定它只对哪个爬虫生效,写法是在指令前面加上爬虫名和一个冒号。Google的规范文档里就有这种用法的例子,含义是:只有名字对得上的那个爬虫才需要遵守,其余爬虫当它不存在。 我们的探针页发了这么一个响应头: X-Robots-Tag: badbot: noindex 页面里的meta robots写的是index,follow。对Googlebot来说,这一页百分之百可以被索引——那条noindex是给一个叫badbot的爬虫看的。 工具的返回是noindex为true,结论直接跳到“无法被收录”。它对这个响应头的处理只有一步:在整个字符串里搜有没有noindex或者none这两个词,搜到就算数,完全不解析前面的爬虫名。 这个误报的杀伤力在于它会把你引向一次完全没必要的紧急排查。有些站会给采集类爬虫、AI训练爬虫单独下noindex或者noarchive指令,这在内容保护上是很常规的做法。工具一看见这行就报红,你以为线上出了大事故,翻半天配置才发现虚惊一场。 正确的读法是:X-Robots-Tag那一栏永远要看原始值。工具好在把原始值原样打出来了,你只要确认冒号前面写的是不是Googlebot,或者干脆没有前缀。有前缀且不是Googlebot,那条红色结论就可以忽略。 ## 跳转与归属这两项,什么时候会给出相反结论? 许可层查完,还剩传输层的跳转链和归属层的canonical。这两项工具都能取到原始值,问题出在它拿到值之后的计算方式上——一个把相对地址算错了目录,一个把等价地址判成了不等价。 ## 重定向目标写成相对路径,结论为什么会翻车? 这一条最隐蔽,因为翻车的样子看起来特别像“真的出问题了”。 HTTP的Location响应头允许写相对路径。老一点的PHP站里,header('Location: next.php')这种写法遍地都是;nginx和Apache的配置里也常见不带前导斜杠的目标。按照RFC 3986的相对引用解析规则,这种目标要相对当前请求的目录来解析——请求的是/tools/a.php,目标写b.php,那就是/tools/b.php。浏览器、curl、Googlebot都是这么算的。 我们的探针是一个放在/tools/目录下的页面,它返回302,Location头就一个裸文件名。工具跟踪重定向链的结果是这样的: 第1跳 302 https://example.com/tools/zzp3.php → zzp4.php 第2跳 404 https://example.com/zzp4.php 它把目标解析到了网站根目录,于是撞上一个不存在的地址,最终结论是“无法被收录:最终状态码是404”。而真实情况是这条跳转好好的,终点在/tools/zzp4.php,返回200。 代码里的处理是:目标不以斜杠开头时,直接把它接到“协议加主机名”后面,中间补一个斜杠。也就是说,只要目标是相对路径,请求URL的目录层级就被整个丢掉了。目录越深,错得越离谱。 这个坑的实际影响面比它看起来大。做迁移、做整站改版的时候,重定向规则往往是批量生成的,相对路径写法在批量规则里非常常见。你拿工具去抽查几条,看到一片404,很容易得出“重定向全写错了”的错误结论,然后去改根本没坏的东西。 判断方法很简单:看链条里那个“→”后面的目标,如果它不是以http开头、也不是以斜杠开头,工具算出来的下一跳地址就不可信,用浏览器实地走一遍才作数。 ## canonical只是域名大小写不同,为什么被判成指向别处? 这一条属于轻伤,但会让结论从绿灯降到黄灯,值得知道。 工具判断canonical是不是自指的方式,是把canonical的值和最终URL都去掉尾部斜杠,然后做字符串比较。相等就是自指,不等就提示“canonical指向了别的地址,意味着这一页把信号让给了目标页”。 我们的探针页写了一个只有域名大小写不同的canonical: <link rel="canonical" href="https://ZhangWenBao.com/tools/zzp5.php"> 返回结果里,canonical是带大写的那串,最终URL是全小写的那串,两者字符串不等,于是被判成指向别处,整体结论降级为“能抓到,但有需要确认的地方”。 RFC 3986说得很直白:scheme和host是大小写不敏感的,HTTP://www.EXAMPLE.com/和http://www.example.com/是同一个URI。所以这就是一个标准的自指canonical,一点毛病没有。 同一个比较方式还用在hreflang的自引用检查上,那里也是严格字符串比对。所以如果你的多语言标注里协议、主机名大小写、尾斜杠跟页面实际地址有任何一点写法差异,工具都会提示“缺少自引用”。这个提示不一定是错的——Google那边确实建议整组hreflang的地址写法保持一致——但它不能作为“标注无效”的判据。 顺带一提,如果canonical确实指向了别的页面,那才是需要认真对待的信号。canonical是提示不是命令,Google有权自选规范页,但一个程序错误地把全站canonical指向首页的站,掉起收录来是成片成片掉的。 ## robots拦截加noindex,为什么是个无效组合? 这个组合值得单开一节,因为它是排查里最反直觉的一处,而工具会专门提示它。 很多人的直觉是:既然想让一个页面彻底不出现在搜索结果里,那就双保险——robots.txt里禁掉,页面里再加个noindex。听起来很稳,实际上等于什么都没做。 原因在于两个机制的作用位置不同。robots.txt管的是“能不能抓”,noindex管的是“抓到之后要不要收”。你先用robots把爬虫挡在门外,它就永远读不到页面里那句noindex。而如果这个地址有外部链接指向它,搜索引擎知道这个地址存在,又被禁止抓取内容,最后可能给出一条没有摘要的结果——想藏的东西反而以最难看的方式露出来了。 正确做法是反直觉的那个:放开robots.txt,让爬虫进来,读到noindex,然后它才会把这一页从索引里拿掉。等确认已经掉出索引了,再决定要不要用robots封路。 工具会在同时检测到这两个信号时给出提示。这个提示是准确的,而且是那种“知道了就不会再犯”的知识点。 ## 绿灯为什么不等于会被收录? 工具给出“可以被收录”的时候,它的准确含义是:在它检查的这六项信号里,没有发现阻断收录的东西。这是一个必要条件的结论,不是充分条件的结论。 可索引和已收录之间隔着好几道关。爬虫得先发现这个地址——没有内链、没有进sitemap的页面,可能压根没被抓过;抓到之后得判断内容值不值得存进索引,重复度高、篇幅极短、和站内其他页面高度雷同的页面会被抓了又丢;就算存进去了,还得排到用户能看见的位置才有意义。 所以看到绿灯却搜不到的时候,接下来该查的不是这六项,而是这几件事: - 这一页有没有站内页面链接过去。一个页面如果只在sitemap里存在、站内没有任何入口,抓取优先级会低得可怜。 - sitemap里有没有它,lastmod是不是真实的。全站lastmod统一刷成今天,效果等同于没有这个字段。 - 内容跟站内已有页面是不是撞了。同一个主题写了三篇,通常只有一篇能拿到排名,其余两篇进索引也是陪跑。 - 是不是刚发布不久。新站或者权重不高的站,从抓取到出现在结果里隔上几周很正常。 反过来,看到红灯基本可以信,因为阻断信号的判定要么是状态码这种硬事实,要么是规则匹配这种可复算的逻辑。唯一需要复核的红灯就是上面说过的X-Robots-Tag带前缀那一种。 ## 还有哪些掉索引的原因,六项信号一个都查不出来? 这六项查的是“有没有人明确禁止收录”。而现实里有一大类掉索引,根本没人禁止过,是搜索引擎自己决定不要了。这类原因工具查不出来,但恰恰是绿灯之后最该往下想的方向。 软404。页面返回200,内容却是“没有找到相关商品”或者一个空列表。状态码骗得过工具,骗不过搜索引擎——它会按内容判定这是个错误页,然后当成404处理。电商站的下架商品、搜索结果页、空标签页最容易变成这种。判断方法是把页面的正文部分单独看一眼,如果一个不知情的人打开会觉得“这页什么都没有”,那它多半已经被判成软404了。 被判为重复而合并。Google会自己选规范页,你的canonical只是众多参考因素之一。当站内有多个高度相似的页面时,它可能把你想要的那一页归到另一页名下。这种情况下工具会显示canonical自指、一切正常,而实际收录的是另一个地址。要确认只能靠Search Console的网址检查,那里会明确告诉你“Google选择的规范网址”是哪一个。 内容质量不够门槛。抓了、也进了索引,过一段时间又被清出去,这在大量自动生成的页面上很常见。参数组合页、按城市批量生成的落地页、只有几十个字的标签页,都是高危对象。这一层没有任何技术信号可查,只能从内容本身下手。 抓取预算耗在了没价值的地址上。站点规模上去之后,爬虫的时间是有限的。如果它每天大半的请求都花在筛选参数、日历翻页、无限滚动生成的地址上,真正重要的新页面就得排队。工具查单页正常,但整站的抓取节奏已经出了问题——这一层要看日志,看爬虫到底把请求花在了哪里。 所以完整的排查顺序应该是两段式:先用工具确认没有硬阻断,再往内容、重复、预算这三层去找。前一段有明确答案,后一段需要判断力,但顺序不能颠倒——在信号层还没排除的时候讨论内容质量,纯属浪费时间。 ## 多语言站体检要多盯哪一项? 做外贸和出海的站,页面往往一式多份,中英法德各一套。这类站用可索引性体检时,有一项要单独盯:hreflang的自引用。 工具会把页面里所有的hreflang标注列出来,并检查里面有没有一条指向页面自己。缺自引用时它给出的提示是“多语言组会被判为无效”。这个提示的方向是对的——按Google的要求,每一个语言版本都必须把包括自身在内的全部替代版本列全,少了自引用,整组标注的可信度就打折。 但前面说过,工具做的是严格字符串比对。这意味着几种写法差异都会被误报成缺自引用: - hreflang里写的是带www的地址,页面实际访问的是裸域。 - hreflang里带尾斜杠,页面地址不带,或者反过来。 - hreflang里是http,页面已经全站升到https。 - 主机名大小写不一致,前面那节说过的老问题。 这几种情况里,第一到第三种其实是真问题,值得改——Google确实建议整组标注用完全一致、且是各语言版本最终地址的写法,跳转地址和替代写法都会增加匹配失败的概率。只有第四种是纯误报。 实操上的建议是:多语言站不要只体检一个语言版本。挑三个语言版本各跑一次,把每一次输出的hreflang清单摆在一起比对,看它们是不是同一组地址、写法是不是一字不差。这个动作两分钟能做完,比出问题之后回头查一整套模板要划算得多。 还有一个多语言站特有的坑:有些站的语言切换是靠地域跳转做的,同一个地址对不同来源IP返回302到不同语言版本。工具的服务器在国内,它看到的永远是这个IP对应的那一份。测这类站时,工具能告诉你“这里有一个302”,但跳到哪里不代表Googlebot会跳到哪里。 ## 掉索引应该按什么顺序排查? 把上面这些拼起来,就是一套可以照着走的顺序。这套顺序的逻辑是“先查不可见的,再查可见的”——因为可见的问题你自己早就看见了,能拖到需要排查的,往往都藏在看不见的地方。 顺序 | 查什么 | 为什么排在这 | 工具里看哪一栏 | 1 | 最终状态码 | 传输层不通,后面全是白查 | 结论行末尾的状态码 | 2 | X-Robots-Tag响应头 | 页面源码里完全看不见,最隐蔽 | 抓取与索引权限第三行 | 3 | robots.txt命中规则 | 改动频繁,且常被上线流程覆盖 | 抓取与索引权限第一行 | 4 | meta robots | 源码可见,但要防属性顺序反写 | 第二行,配合源码搜词 | 5 | 重定向链 | 相对路径目标要手工复核 | 重定向链区块 | 6 | canonical归属 | 不阻断收录,但决定权重给谁 | 第四行与Link响应头 | 改版和迁移之后最容易出事的是前三项,而且这三项有个共同特点:在页面上没有任何可见痕迹。新服务器的配置里带了一行noindex响应头、测试环境的robots.txt被一起发到了生产、CDN把某个目录整体拦了——这些都不会让页面看起来有任何异常。 保哥经手过一次跨境健身器材站的掉收录,页面正常、内容正常、sitemap正常,查到第三天才发现是CDN的一条边缘规则给整个产品目录加了noindex响应头。那次之后我们团队的排查清单就改成了先看响应头再看页面,顺序一换,同类问题的定位时间从天级降到分钟级。 ## 独立站的哪几类页面最该定期体检? 把工具当成一次性的救火队用,收益有限。真正划算的用法是圈出几类高风险页面,改版后、上新后、换主题后各跑一遍。做电商和外贸独立站的,下面这几类值得列进固定清单。 分面筛选与排序参数页。这是重复内容与抓取预算的重灾区。正常做法是让筛选组合页保持可抓但把canonical指向主分类页,或者干脆用robots挡掉参数路径。两种做法各有取舍,但最怕的是两种都做了一半——canonical指向主页面的同时又被robots拦住,爬虫读不到那个canonical,归属关系永远建立不起来。用工具跑一个典型的筛选地址,两栏一起看,一眼就知道当前是哪种状态。 商品变体页。颜色、尺码各自一个地址的站,变体页通常应该把canonical指向主商品页。程序生成的canonical出错时,常见症状是全部变体指向同一个不存在的地址,或者指回自己导致大量近似重复。这一栏工具查得很准,值得每次上新后抽查几条。 缺货与下架页。下架商品该返回什么状态码,取决于它还回不回来。短期缺货保持200并说明补货时间;永久下架且有替代品的做301;彻底没了的用410。最糟的是返回200却渲染一个空白页面,或者跳转到首页——后者会让搜索引擎把这一批地址判成软404。工具能把最终状态码和跳转链一次给你看全。 分页序列。第二页往后的列表页要不要收录,各家策略不同,但至少要保证策略一致。常见事故是分页被noindex,同时又被当成通往深层商品页的唯一通道——爬虫顺着走进来,看见noindex掉头就走,深层商品自然抓不到。 促销落地页。活动期建站、活动后遗弃,是掉索引和死链的主要来源之一。活动结束后如果不处理,这批页面通常既没有内链也没有更新,属于典型的负资产。 保哥给一家做户外装备的独立站定过一份很朴素的检查节奏:每次上新后抽五个商品页和两个筛选页,每次改版后把这五类各跑一遍。工具本身就三十秒的事,难的是把它变成流程里固定的一步而不是出事之后的补救。 ## 四个反直觉结论怎么记? 前面拆的四处判定偏差,光看一遍很难记住。把它们整理成“看到什么现象、该做什么动作”的形式,用起来更顺手。 工具给出的结论 | 可能的真实情况 | 你要做的动作 | 方向 | meta robots未设置,可以被收录 | 标签把content写在了name前面,页面实际带noindex | 在源码里直接搜noindex这个词 | 漏报,最危险 | X-Robots-Tag带noindex,无法被收录 | 指令带爬虫名前缀,只对别的爬虫生效 | 看原始值,确认冒号前写的是谁 | 误报,虚惊 | 重定向终点404,无法被收录 | 目标是相对路径,真实终点在当前目录下 | 浏览器实地走一遍这条跳转 | 误报,会误导返工 | canonical指向别处,存在风险 | 只是主机名大小写或尾斜杠写法不同 | 把两个地址都转成小写再比一次 | 误报,轻伤 | robots.txt返回5xx,视为全部允许 | 规范要求此时假定完全禁止抓取 | 先去把服务器修好再谈收录 | 方向相反 | 规律其实挺清楚:凡是“没发现问题”的结论,都要留一分怀疑;凡是“发现了问题”的结论,先看它给出的原始值。这款工具的可贵之处在于它把原始值全都打出来了,没有藏在结论后面——只要你养成看原始值的习惯,上面这些偏差就都伤不到你。 ## 它的边界在哪里,该配合哪些工具用? ## 这款工具明确做不到的几件事 把能力和边界说清楚,工具才用得踏实。这几条是它明确做不到的: - 不执行JavaScript。抓到的是服务器返回的原始HTML。前端脚本注入的canonical、meta robots,这里一律看不见。好消息是搜索引擎首轮抓取看到的也正是这份原始HTML,所以这个限制反而让你看到了爬虫第一眼看到的样子。 - 不查这一页是否已在索引中。要确认这件事只能用Search Console的网址检查,那需要站点所有权验证,第三方工具做不到。 - 只支持公网地址。内网、本地地址、需要登录的页面都会被直接拒绝,这是防止服务端请求伪造的必要限制。 - 响应体积统计的是传输字节。它接受压缩传输,所以显示的大小是压缩后的,不是解压后的HTML真实体积。判断页面是不是过大时要留意这个口径差。 - 重定向链最多跟8跳。超过就报错退出。真实场景里超过3跳就该合并了,这个上限一般碰不到。 还有一条不算限制但值得知道:它每次只查一个地址。想批量体检得自己一条条来,这时候更合适的做法是先用日志或者爬虫软件圈出可疑的一批,再用它逐个确认细节。 ## 配合哪些工具一起用效果更好? 可索引性只是收录链条的一环,前后各有一段路。 往前一环是robots.txt本身。你如果正在改规则,先在robots.txt生成器与验证器 (https://zhangwenbao.com/robots-generator-preset-validator-wildcard-match-guide.html)里把文件本身的语法和通配符逻辑过一遍,再用可索引性体检去验单个页面的实际判定结果,两边对得上才算稳。 往后一环是页面被发现的能力。一个页面就算所有许可信号都放行,站内没有任何链接指向它,抓取优先级依然低。这一层可以用孤岛页面检测的抽样口径 (https://zhangwenbao.com/orphan-page-finder-sitemap-sampling-internal-link-audit-guide.html)去看看它在站内的入链情况——那篇里也拆了那款工具的数据口径,别拿它的数字直接下结论。 如果你要排查的是整批页面的头部标签质量,而不只是能不能收录,网页Head标签检查器 (https://zhangwenbao.com/meta-checker-weighted-seo-audit-guide.html)覆盖的字段更全,两者的定位不冲突。 🔧 动手试试:可索引性一键体检 输入一个网址,服务器以Googlebot的身份跑一遍,把状态码、重定向链、robots判定、两处noindex和canonical归属一次性摆给你看,并指出是哪一条在起作用。 保哥自研免费在线工具,浏览器打开就能用。 → 打开可索引性一键体检 (https://zhangwenbao.com/tools/indexability-checker.php) ## 常见问题解答 ## 工具说可以被收录,为什么搜索不到? 可索引是必要条件不是充分条件。它只保证没有信号在阻断收录,不保证爬虫已经发现这个地址、判定内容值得存进索引、并且给了排名。绿灯之后该查的是站内入链、sitemap覆盖、内容是否与站内其他页面撞题,以及页面发布了多久。 ## 页面源码里明明有noindex,为什么工具说未设置? 大概率是meta标签的属性顺序反了。工具的提取正则要求name属性出现在content属性之前,写成content在前的话读不到值,会显示未设置并放绿灯。遇到这种矛盾,直接在源码里搜noindex这个词为准。 ## X-Robots-Tag报了noindex,一定是出事了吗? 不一定。这个响应头可以带爬虫名前缀,只对指定爬虫生效。工具不解析前缀,只要字符串里有noindex就判为阻断。看一眼原始值,如果冒号前面写的是别的爬虫名,那条红色结论对Googlebot不成立。 ## 重定向链最后显示404,可信吗? 要看目标写法。目标是完整网址或以斜杠开头的绝对路径时可信;目标是相对路径时不可信,工具会把它解析到网站根目录,得到一个并不存在的地址。这种情况用浏览器实地走一遍才作数。 ## robots.txt返回500的时候,工具说全部允许对吗? 不对。RFC 9309把5xx归为不可达状态,要求爬虫必须假定完全禁止抓取,只有这种状态持续很久之后才可以改按不可用处理。工具把4xx和5xx放在同一个分支里当作允许,方向与规范相反。 ## canonical只是域名大小写不同,为什么被判成指向别处? 工具用的是去掉尾斜杠后的字符串比较,没有做主机名大小写归一。按RFC 3986,scheme和host大小写不敏感,这属于正常的自指canonical。同样的比较方式也用在hreflang自引用检查上。 ## robots屏蔽加noindex是不是双保险? 恰恰相反,等于什么都没做。爬虫被robots挡在门外就永远读不到noindex,页面反而可能因为外链而以无摘要的形式出现在结果里。正确顺序是先放开robots让爬虫读到noindex,等确认掉出索引之后再考虑封路。 ## 它能替代Search Console的网址检查吗? 不能,两者定位不同。它查的是“这一页有没有被什么挡住”,不需要站点所有权,任何地址都能查,也能查竞品;网址检查查的是“Google那边现在是什么状态”,能看到实际收录情况和渲染结果,但只能查自己验证过的站。排查时先用前者定位阻断信号,再用后者确认索引状态。 ## 权威参考资料 ## 人机验证屏被谷歌当正文索引:页面掉收录,规范网址还判给了别的站 - URL:https://zhangwenbao.com/bot-check-screen-deindex-canonical.html - 分类:技术SEO - 发布:2026-07-22 | 更新:2026-07-22 - 摘要:为什么站长自己访问一切正常却照样中招、503和200的后果差在哪、这与已索引但无内容是不是同一个毛病、速率限制与地理封锁怎么误伤Googlebot、修好之后为什么不该再加noindex或robots规则,写给独立站与外贸站的技术负责人。 - 关键词:canonical,技术SEO,索引 > **TLDR**:摘要:谷歌的John Mueller在2026年7月的一期播客里点出了一个很多人从没想过的坑:网站为了拦坏流量挂上的人机验证屏,会被谷歌当成正文抓走并索引。更糟的是,全网成千上万个站用的是同一套验证页模板,谷歌把它们判成近似重复之后,可能选中别人家的页面当规范版本,你的页面就变成了副本。这篇拆开这条链路的每一环,给出状态码对照、身份伪装自查法、按成本排序的排查顺序,以及修好之后让谷歌尽快回来的做法。 > 摘要:谷歌的John Mueller在2026年7月的一期播客里点出了一个很多人从没想过的坑:网站为了拦坏流量挂上的人机验证屏,会被谷歌当成正文抓走并索引。更糟的是,全网成千上万个站用的是同一套验证页模板,谷歌把它们判成近似重复之后,可能选中别人家的页面当规范版本,你的页面就变成了副本。这篇拆开这条链路的每一环,给出状态码对照、身份伪装自查法、按成本排序的排查顺序,以及修好之后让谷歌尽快回来的做法。 先描述一个场景,看看你是不是遇到过。 网站好端端的,没改版、没迁移、没被黑,某天开始有一批页面从搜索结果里消失。你自己点进去,页面打开正常,内容也在。搜索控制台里那些页面标着已抓取但未编入索引,或者被标成了重复页面,谷歌选择的规范网址指向了一个你完全不认识的域名。 这时候大多数人的第一反应是内容被抄了。查了一圈发现没人抄,然后就卡在这儿了。 2026年7月,谷歌搜索团队的John Mueller在一期播客里给了这个现象一个解释,原话大意是:那些用来阻止坏流量的人机验证检查,有时候会导致页面从谷歌里掉出去。这段表态的完整报道 (https://www.searchenginejournal.com/are-you-a-bot-screens-can-get-your-pages-dropped-by-google/582801/)不长,但顺着它往下推,能扯出一整条大多数人从来没检查过的链路。 ## 一块人机验证屏,怎么就把页面弄掉了? 整条链路分三段,每一段单看都很正常,合起来就出事了。 第一段,触发。你的站前面挂着某种防护——可能是CDN的机器人管理、可能是主机商默认开的安全策略、也可能是专门的Bot防护服务。当它判定某个访客可疑时,不返回真实内容,而是先弹一张验证页:勾选框、滑块、或者那句熟悉的正在验证您是否是真人。 第二段,抓取。如果被判定可疑的那位访客恰好是Googlebot,它拿到的就是这张验证页。而关键在于,这张页通常返回的是200状态码——在谷歌看来,这个网址访问成功,内容就是这些。它没有任何理由怀疑这不是你的真实页面。 第三段,归并。谷歌把这张验证页当成该网址的正文收进了索引。问题是,同款防护产品的验证页在全网长得一模一样,成千上万个站共用同一套模板、同一段文案、同一个图标。谷歌的重复内容处理机制一看,这一大堆网址内容几乎完全相同,于是启动归并,从中挑一个当规范版本。 Mueller的说法是,谷歌可能会选中另一个网站的页面作为主要版本,你的页面则被标记成重复。 读到这儿你大概能感觉到荒谬在哪:你的页面不是因为内容差被降下去的,是因为它在谷歌眼里已经不再是你的内容了。它变成了那个验证页模板的第一万零一个副本,而模板的归属权,跟你没关系。 ## 为什么规范网址会跑到别人家的站上去? 这一步最反直觉,值得单独说清楚,因为它牵涉到跨站归并的判定逻辑。 很多人以为规范标签是自己说了算的:我在页面上写了自指的canonical,谷歌就该听我的。实际上按谷歌关于合并重复网址的官方说明 (https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls),canonical一直只是个建议信号,谷歌会综合十几个因素自己做选择,页面内容的相似度是其中权重很高的一个。 正常情况下,你的页面内容独一无二,相似度这条根本不会触发,所以自指的canonical一说就准。可一旦你的网址返回的是通用验证页,情况就反过来了——内容相似度直接拉满,而且不是和你自己站内某个页面相似,是和全网无数个陌生域名的页面相似。 归并机制这时候要挑一个代表。它会看哪些信号?站点整体权重、这个网址被抓取的历史、内部外部链接、页面加载稳定性等等。一个临时被判可疑、返回了通用模板的网址,在这场评比里几乎必输。于是代表权落到别人手上,你的页面被归入副本,在搜索结果里自然就没位置了。 关于谷歌到底怎么在一堆相似网址里挑代表,我在谷歌选择规范网址的决策逻辑 (https://zhangwenbao.com/google-canonical-url-selection-logic.html)那篇里按信号权重排过序,这次这个场景算是那套逻辑的一个极端案例:不是你的两个页面在内耗,是你的页面被整个互联网的模板池吞了。 ## 验证屏返回什么状态码,后果差多少? 这是源头报道里没细讲、但实操上最要紧的一环。同样是弹验证屏,返回什么状态码,结果天差地别。 验证页返回的状态码 | 谷歌的理解 | 实际后果 | 200 | 网址正常,内容就是这张验证页 | 最坏。验证页被索引,触发跨站重复归并,规范权可能旁落 | 403 | 禁止访问 | 较坏。谷歌会认为该网址不可用,长期返回会导致移出索引,但至少不会被当成内容 | 429 | 请求过于频繁 | 可接受。谷歌会降低抓取频率并稍后重试,属于它能理解的信号 | 503 | 服务暂时不可用 | 最安全。谷歌明确表示会保留原有索引状态并择期重来,短期内不影响排名 | 结论很直接:如果你的防护层非拦不可,那也请让它返回503而不是200。一个字节的差别,一边是暂时看不了、我待会儿再来,一边是这个页面的内容就是这一段、我记下了。 不过这条改起来往往不在你手上。多数商业防护产品的验证页是产品自带的,状态码由厂商决定,控制台里未必给你开这个开关。真遇到这种情况,先去翻厂商文档里关于搜索引擎爬虫的那一节——主流产品基本都有已验证机器人这类放行机制 (https://developers.cloudflare.com/bots/concepts/bot/verified-bots/),把Googlebot从验证流程里整个摘出去,比纠结状态码更省事,也更彻底。 ## 这两年为什么突然多了起来? 这个坑其实一直都在,但我明显感觉到,最近一年多问到它的人变多了。原因不难猜,是三股力量撞在了一起。 一是AI爬虫来势太猛。各家模型公司的抓取量在过去两年翻了好几番,很多站主是先在带宽账单上感受到的,然后才反应过来该拦。慌乱之下装上的防护,配置往往是默认的、粗放的。 二是防护产品本身在变智能。早年的规则是明确的:这个地址段拦、这个标识拦。现在流行的是行为评分,系统给每次访问打个可疑分,超过阈值就弹验证。好处是能拦住伪装得很像人的爬虫,坏处是判定过程变成了黑箱——你没法预先知道Googlebot会不会在某次突发抓取里被评成高分。 三是这类功能越来越多地默认开启。主机套餐送、CDN默认开、建站平台预置,装的人经常不知道自己装了。等出问题去查,第一反应是我们没装什么防护啊。 三股力量叠在一起,结果就是:被误伤的概率在涨,而发现误伤的能力没跟上。多数站到今天都没有任何一条监控是盯着Googlebot拿到了什么响应的,这块完全是盲区。 ## 除了Googlebot,还有谁也在被你拦着? 既然验证屏是按可疑分发的,它就不会只拦一种爬虫。这一节值得单列,因为损失是叠加的,而且另外几笔更隐蔽。 必应的爬虫。被拦的后果和谷歌一样,只是很多人不看必应的数据所以察觉更晚。要注意的是,一部分AI产品的检索能力是建在必应索引之上的,拦掉它等于同时断了好几条引用链路。 各家AI模型的抓取爬虫。这里得分清两件事:有的爬虫是拿去训练模型的,有的是用户提问当下实时去取页面用来生成答案的。前者你想拦有你的道理,后者拦掉就意味着AI在回答涉及你品牌的问题时,取不到你官网这份最权威的说法,只能去引用别人转述你的版本。这笔损失不会出现在任何一张流量报表里,因为它损失的是没发生的引用。 社交平台的预览抓取。这类抓取负责生成分享卡片的标题、描述和缩略图。被拦的表现是链接发到社交平台上只剩一条光秃秃的网址,点击率立刻掉一截。这个症状很好认,但几乎没人会把它和防护配置联系起来。 所以做放行清单的时候,别只写Googlebot一条就收工。该放行的是一个清单,不是一个名字,而且这份清单需要每半年过一遍——新的爬虫在出现,老的标识也在改。 ## 你自己访问一切正常,为什么还是中招了? 这件事最阴的地方在于隐蔽性。验证屏只对被判可疑的访客触发,而你——站长本人,从办公室固定IP、用常用浏览器、带着一堆历史cookie——几乎永远不会被判可疑。 你去点自己的页面,一切正常。你让同事点,也正常。你甚至让客户点,还是正常。所有人都看到内容,只有谷歌看到验证屏。 要发现它,得换个身份去测。几种由浅入深的办法: 第一,用搜索控制台的网址检查工具做实时抓取。这是最准的一招,因为它是真的以Googlebot的身份去取一次。抓完看渲染后的HTML,如果里面出现验证相关的文案或者防护厂商的脚本,实锤了。这一步不花钱,两分钟。 第二,看网址检查里谷歌选择的规范网址那一栏。如果它指向的不是你自己的地址,尤其指向了一个陌生域名,别犹豫,直接按本文的链路排查。 第三,改User-Agent加境外节点访问。把浏览器UA改成Googlebot的标识,再走一个美国的出口访问自己的站。注意这一招有假阴性——正经的防护产品不会只看UA,还会反查IP是不是真属于谷歌,你伪造的UA加上一个普通数据中心IP,触发的可能是另一套规则。测出问题算数,测不出问题不能算安全。 第四,翻服务器日志。把Googlebot的访问记录按状态码分组,统计200之外的比例。这一招最实在,也最容易被忽略——大部分站长从来没看过自己站上Googlebot到底拿到了什么响应。如果日志显示Googlebot有相当比例的请求拿到的不是200,问题不在猜测阶段了。 系统性做这件事,其实就是把爬虫看到的和用户看到的摆在一起对比。渲染对比这套方法 (https://zhangwenbao.com/render-compare-bot-user-cloaking-detection-guide.html)本来是用来查伪装问题的,拿来查防护误伤一样趁手,两者症状不同但排查动作高度重合。 ## 这和已索引但无内容是同一个毛病吗? 不是,但它们是亲戚,而且经常被混为一谈。 Mueller之前讨论过另一个场景:网站的安全设置悄悄屏蔽了Googlebot,却照常放行普通访客,结果谷歌加载到的是一张空白页。那个问题的表现是已编入索引但无内容。 两者的区别在这儿: 对比项 | 被喂空白页 | 被喂人机验证屏 | 谷歌拿到的内容 | 基本为空 | 一整页通用验证文案 | 典型报告状态 | 已索引但无内容 | 重复页面,规范网址不同 | 是否触发跨站归并 | 否,空页面不构成模板重复 | 是,这正是最麻烦的部分 | 排名表现 | 排名逐步流失 | 可能突然整批消失 | 修复后恢复速度 | 较快,重新抓到内容即可 | 较慢,需要等归并关系被重新评估 | 为什么第二种恢复更慢?因为你要撤销的不只是一次错误抓取,还有一个已经建立的跨站归并关系。谷歌得重新抓、重新比对、重新判定这个网址不再是那个模板的副本,然后才轮到重新评估排名。这中间的每一步都有自己的排队时间。 顺便一提,搜索控制台里那些看着差不多的状态描述,背后的处理路径其实差别很大。索引覆盖状态的机制拆解 (https://zhangwenbao.com/gsc-index-coverage-states-discovered-crawled-canonical-mechanism.html)那篇把常见状态对应的决策路径都过了一遍,遇到看不懂的状态先对照那份再动手,能省掉不少乱试。 ## 怎么区分是防护误伤,还是内容本身出了问题? 掉收录的原因有很多种,防护误伤只是其中之一。开工之前先做个鉴别,能避免把时间花在错误的方向上。 这几个特征放在一起看,指向性相当明确: 观察点 | 更像防护误伤 | 更像内容或算法问题 | 发生节奏 | 某个日期前后突然成批消失 | 数周内逐步下滑 | 受影响范围 | 不分页面类型,产品页博客页一起掉 | 集中在某类页面或某个主题簇 | 报告里的状态 | 重复页面、规范网址指向别处 | 已抓取未编入索引、内容质量相关状态 | 实时抓取结果 | 渲染出验证文案或防护脚本 | 渲染正常,就是不给排名 | 时间线关联 | 能对上一次运维或平台变更 | 能对上一次算法更新的时间窗 | 日志表现 | Googlebot非200占比跳升 | 抓取量正常,只是排名掉了 | 六条里对上四条以上,基本可以定方向了。其中最有分量的是第二条和第四条:算法问题几乎不会不分青红皂白把各种类型的页面一起端掉,而实时抓取渲染出验证文案这件事,没有第二种解释。 反过来提醒一句,这两类问题是可以同时存在的。修好了防护误伤,页面回来了,排名却没回到原位,那大概率是底下还压着一个内容层的老问题——只是之前被更严重的技术故障盖住了。这种情况别急着推翻结论,先把两件事分开记账。 ## 排查该按什么顺序做,先花钱还是先花时间? 按成本从低到高排,每一步都可能直接终结排查,所以别跳步。 第一步,看页面索引报告的分布。重点看重复页面且谷歌选择了不同规范网址这一类的数量趋势,各状态的准确含义可以对照页面索引报告的官方状态说明 (https://support.google.com/webmasters/answer/7440203)。如果它在某个日期附近突然抬头,把那个日期记下来——那多半就是防护策略变更的日子。零成本。 第二步,抽三个受影响的网址做实时抓取。看渲染HTML里有没有验证相关内容,看谷歌选定的规范网址指向哪儿。零成本,五分钟出结论。 第三步,对齐时间线。拿第一步记下的日期,去问运维那几天动过什么:换了CDN、开了新的防护规则、调了速率限制、升级了主机套餐送的安全模块。这一步经常能一步到位,因为这类变更几乎总有人记得。 第四步,翻日志验证。确认Googlebot的响应码分布在那个日期前后是否发生变化。这一步是给前三步的结论盖章用的,也是你去找厂商时唯一有说服力的证据。 第五步,联系防护服务商或主机商。带着日志去谈,要求把已验证的搜索引擎爬虫从验证流程里排除。这一步最花时间,尤其是遇上那种客服只会让你重启一下的厂商。 顺序的意义在于:前四步不花钱、不求人、不需要审批,通常能覆盖八成以上的情况。很多团队反过来做,先给厂商开工单,然后等三天,等回复的时候什么都没查——纯属浪费。 ## 哪几种常见配置最容易误伤Googlebot? 见得比较多的有三类,都不是什么奇葩配置,恰恰是最常见的那几种。 速率限制。谷歌抓取从来不是匀速的,遇到你大批量更新内容或者提交了新的站点地图,它可能在短时间内密集请求。如果你的限速阈值按普通用户的节奏设定,这种突发会被直接判成攻击。这也是为什么问题常常出现在网站大改版之后——改版本身没错,是改版触发了抓取高峰,抓取高峰撞上了限速墙。 地理封锁。不少做单一市场的站会把非目标国家的流量直接拦掉,理由是那些流量反正也不转化。但谷歌的抓取有相当一部分来自美国的地址,你要是做的是欧洲或者中东市场,顺手把美国段封了,等于把Googlebot关在门外。 AI爬虫规则误伤。这两年很多站在拦AI爬虫,用的规则常常是一条粗放的正则,匹配UA里带bot的一律拦。写得宽一点,Googlebot自己就撞进去了。防火墙到底拦不拦得住AI爬虫 (https://zhangwenbao.com/waf-bot-management-search-ai-crawler-misblock-diagnosis.html)那篇讲过这类规则的边界,核心就一句:按UA拦是最粗糙的做法,能反查地址就一定要反查。 去年有个做宠物用品的客户就栽在第三类上。他们换了新的防护服务,套餐里默认开了一个所谓的智能机器人防护,运维觉得默认配置总不会有错,就没细看。两周后开始掉收录,查了半个月,最后是在日志里看到Googlebot大面积拿到验证页才定位到。修复本身只花了十分钟——在厂商控制台里把已验证搜索引擎爬虫加进放行名单,一个开关的事。 这事最值得记的不是怎么修,而是那两周里团队做的所有猜测——内容质量、外链、算法更新、竞品打压——没有一条沾边。技术层出问题的时候,内容层的所有解释都会显得合理,这是最大的陷阱。 ## 修好之后,谷歌多久能把页面收回去? 先给个心理预期:比你希望的慢。 修复之后要发生的事有三件,依次排队。第一,谷歌重新抓到这个网址并拿到真实内容;第二,它重新评估这个网址和那个模板池的关系,撤销原来的归并判定;第三,重新评估排名。 第二步是大头。谷歌自己说过,规范网址的重新评估最长可能需要两周左右,这还是在抓取顺畅的前提下。也就是说,就算你今天修好、明天就被抓到,页面回到搜索结果里也可能是两周之后的事。这段时间最难熬的不是等待本身,而是老板每天问一句好了没有。 能加速的动作有限,但也不是没有: - 在搜索控制台的页面索引报告里点验证修复,这会让谷歌把这批网址排进优先重爬队列 - 对最重要的那几个网址,单独用网址检查工具请求编入索引 - 确保站点地图里这些网址的最后修改时间是新的,别让谷歌觉得没必要来 - 修复期间别再叠加别的大动作,改版、改结构、批量调整标题都往后放,免得几件事混在一起没法归因 最后一条最容易被违反。人在焦虑的时候特别想多做点什么,结果就是同时改五件事,两周后无论好坏都不知道是哪件起的作用。 ## 让它以后不再发生,其实只要盯住三件事 治标是把爬虫放行,治本是让这类问题在发生的当天就被发现,而不是两周后靠掉收录才暴露。 成本最低的一套监控,大概是这样三件事: 把Googlebot的响应码分布做成日报。不需要什么高级工具,日志按天分组,统计Googlebot请求里非200的占比,超过某个阈值就报警。这个指标平时几乎是条直线,一旦有防护规则变更,它会在当天就跳起来。这是全套办法里性价比最高的一条。 把防护规则变更纳入发布流程。很多团队的上线流程里有代码评审、有测试环境,唯独安全策略是运维在控制台里点两下就生效,没人知会。至少让这类变更走一遍通知,出问题时时间线能立刻对上。 每月做一次爬虫视角抽检。挑十个重要页面,用网址检查工具实时抓一遍,确认拿到的是真实内容、规范网址指向自己。十分钟的事,挂在月度例行清单里。 做完这三样,这类事故的发现时间基本能从两周压缩到一天。技术SEO里真正值钱的从来不是修复能力,是发现时间——同样的问题,当天发现是件小事,两周后发现就成了要复盘的事故。 ## 那到底还该不该收紧防护? 看到这儿可能有人会想:那我干脆把防护全关了? 千万别。恶意抓取、撞库、刷接口这些威胁是真实存在的,而且这两年只多不少。防护该开还得开,问题从来不在开不开,而在拦的时候有没有把该放的放掉。 可以拿来自查的判断,就三条: 第一,防护层认不认得已验证的搜索引擎爬虫?正经产品都有这个概念,也都提供白名单开关,就看有没有人去打开。这是必答题。 第二,被拦时返回的是不是503?不能白名单的场景下,至少让状态码说人话。这是加分题。 第三,有没有人在看Googlebot的响应码?没有的话,前两条配得再好,下次策略一变照样重来一遍。这是保命题。 至于AI爬虫要不要拦、拦到什么程度,那是另一个话题,涉及内容授权、引用可见度和带宽成本的权衡,跟本文说的误伤不是一回事。只有一点要提醒:不管你在这个问题上持什么立场,写规则的时候都别用一条粗放的正则去糊。真要拦,就按具体标识精确拦,并且逐条验证放行清单里的爬虫还能不能正常拿到内容。图省事写出来的规则,最后省下的时间总会以掉收录的形式还回去。 ## 改版或大促之前,怎么先把这条链路验一遍? 前面说的都是出事之后怎么办。但这类问题有个特点:它几乎总是伴随某次变更出现的,而变更是可以预知的。既然能预知,就该在变更前后各验一次,而不是等掉收录。 风险最高的几个时间点,基本就是这几类:网站改版上线、更换或新增CDN、更换主机或升级套餐、启用新的安全模块、大促前临时调高防护等级、以及批量发布内容之后。 最后一类最容易被漏掉。批量发内容意味着大批新网址进入抓取队列,谷歌会在短时间内密集来取,而这正是触发速率限制的经典场景。你精心准备的一批新内容,可能刚上线就撞在了自家的限速墙上,这事想想还挺讽刺的。 变更前后各跑一遍的清单,五条就够: - 用网址检查工具对三个不同类型的页面各做一次实时抓取,确认拿到的是真实内容 - 确认谷歌选定的规范网址仍然指向自己 - 在防护控制台里确认已验证爬虫放行开关的状态没被重置——换套餐和升级模块之后被重置回默认值是常事 - 变更后连续三天看一眼日志里Googlebot的非200占比 - 把这次变更的日期记进一个共用文档,出事时省掉一半排查时间 整套跑下来十几分钟,但它把发现窗口从两周压到了三天以内。对靠自然流量吃饭的站来说,这十几分钟的回报率高得离谱。 还有个细节值得单说:速率限制的阈值不该按人的节奏设。真人访问是有间隔的,爬虫不是,它可能一秒内发几十个请求,而这完全是正常行为。如果你的限速规则是按普通用户体验设计的,那它迟早会把爬虫判成攻击。合理的做法是给已验证爬虫单独一套宽松得多的阈值,或者干脆让它们走在限速逻辑之外。 ## 已经被索引的那些验证页,要不要主动清掉? 这是修复过程中最容易做错动作的一步,我见过好几个团队在这儿走了弯路。 常见的错误做法是:发现验证页被索引了,赶紧给验证页加noindex,或者在robots文件里把验证路径屏蔽掉。听起来很合理,实际上两条都会帮倒忙。 先说noindex。问题在于验证页并不是一个独立的网址,它是你原本那个正常网址在特定条件下返回的内容。给它加noindex,等于告诉谷歌你的产品页别索引了。等防护误伤解除、页面恢复正常,那条noindex还挂在那儿——你会得到一个更难查的新问题。 再说robots屏蔽。屏蔽路径的后果是谷歌连抓都不抓了,那它永远不会知道这个网址已经恢复正常。屏蔽掉的不是问题,是发现问题已经解决的机会。 正确顺序其实很朴素,一句话:先修根因,再谈清理。 - 第一,把爬虫放行配好,确认实时抓取拿到的是真实内容 - 第二,在页面索引报告里点验证修复,让谷歌重新走一遍 - 第三,对核心页面单独请求编入索引,插个队 - 第四,什么都别加。不加noindex,不改robots,不动canonical 第四条最重要也最反直觉。这类问题的本质是谷歌拿到了错误的内容,那么解决办法就只有一个——让它拿到正确的内容。任何试图通过增加指令去纠正结果的动作,都是在给一个本来会自愈的系统加约束,而这些约束往往留得比问题本身还久。 我见过最离谱的一个案例,是团队为了处理这类掉收录,前后加了自定义canonical、加了noindex、又加了robots规则,三个月后根因早修好了,页面还是回不来。最后花了两周时间把这三层补丁一层层扒掉,页面才慢慢回来。补丁本身成了新的病灶,这在技术SEO里太常见了。 ## 常见问题解答 ## 我的页面被判成重复,规范网址指向了陌生域名,一定是人机验证屏导致的吗? 不一定,但这是最值得先排除的一种。其他可能性包括内容被大规模采集、你自己的内容联合发布没设好归属、或者页面本身内容极薄导致和通用模板相似。区分方法很简单:用网址检查做一次实时抓取,看谷歌拿到的HTML是不是验证页。是就实锤,不是就往别的方向查。 ## 把Googlebot加白名单,会不会被别人伪造UA混进来? 正确做法不会。合格的白名单机制不只看User-Agent,还会对访问地址做反向查询,确认它确实属于谷歌的网段。只按UA放行才有伪造风险,那种配置本来就不该用。主流防护产品的已验证爬虫功能默认就是带反查的。 ## 我用的是共享主机,防护策略不归我管,怎么办? 先拿日志和网址检查的截图去开工单,说明搜索引擎爬虫正在被拦,要求加白。多数主机商有这个能力,只是不主动做。如果对方推诿又不肯提供爬虫白名单,那这件事已经超出SEO范畴了——一个不让搜索引擎正常抓取的主机,本身就不适合放一个靠自然流量吃饭的站。 ## 验证屏返回503就真的完全没事吗? 短期没事,长期不行。谷歌把503理解为暂时不可用,会保留索引状态并稍后重试,但如果一个网址持续数周都返回503,它最终还是会认为这个页面没了并移出索引。503是缓冲垫,不是免死金牌,该修的规则还是得修。 ## 我怎么知道自己的站有没有这个问题,有没有五分钟能跑完的自查? 有。第一步打开搜索控制台的页面索引报告,看有没有重复页面且谷歌选择了不同规范网址这一类,数量多不多、最近有没有突然增长。第二步随便挑一个受影响的网址做实时抓取,看渲染结果。两步之内就能得出结论,不用等任何人配合。 ## 掉出去的页面自己会回来吗,还是必须做点什么? 只要根因修好,多数情况会自己回来,因为谷歌本来就会定期重抓。但被动等会慢很多。主动点验证修复、对核心页面单独请求编入索引,能把恢复时间明显压短。要提醒的是,恢复期间排名可能不会一次性回到原位,需要一段爬坡时间,这属于正常现象,别急着又去动别的东西。 ## 只有一部分页面掉了,其他页面好好的,也可能是这个原因吗? 可能,而且很常见。防护判定是按单次访问打分的,不是按站点整体开关的,所以完全可能只有某几次抓取被拦。此外抓取频率高的页面撞上验证屏的概率天然更大,表现出来就是重要页面先掉、边缘页面反而没事,看着像是谷歌专门针对你的核心页,其实只是概率问题。 ## 做了这一套排查还是没找到原因,下一步该往哪儿查? 先确认实时抓取拿到的内容真的没问题,这是分水岭。如果抓取内容完全正常、规范网址也指向自己,那基本可以把防护误伤这条线排除掉,接下来该往内容重复、页面质量、站点结构或者算法更新的方向查。别在已经排除的方向上反复回头,那是排查最消耗士气的一种走法。 ## 用第三方的加速或安全服务,有没有办法提前知道它会不会拦爬虫? 有个省事的判断:翻它的文档,看有没有已验证爬虫或者搜索引擎白名单这类章节,以及这个开关是不是默认打开的。有明确文档、默认放行的,风险低;文档里只字不提、全靠行为评分的,上线前一定要自己实测一遍再放量。选型阶段花十分钟翻文档,比上线后花两周排查划算得多。 ## 权威参考资料 ## robots.txt挡不住AI训练:Google被诉案摊开了内容进模型的4条路 - URL:https://zhangwenbao.com/ai-training-data-four-paths-robots-txt-limits.html - 分类:技术SEO - 发布:2026-07-20 | 更新:2026-07-20 - 摘要:从图书馆扫描、平台交付、第三方数据集到自家抓取,4条进料路径各自归谁管;官方定义里那两个限定词把管辖范围划在哪;以及一个乐器教学站在日志里翻出的、跟浏览量排名完全对不上的内容清单。 - 关键词:robots.txt,爬虫,Common Crawl > **TLDR**:摘要:2026年7月10日,三家出版社加一位小说家在纽约南区联邦地区法院把Google告了,指控它拿受版权保护的书训练Gemini。这份起诉书真正值得做内容的人读一遍的地方,不是索赔金额,而是它把4项指控分开排列的方式——原告自己就把“从Google图书里复制”和“通过网页抓取复制”当成2条互不相干的侵权路径分别起诉。顺着这个结构往下看,你会发现内容进入一个大模型至少有4条路,而你的robots.txt只管得住其中一条。更尴尬的是,那条你管得住的路,恰恰是4条里分量最轻的。 > 摘要:2026年7月10日,三家出版社加一位小说家在纽约南区联邦地区法院把Google告了,指控它拿受版权保护的书训练Gemini。这份起诉书真正值得做内容的人读一遍的地方,不是索赔金额,而是它把4项指控分开排列的方式——原告自己就把“从Google图书里复制”和“通过网页抓取复制”当成2条互不相干的侵权路径分别起诉。顺着这个结构往下看,你会发现内容进入一个大模型至少有4条路,而你的robots.txt只管得住其中一条。更尴尬的是,那条你管得住的路,恰恰是4条里分量最轻的。 先说清楚一件事:这不是一篇法律分析。判决要等好几年,赔多少钱跟你我也没什么关系。 但这份起诉书有个别的用处。它是目前为止把“内容是怎么进到一个大模型里去的”讲得最完整的一份公开文件——因为原告为了把责任说清楚,必须一条一条把路径拆开。而这些路径,正好就是你每天在琢磨的那件事:我在网上放的东西,最后都去了哪。 ## 一份起诉书,凭什么值得做SEO的人读完? 大部分人看到这条新闻 (https://www.searchenginejournal.com/google-faces-class-action-over-books-used-to-train-gemini/582708/),抓住的是“Google被告了”。这个信息量约等于零。这些年被告的AI公司排起来能绕一圈。 真正有信息量的是起诉书封面那一页。这份文件在法院备案系统里能查到原件 (https://www.courtlistener.com/docket/73603888/hachette-book-group-inc-v-google-llc/),案号1:26-cv-05870,一共57页。我把封面原样抄下来: 指控 | 法条 | 指向的行为 | 第一项 | 17 U.S.C. §§ 106(1)、501 | 从Google图书及其他Google服务中复制未经授权的副本 | 第二项 | 17 U.S.C. §§ 106(1)、501 | 通过网页抓取复制 | 第三项 | 17 U.S.C. §§ 106(1)、501 | 在训练过程中复制 | 第四项 | DMCA,17 U.S.C. § 1202(b) | 删除或篡改版权管理信息 | 看出问题了吗。前3项引的是同一组法条,同样是“未经授权复制”,却被拆成了3条独立的指控。 律师不会平白无故把一件事写成3件。拆开,是因为这3次复制发生在完全不同的地方、通过完全不同的渠道、涉及完全不同的抗辩。原告必须分开告,才能保证其中一条被驳回时另外2条还站得住。 ## 为什么第一项和第二项分开列,是这份文件里最该被注意的细节? 第一项针对的是Google图书和其他Google服务。第二项针对的是网页抓取。 这个区分,把一件平时被混为一谈的事情摊开了:同样是“Google拿到了我的内容”,来路完全可以不一样,而不同的来路,适用完全不同的规则。 书是怎么到Google手里的?要么是图书馆里的实体书被搬去扫描,要么是出版社按合同上传的。这2条路上,从头到尾没有任何一个爬虫参与过。既然没有爬虫,robots.txt自然就无从谈起——你没法用一份写给抓取器看的文件,去约束一台平板扫描仪。 网页抓取那一项才是有爬虫的。可即便是这一项,后面你会看到,主力也不是Google自己的爬虫。 ## 内容进到一个大模型里,一共有几条路? 把起诉书里提到的渠道理一遍,至少4条。我按“你能不能管得到”从弱到强排: 路径 | 内容怎么进去的 | 你的robots.txt管不管得到 | 图书馆扫描 | 实体书被逐页数字化 | 完全管不到 | 平台交付 | 你按合同把文件传给平台 | 完全管不到 | 第三方数据集 | 别人抓走,Google再从别人那里拷贝 | 管不到Google,只能去管那个“别人” | 自家抓取 | Google的爬虫直接来你站上抓 | 管得到 | 4条路里只有最后一条归你的robots.txt管。而对这场官司来说,最后一条几乎不重要——书又不在网站上。 下面一条一条拆。 ## 第一条路:图书馆里的实体书,是怎么变成训练语料的? Google官方在Google图书的项目说明页 (https://books.google.com/intl/en/googlebooks/about/index.html)上写得很直白,书只有2个来源:合作伙伴计划和图书馆项目。 图书馆项目就是字面意思。Google跟大学图书馆合作,把书一本一本搬出来,一页一页扫成数字副本。这件事从2004年就开始做了,规模是千万册级别。 这条路上没有网络请求,没有User-Agent,没有IP段,没有日志。你在服务器上部署再严密的拦截规则,对一本躺在密歇根大学书库里的精装书没有任何作用。 这听起来像句废话,但它恰恰是这场官司的地基。原告要证明的正是:这批内容从来就不在“公开网络”这个语境里,所以任何“你都放到网上了还怪谁”的辩解,在这里根本用不上。 ## 第二条路:你主动交给平台的东西,授权边界划在哪? 起诉书点了3个Google服务的名:Google图书、Google Play图书、Google学术。 这3个的共同点很有意思——内容都是版权方主动、自愿、按合同交出去的。出版社把电子书传到Play图书,是为了卖书;把文章放进学术检索,是为了被引用。 起诉书里那句话说得很干净,我直译过来:作者和出版社把数字图书交给Google,目的仅限于销售获得授权的电子书,并未授权Google复制这些作品去训练或开发它的AI模型。 这就引出了整件事里最值得单独拎出来讲的一条原理。 ## Google学术为什么也被点名? 3个服务里,Google学术最容易被忽略,但它对做专业内容的人最有参考价值。 起诉书里的说法是:Google学术让用户检索学术文献,检索结果会把用户导向可以合法获取全文的地方。这个模式本身没问题,出版商也认。问题在下一句——起诉书写的是,Google学术里没有任何条款授权Google复制参与出版商的文章去训练或开发它的AI模型。 注意这个句式:不是“禁止”,是“没有任何条款授权”。 这两者的差别很重要。版权的默认状态是保留,不是开放。合同里没提到的用途,不需要被明令禁止才算越界,它本来就不在授权范围内。很多人把这个关系搞反了,以为“协议里没写不许,那就是可以”。 把这个逻辑放到你自己的处境里:你给某个平台供稿时签的协议,大概率也没有一个字提到AI训练——不是因为对方大方,而是因为签的时候这件事还不存在。这个空白对你是保护还是风险,取决于当地法律怎么填,以及你有没有能力把它谈成明文。 ## Google内部自己是怎么评估这件事的? 起诉书第60段里有几条内部材料的引述,这是整份文件里最有杀伤力的部分,因为它指向的是“明知故犯”。 第一条,Google内部把使用Play图书里“出版商提供的受版权保护图书”来做AI这件事,标注为对Google“高度有问题”,并警告可能面临“数百亿到上千亿美元的潜在罚款”。这个原文表述是$10Bs-$100Bs。 第二条,内部识别出的具体风险里,有一句几乎是预演了今天:图书出版商很可能会把在他们的书上做大模型训练视为侵权,可能撤回在Play图书上的内容并起诉Google。 第三条,内部分析列出的关键问题包括:部分合作方图书内容存在限制性许可;出版商对在他们的数据上训练很敏感;合理使用抗辩的风险升高。 这3条为什么重要?因为版权侵权分故意和非故意,法定赔偿的上限差好几倍。原告把这些内部材料放在这么靠前的位置,就是奔着“故意”去的。 对我们这些旁观者来说,还有一层更朴素的启发:连Google自己的法务都认为这件事风险极高,那些告诉你“反正大家都在抓,没关系”的说法,可以打个折扣听。 ## 授权是按用途给的,不是按副本给的 很多人对授权的理解停留在“我把文件给你了”这个动作上。给了就是给了,你拿去干什么是你的事。 版权法不这么看。你交出去的是一次有明确用途的许可,不是这份内容的所有权。用途换了,许可就得重新谈。 这个道理放到日常工作里也一样成立。你授权某个聚合平台转载你的文章,是为了拿曝光;它拿去喂自己的模型,那是另一件事。你给分销商产品图,是为了让它卖货;它拿去训练一个能生成同类产品图的工具,也是另一件事。 合同里没写的用途,默认不在许可范围内——这条原则比任何技术手段都更接近问题的本质。而绝大多数内容合作协议,压根就没写过AI训练这一条,因为签的时候还没这回事。 ## 2015年那个判决,为什么现在反过来成了原告的武器? Google图书当年也被告过,打了10年。2015年第二巡回上诉法院判Google赢,认定它扫描全书构成合理使用。 按常理,这应该是Google最硬的护身符。可这次原告主动把它写进了起诉书里,而且是当成弹药用的。 原因藏在判词的限定语里。起诉书引用的原话是:法院认定制作完整数字副本属于合理使用,但仅仅是因为Google制作这些副本的目的,是向公众提供搜索与片段浏览功能。 合理使用从来不是给一份副本发的通行证,而是给一个特定用途发的。判决书里那句“仅仅是因为”,把这张通行证的适用范围死死钉在了“搜索和看片段”上。 所以原告的逻辑链条是这样的:你手上这批副本合法,前提是你只拿它做检索。现在你拿它去训练一个会写小说的模型,用途变了,前提就没了,合法性得重新算。 这一招挺漂亮的。Google当年为了赢那场官司,必须把自己的用途说得越窄越好;10年后,那个被自己主动缩窄的说法,成了套在脖子上的绳子。 ## 第三条路:中间商Common Crawl,为什么最该让你警觉? 前面2条路离普通站长很远——你多半没有实体书要被扫描,也没往Play图书传过东西。 第三条路才是真正跟你有关的那条,而且它是4条里最反直觉的。 起诉书里给了一条完整的链路,数字都是原文里的:Google早期的对话模型LaMDA,训练用的语料集叫Infiniset,一共29.7亿份文档;其中大约3.71亿份,占12.5%,来自Google自己整理的C4数据集;而C4,是Google从公开的Common Crawl数据集里挑拣、复制出来的。 关键就在最后这一环。Common Crawl不是Google的。 它是一家独立的非营利机构,自己养着爬虫满世界抓网页,然后把抓来的东西免费公开。Google做的事情,是从这个公开池子里舀水。 ## 这条链路上,你的robots.txt是在哪一步失效的? 假设你在robots.txt里把Google相关的令牌全写了一遍,包括那个专门管训练用途的Google-Extended。你觉得自己拦住了。 但抓你网页的那个爬虫,叫CCBot,是Common Crawl的。它不看你写给Google的任何一条规则——那些规则的收件人不是它。 它抓完,内容进入Common Crawl的公开数据集。Google再从那个数据集里复制,这一步是数据集之间的拷贝,压根不产生任何指向你服务器的网络请求。 于是就出现了这么个局面:你的内容确实进了Google的训练语料,全程却没有任何一个Google的爬虫违反过你的robots.txt。每一步单看都合规,合起来把你的规则绕干净了。 这不是什么阴谋,就是分工的自然结果。但对你来说,后果是实打实的:你以为的那道门,装在了一条没人走的路上。 ## C4里那2亿个版权符号,说明了什么? 起诉书里有个数字我觉得特别有画面感:版权符号©在C4数据集里出现了超过2亿次。 这个数字本身不能证明侵权——网页页脚放个版权声明是标配,出现2亿次只能说明网页页脚很多。 但它能说明另一件事:这个数据集里的内容,绝大多数都自带“我是有主的”这个标记,而这个标记在被吸进去的过程中显然没起到任何作用。标记还在,约束力为零。 起诉书还点了几个具体来源:Z-Library、LibGen、Sci-Hub这些早就被判过侵权的盗版站,都在Common Crawl的抓取范围里;订阅制的在线图书馆Scribd.com,是C4里的第三大站点。 Scribd这个例子特别值得琢磨。它是合法平台,从版权方那里拿了正经授权,把内容提供给付费用户。可当一个爬虫从外面把它的内容抓走时,等于绕过了整个订阅模式——授权链条在合法的那一端是完整的,在被抓走的那一端断了。 ## 起诉书点名的那些盗版站,为什么值得单独看一眼? 这一段初看像是在骂人,其实藏着一个对普通站长很实际的机制。 起诉书点了名的有Z-Library、LibGen、Sci-Hub、OceanofPDF,还有一个叫WeLib的站,前身是PDF Drive。关于Z-Library,起诉书提到执法部门在相关刑事诉讼中查封了多达350个网站与域名。此外它还说,C4数据集里至少还包含27个被美国政府认定为盗版与假冒市场的站点。 重点不在于这些站有多坏,而在于它们是怎么进到训练语料里去的:它们是被Common Crawl当作普通网页一并抓走的。 Common Crawl的爬虫不做也做不了版权判断。它看到一个能访问的URL,就抓。至于这个页面上的内容是原创、是授权转载,还是彻头彻尾的盗版,对一个爬虫来说没有任何区别。 这件事对你的直接含义是:你的内容如果被盗版站转走过,那么就算你自己的站把所有爬虫都拦干净了,那个副本仍然会经由盗版站进入公开数据集。 换句话说,防抓取这件事有个天然的上限——你只能管住你自己那份。内容一旦被复制出去,副本的命运就不归你管了。这也是为什么“把内容藏起来”从来不是一个完整的策略;真正能持续起作用的,是让你那一份成为最权威、最新、最容易被验证的版本。 ## Common Crawl自己是怎么回应的? 起诉书里引了2句Common Crawl方面的公开表态。我原样翻译:“如果你不希望自己的内容出现在互联网上,你当初就不该把它放到互联网上。”还有一句更直接:“机器人也是人。” 这2句话值得单独看一眼,因为它把一个平时被默认的前提掀开了。 robots.txt能运转30年,靠的从来不是技术强制力——它就是个文本文件,没有任何东西能阻止一个爬虫无视它。它靠的是一种行业共识:大家都同意遵守,因为遵守对大家都有好处。 当一方公开说“我不认为你有资格提这个要求”的时候,共识这一层就已经不存在了。剩下的只有你自己在服务器上真正能执行的那部分。 ## 想拦住这条路,具体该写什么? 好消息是,Common Crawl至少把口子留得很清楚。它在CCBot的官方说明页 (https://commoncrawl.org/ccbot)上直接给了写法,令牌就是CCBot,用户代理字符串是CCBot/2.0。 写进robots.txt是这样: User-agent: CCBot Disallow: / 同一页上还提到2件配套的事:一是已经出现了伪装成CCBot的爬虫,所以只认User-Agent字符串是不够的;二是CCBot现在跑在专用IP段上并支持反向DNS验证,这给了你一个真正可靠的核对手段。 这个思路跟核对Googlebot真伪是一样的:User-Agent是自称,反向DNS才是身份证。关于用户触发型抓取器那一整类的验证细节,我在Google有一整类抓取器不看robots.txt (https://zhangwenbao.com/google-user-triggered-fetchers-robots-txt.html)里拆得更细,那篇讲的是同一套机制的另一半。 ## 拦掉Common Crawl,你会失去什么? 这一步别急着动手。Common Crawl不只喂AI训练,它是一大批学术研究、语言学项目、开源工具的基础数据来源;不少反链分析和网络图谱类的服务,底层数据也来自它。 更要紧的是,现在有相当一部分AI系统在回答问题时会去检索网络内容,而检索用的索引未必是自建的。把自己从公开数据集里彻底摘出去,有可能顺手把“被AI提到”的机会也摘掉了。 这就变成一个取舍题,而不是一道有标准答案的技术题: 你的内容属于哪类 | 倾向 | 理由 | 靠内容本身变现,比如付费专栏、教程、研报 | 倾向拦 | 内容被复制等于直接损失,曝光换不回来 | 靠内容获客,最终卖产品或服务 | 倾向不拦 | 被提到、被引用就是获客,拦掉是自断入口 | 做品牌资料、事实性说明 | 明确不拦 | 你反而希望模型学到的版本是准确的那个 | 第三行值得多说一句。如果模型对你的品牌说法有误,问题的根子往往不是被抓得太多,而是被抓到的那一版本身就旧了或者不一致。这种情况下把自己藏起来,只会让错误的那版活得更久。 ## 第四条路:Google自家的抓取器,也就是你唯一真管得住的那条 最后这条反而最简单,因为它是唯一一条“规则的收件人就是它本人”的路。 但这里有个技术细节,我把官方文档翻出来核了一遍,结果比我预期的有意思。 ## Google-Extended这个令牌,为什么在日志里永远看不到? Google在抓取器与提取器的官方文档 (https://developers.google.com/crawling/docs/crawlers-fetchers/google-common-crawlers)里,对Google-Extended有这么一句说明,我直译过来:Google-Extended没有独立的HTTP请求用户代理字符串,抓取是由现有的Google用户代理完成的,robots.txt里的这个令牌只起控制作用。 换句话说,Google-Extended根本不是一个爬虫。它是一个纯粹的开关。你在日志里翻一辈子也翻不到它,因为从来没有哪个请求是以它的名义发出的。 这一点很容易让人误判。有人在日志里搜不到Google-Extended,就以为自己的规则生效了、没人来抓;实际上抓取照常在进行,只是用的是别的名字,这个令牌管的是抓完之后那批数据能不能进训练集。 把它和上一篇讲的用户触发型抓取器摆在一起看,正好是一对镜像: | 有没有独立UA | robots.txt管不管得到 | 用户触发型抓取器 | 有,日志里能看见 | 一般不受约束 | Google-Extended | 没有,日志里看不见 | 是约束本身 | 一个看得见但管不着,一个管得着但看不见。指望靠翻日志就把这套体系摸清楚的人,大概率两头都会摸错。 ## 官方那句定义里的2个限定词,把管辖范围划到哪了? 同一份文档里还有一句,是这次核对下来最关键的一句。原文直译:Google-Extended是一个独立的产品令牌,网站发布者可以用它来管理Google从其网站上抓取的内容是否可以用于训练未来的Gemini模型。 2个限定词值得逐个看。 主体是“网站发布者”。客体是“Google从其网站上抓取的内容”。 把这2个限定词套回这场官司:那些书不是从任何网站上抓来的,是图书馆扫的、是出版社按合同交的。它们从定义上就不落在这个令牌的管辖范围里——不是Google不守规矩,是这条规矩从一开始就没写到那儿去。 所以那个流传很广的说法——“出版社当初把Google-Extended一屏蔽不就完了”——在机制上根本不成立。这个开关只能关掉网页抓取那一路,而这场官司的主战场是另外三路。 ## 时间线上还有一记补刀,很多人没算过这笔账 就算退一万步,假设Google-Extended真能管住网页抓取那一路,还有个时间问题绕不过去。 这个令牌是2023年9月底才发布的。而这场官司里被反复提到的C4数据集,是从更早的Common Crawl快照里整理出来的,用来训练LaMDA那一代模型。 也就是说,等到这个开关被造出来的时候,该进去的内容早就进去了。 这一点对所有做内容的人都成立,而且比法律细节更值得记住:退出机制永远是往后生效的,它不能把已经发生的事情撤回来。你今天在robots.txt里加的任何一行,管的都是明天的抓取;至于过去十几年里被抓走、被复制、被打包进各种数据集的那些副本,没有任何一个开关能追回。 所以把希望寄托在“找到正确的屏蔽写法”上,从一开始就搞错了时态。屏蔽是个止损动作,不是个撤销动作。 ## 第四项指控告的是删除版权信息,这对做内容的人意味着什么? 前3项都是复制,第四项换了个赛道,走的是DMCA的第1202(b)条,告的是删除或篡改版权管理信息。 版权管理信息这个词听着抽象,说白了就是那些标明“这东西是谁的”的元数据:作者名、版权声明、许可条款、标识符。 这一项为什么单独告?因为它的证明门槛跟复制不一样。复制那几项要跟合理使用抗辩正面打,胜负难料;而“你把我的署名信息抹了”是个相对干净的事实问题——抹没抹,比对一下就知道。 对内容从业者来说,这一项的启发比前3项更实际:你的内容上,到底有没有一个机器读得到、又不容易被顺手抹掉的归属标记? ## 你的页面上,有没有可被移除的归属信息? 大部分站点的答案是:有,但只有人看得见的那种。 页脚一行“版权所有”,文末一句“转载请注明出处”——这些是写给人看的。内容被提取成纯文本喂进模型的那一刻,这类信息跟正文混在一起,能不能留下全看运气。 能被机器稳定识别的归属信息是另一套东西:结构化数据里的作者与出版方字段、图片文件里的元数据、正文里被明确标注的引用来源。这些至少在格式上是可解析的,被移除时也留得下痕迹。 这条线索往前推一步,就接到了内容溯源那套东西上。关于可验证出处正在怎么变成一种新的信任凭据,我在内容溯源与C2PA (https://zhangwenbao.com/content-provenance-c2pa-trust-currency-geo.html)那篇里展开过。这场官司等于从法律那一侧,给同一件事补了个注脚:归属信息不只是礼貌问题,它可能是你唯一能拿出来的证据。 ## 为什么删除版权信息那一项,可能是4项里最难缠的? 把4项指控放在一起掂量,第四项的分量常被低估。原因在赔偿的算法上。 起诉书里明确写了一句:每一次移除或篡改版权管理信息,以及每一次分发或使用被移除、篡改了该信息的作品,都构成一次独立的违法。 “每一次算一次”这几个字,是个乘法器。前3项复制类指控要跟合理使用抗辩正面交锋,胜负难说;而这一项的争点更偏事实——信息在不在,被没被抹掉,比对一下就知道,抗辩空间小得多。 顺带说一句,用版权规则去撬动一个体量巨大的平台,这套路数并不新鲜。Google自己就在用同样的工具对付盗版站,我在Pirate更新是什么 (https://zhangwenbao.com/google-pirate-dmca-copyright-update-explained.html)里写过它怎么拿DMCA投诉量当降权信号。同一部法律,这次调转了枪口。 ## 这场官司的“集体”包括谁,跟你有关系吗? 这是一起拟制集体诉讼,意味着5位原告不只为自己打,还代表一批处境相同的权利人。 对绝大多数读到这里的人来说,答案很直接:你不在这个集体里。这个集体针对的是书籍与期刊文章的权利人,不是网站内容的作者。 但“不在集体里”不等于“跟你无关”。这场官司会给几个问题定调,而这些定调最终会渗到所有内容创作者身上:用途受限的授权能不能被单方面扩展?合理使用能不能覆盖训练?归属信息被抹掉算不算独立的伤害? 这3问,答案落在哪一边,决定的是未来几年内容分发协议怎么写。你现在还谈不上有筹码,但至少可以先把自己的合同翻出来看看。 ## 把这套框架搬到你自己的供稿协议上 这是整篇里迁移价值最高的一段,尤其是对做外贸和独立站的人。 出版商这次栽的跟头,说白了是:把内容交给了一个用途受限的渠道,却没在合同里写清楚AI训练这一条。而这个错误,你大概率也正在犯。 盘一遍你把内容交出去过的地方: - 给分销商和渠道商的产品图、说明书、参数表 - 上架第三方平台时提交的商品描述与详情页素材 - 投给行业媒体、目录站的稿件与企业资料 - 交给代运营或本地化服务商的全部文案 - 为参加展会、评奖、认证提交的技术文档 这些协议里,有几份写了对方能不能拿去训练模型?我猜是零。 该怎么补也不复杂,谈新合同或者续约时加一句用途限定就行——授权范围仅限于约定的展示与销售用途,不含用于训练或开发机器学习模型。对方接不接受是另一回事,但至少这个空白不该是你自己留的。 这里有个反直觉的地方值得点一下:你在自己网站上花力气配置的那些拦截规则,保护的是你控制权最强的那部分内容;而你真正没有控制权的那部分,恰恰是通过合同交出去的。结果就是大多数人把精力放在了防线最厚的地方。 ## 一张表:4条路径各自归谁管,你能做什么 把前面拆的东西收拢成一张表,这是这篇里最该被存下来的部分: 路径 | 入口 | 约束手段 | 你的动作 | 实体扫描 | 图书馆、纸质出版物 | 只有合同与诉讼 | 与出版方谈用途条款 | 平台交付 | 你签约上传的平台 | 合同条款 | 翻出旧合同看有没有AI训练条款 | 第三方数据集 | CCBot等独立爬虫 | 针对该爬虫的robots规则加服务器拦截 | 先决定要不要拦,再动手 | 自家抓取 | Google的爬虫 | robots.txt与Google-Extended | 确认令牌写对了,但别高估它的覆盖面 | 看这张表最该带走的一句话是:robots.txt只在第三、第四行有位置,而且第三行还得指名道姓写对是谁。 ## 保哥的客户案例:一个乐器教学站在日志里翻出了什么 去年下半年有个做乐器教学内容的出海独立站找过来,主要卖的是分级课程,站上还挂着大量免费的入门教程和曲谱解析。 他们的诉求原本很简单:怀疑内容被AI学走了,问能不能全拦掉。 我们先没动手,先把3个月的访问日志按用户代理分了个组。结果有2件事跟他们原来的判断不一样。 第一件,他们最担心的Google相关抓取,占比其实很平稳,跟往年比没有明显变化。真正涨得快的是几个第三方数据采集类的爬虫,其中就包括CCBot,而这一类在他们此前所有的拦截规则里一条都没被提到过——规则全是照着Google和几个知名AI公司的名字写的。 第二件更有意思。被抓得最集中的不是那些流量最高的入门教程,而是几篇讲乐理概念辨析的长文。那几篇在后台的浏览量排名一直很靠后,站长自己都快忘了。 这2件事凑在一起,结论就不是“拦不拦”了,而是他们真正的资产跟他们以为的资产不是同一批内容。浏览量高的是引流页,被反复抓走的那几篇才是不可替代的部分。 最后的处置也就跟着变了:免费入门内容照旧开放,那几篇核心辨析文章补齐了结构化的作者与出版方标注,付费课程正文本来就在登录墙后面,不用额外处理。CCBot那一条最后也没拦——他们靠内容获客,拦掉是自断入口。 得说清楚,这里面没有对照组,我也没法证明“如果当时全拦了会更差”。这只是一次把假设换成读数的过程,它值钱的地方在于把注意力挪对了地方,而不在于某个结论多正确。 ## 怎么判断自己的内容有没有进过公开数据集? 这个问题没法给出确定答案,但可以做几个成本很低的近似判断。 第一,查Common Crawl的公开索引。它提供按域名检索的接口,能查到你的站在历次抓取快照里被收录了哪些URL。查到不等于一定进了某个模型的训练集,但至少说明原料是齐的。 第二,直接问模型。挑几段你站上独有、别处不会有的表述——比如某个自造的说法、某组只有你测过的数据——去问几个主流模型,看它能不能补全或者复述。 第二种方法要特别小心解读。模型答得出来,不代表它训练时见过你的原文,也可能是它当场检索到的。反过来,答不出来也不代表没见过,训练语料里的东西不一定能被准确召回。这个测试只能提供弱信号,不能当证据用。 第三,看有没有被“共现”。比你的原文有没有被抓走更值得关心的,是你的品牌名和你所在品类的关键概念有没有被绑在一起。关于这个机制怎么运作,我在AI答案为什么不引用你 (https://zhangwenbao.com/ai-answer-cooccurrence-strategy.html)里展开过。从做生意的角度看,被记住比被抓走重要得多。 ## 付费墙被绕过这件事,反过来能给你什么启发? 起诉书里关于Scribd的那段,藏着一个可以直接拿来用的判断。 Scribd是合法的订阅制平台,从版权方拿了正经授权。可当爬虫从外面把内容抓走时,订阅这道门等于不存在——爬虫走的是公开可访问的那个入口。 这就把一件事说清楚了:付费墙能不能拦住抓取,取决于它是真墙还是假墙。 假墙是前端遮挡——内容其实已经随页面发给浏览器了,只是用样式盖住或者用脚本折叠起来,弹个框让你登录。这种做法对搜索引擎友好,对爬虫也一样友好,因为内容就在返回的HTML里躺着。 真墙是服务端判断——没有有效会话,服务器压根不把正文发出来。这种情况下爬虫拿到的就是一个空壳。 大量内容站用的是前一种,而且往往是有意为之,因为担心真墙会影响收录。这个取舍本身没有错,但你得知道自己选的是什么:选了假墙,就等于选了“对所有人可读,只对人类收费”。 顺带一提,这也是为什么前面那个乐器教学站不用为付费课程做额外处理——他们的课程正文是服务端鉴权的,本来就发不出去。 ## 中文内容的处境,会不会更好一点? 会好一点,但好得有限,而且好的原因不太让人高兴。 好的部分是:主流公开数据集里中文语料的占比一直不高,中文内容被卷进去的密度确实低于英文。 不高兴的部分是:这个“好”本质上是被边缘化的副产品,不是保护措施起了作用。而且随着各家把多语种能力当成竞争重点,这层稀薄的缓冲正在快速变薄。 还有个结构性差别值得注意。中文内容的分发高度依赖各类平台,而平台内容对外部爬虫往往是封闭的。这意味着中文创作者面临的主要风险,从来就不是“被外部爬虫抓走”,而是“被自己发布的那个平台按用户协议拿去用”。 后一种风险,robots.txt一个字都管不到——那是合同问题,跟这场官司里出版商栽的跟头是同一类。 ## 怎么在日志里把这几类请求分开看? 不用上工具,先按用户代理粗分成四组就够了:Google的常规抓取、Google的用户触发型抓取、第三方数据集爬虫、其他AI公司的具名爬虫。 分完之后看3个东西。一是各组的请求量占比,二是各组集中抓的路径前20名,三是有没有哪一组在最近3个月里增长特别快。 第二项通常最有价值。浏览量排名反映的是人对什么感兴趣,抓取集中度反映的是机器认为什么值得拿走。这2个榜单差得越远,说明你越需要重新看一遍自己的内容资产清单。 要注意的是,任何一组的请求量都不能直接当成“被学走了多少”。抓取次数跟最终有多少内容进了训练集之间,隔着去重、筛选、质量打分好几层,中间的损耗谁也不知道有多大。 ## 这件事上最容易犯的3个判断错误是什么? 第一个,把robots.txt当成有强制力的东西。它是一份君子协定,收件人愿意听才有用。真正有强制力的是服务器层的拦截和登录墙。 第二个,只按名字写规则。今天规则里写着几家AI公司的名字,明天换一批名字你就得重写一遍。这场官司里的关键路径是CCBot,一个绝大多数人的规则里压根没出现过的名字。 第三个,把“拦住”当成目标。拦住是手段,目标得是你想保住什么。上面那个乐器站的例子里,全拦的方案在动手前看起来最稳,实际上是把获客入口和核心资产一起关掉。 ## 出海独立站要不要按这个框架自查一遍? 要,但重点跟本土站不太一样。 出海站往往有大量内容散在别人的地盘上:分销商的商品页、行业目录、评测媒体、社媒平台。这些地方的内容你既没有服务器控制权,也没有robots.txt写入权。 换句话说,你能管的那一小块,在你全部内容里的占比,比本土站还要低。 所以自查的重点不该放在“我的robots.txt写全了没有”,而该放在2件事上:一是把散出去的内容清点一遍,看看关键事实的版本一致不一致;二是把跟平台、分销商签的旧合同翻出来,看看用途条款是怎么写的。 第二件事的价值可能超出预期。这场官司告的正是“超出约定用途使用”,而这个逻辑对你同样适用——你的分销商拿你的产品资料去做了什么,合同里多半也没写清楚。 ## 老板问“这事要不要紧”,该怎么答? 这种问题最怕2种答法:一种是“不要紧,跟我们没关系”,一种是“很严重,得赶紧全拦上”。前者会让你在半年后被翻旧账,后者会让你亲手关掉获客入口。 比较稳的答法是把它拆成3句。 第一句,这场官司告的是书和期刊,我们不在原告集体里,短期内没有直接的法律风险。 第二句,但它把一件跟我们有关的事说清楚了:内容进AI有4条路,我们的技术手段只覆盖得了其中一条,剩下3条靠的是合同。 第三句,所以我建议做的不是加拦截规则,而是花2个小时把我们对外供稿和上架的协议翻一遍,看看用途条款是怎么写的。 这3句的好处是,它把话题从“要不要拦”挪到了“我们的内容资产到底散在哪些地方、各自归谁管”。后面这个问题,不管这场官司怎么判都得回答。 ## 这件事有没有可能反过来是个机会? 有,而且机会不在技术那一侧。 如果这场官司最终确立了“训练需要单独授权”这条线,那么内容授权就会从一个没人谈的空白,变成一个有价格的东西。已经有平台开始给创作者提供训练授权的开关和分成方案了,虽然目前给的钱少得可怜。 真到那一天,能拿到钱的会是哪些人?大概率是3类:内容量足够大的、内容质量足够高的,以及权属足够清楚的。 前2类靠长期积累,急不来。第三类反而是现在花点力气就能补上的——把作者、出版方、许可条款这些字段在结构化数据里填好,把原创内容的首发时间和版本留痕。这些事今天做的收益是SEO层面的,将来如果授权真的能卖钱,它们又正好是证明权属的材料。 一件事今天有用、将来也有用,这种活值得优先做。至于那些只在某种特定判决结果下才有意义的准备,可以先放着。 ## 官司还没判,哪些结论现在就能用? 要分清楚哪些东西依赖判决结果,哪些不依赖。 依赖判决的:赔多少、合理使用这条抗辩在训练场景下站不站得住、以后行业得怎么改规矩。这些现在猜都是白猜,官司打完得好几年。 不依赖判决的,反而是更实用的那部分: - 内容进模型有4条路,robots.txt只覆盖其中一条半,这是机制问题,判决怎么判都不会变。 - Google-Extended没有独立UA、只对网页抓取生效,这是官方文档白纸黑字写的。 - CCBot是独立第三方,得单独写规则,这是Common Crawl自己公布的。 - 授权按用途走、合同没写的用途默认不在范围内,这是版权法的基本盘。 这4条今天就能拿去用,而且不会因为哪一方赢了而作废。 ## 如果只有10分钟,先做哪3件事? 第一件,打开自己的robots.txt看一眼,有没有CCBot这一条。有,说明你或者你的前任想得比大多数人细;没有,说明第三条路对你是完全敞开的。先别急着加,先看第二件。 第二件,问自己一句:我的内容是靠被看见赚钱,还是靠不被复制赚钱?答案决定了上一条该不该加,这个问题比任何技术细节都更该先想清楚。 第三件,随便挑三篇你最不希望被拿走的文章,看看它们的结构化数据里作者和出版方字段填了没有。大概率没填。这是10分钟里性价比最高的一件事,因为它既是SEO的基本功,又刚好是第四项指控指向的那种东西。 ## 半年后回头看,这篇里哪些会过期,哪些不会? 会过期的:官司进展、Google文档的具体措辞和地址、Common Crawl的表态、各家爬虫的名字和令牌。这些都是当期取值,随时会变,尤其是文档地址——Google这套抓取器文档最近才整体搬过一次家,旧地址还在返回301。 不会过期的:授权按用途划分、robots.txt管的是抓取动作而不是内容用途、你能约束的只有直接向你发起请求的那一方。这3条是结构,不是取值。 判断一条信息值不值得记住,用这个标准就够了:它依赖的是一个机制,还是一个当期数值?依赖机制的可以放进长期认知,依赖数值的每季度都得重新核一遍。 ## 常见问题解答 ## 在robots.txt里屏蔽Google-Extended,能阻止我的内容被用来训练AI吗? 只能阻止一部分。按Google官方文档的定义,这个令牌管的是“Google从你网站上抓取的内容”能否用于训练Gemini。它管不到通过第三方数据集流转的内容,也管不到你通过合同交给任何平台的内容。而且它没有独立的用户代理字符串,你在日志里是看不到它的。 ## CCBot到底是什么,为什么我的规则里从来没有它? CCBot是非营利机构Common Crawl的爬虫,它抓取的数据被整理成公开数据集,再被众多AI公司取用。绝大多数人的拦截规则是照着Google和几家知名AI公司的名字写的,而CCBot既不属于任何一家AI公司,名字也不出现在那些榜单上,所以经常被整个漏掉。 ## 那我到底该不该屏蔽CCBot? 取决于你的内容怎么变现。靠内容本身收费的,屏蔽的收益大于损失;靠内容获客最终卖产品服务的,屏蔽等于自断曝光入口。做品牌事实性资料的最好别屏蔽,否则模型里错误的旧版本会活得更久。这个问题没有通用答案,先想清楚要保住什么再动手。 ## 这场官司的4项指控,为什么前3项引的是同一组法条? 因为3次复制发生在不同环节:从Google图书等服务里复制、通过网页抓取复制、在训练过程中复制。渠道不同,涉及的抗辩理由也不同,分开起诉可以保证其中一条被驳回时另外2条仍然成立。这个拆分方式本身,就说明内容进入模型的路径不止一条。 ## 2015年Google图书那个判决,跟这次有什么关系? 那次判决认定Google扫描全书构成合理使用,但判词明确限定了理由是“为向公众提供搜索与片段浏览功能”。原告这次正是拿这个限定语当武器:合理使用是发给特定用途的,用途换成训练AI模型,原来的认定就不能自动延续。 ## 普通的独立站站长,需要为这件事做什么吗? 3件小事就够了:确认robots.txt里有没有CCBot这一条并想清楚要不要加;把最重要的几篇内容的结构化作者与出版方字段补齐;翻一遍跟平台和分销商签的旧合同,看用途条款怎么写的。前2件是技术活,第三件往往才是风险最大的那件。 ## 为什么说抓取次数不能当作被训练程度的衡量? 抓取只是第一步。从抓到的原始网页到最终进入训练集,中间还有去重、质量筛选、格式转换好几道工序,损耗率外界完全不掌握。用请求数去推断“被学走了多少”,分母和口径都是缺的,只能当作一个粗略的关注度信号。 ## 权威参考资料