首页的title、og:title和H1,说的常常不是同一件事

首页的title、og:title和H1,说的常常不是同一件事
张文保 44 分钟阅读 1,238 阅读
本文目录
  1. 一个首页到底有几个地方在自我介绍?
  2. 为什么是六个而不是三个
  3. 覆盖率从96.7%一路掉到42.5%
  4. 样本与口径先交代清楚
  5. 六个副本齐全的站有多少
  6. 这几个名字说的是同一件事吗?
  7. 社交那三个字段几乎是同一份
  8. 结构化数据里的名称是另一种关系
  9. 标题和H1那个72.3%
  10. 为什么H1和标题差得最远?
  11. H1变成了促销位
  12. 这47个站是不是都该改
  13. 还有一类更离谱的
  14. 那17个包含关系是怎么回事
  15. 这算问题吗
  16. 谁读哪一个字段?
  17. 这张表里有两条容易被忽略的分界
  18. 回退链是这张表里最实用的部分
  19. 最后一行是眼下最不确定的
  20. 搜索结果里的标题还可能被改写
  21. 缺席比不一致更常见,也更容易补
  22. 那些不一致的站,具体差在哪儿?
  23. 先说一个不该被当成问题的
  24. 三个名字各说各话
  25. 五个副本全不一样
  26. 一个转义引发的显示事故
  27. 把品牌名从名称字段里弄丢的那几个
  28. 一个反例:做对了的长什么样
  29. 中国站的三重身份
  30. 四个字段一起错的那种
  31. 换一个身份去抓,拿到的还是同一个页面吗?
  32. 四种身份,同一批地址
  33. 18个站从一开始就没进样本
  34. 六个西班牙品牌,一个都不给
  35. 先排除掉自己造成的差异
  36. 还有一个反过来的
  37. 为什么AI爬虫被拦得最多?
  38. 多出来的那几个是谁
  39. iittala那个最值得看
  40. 体积也是一种差异
  41. 拦截可能不是站点自己决定的
  42. 验证身份这件事本身也是双向的
  43. 被拦不完全是坏事
  44. 这件事的量级在变
  45. 名字不统一在AI这一层放大了
  46. 13个站消失,损失的到底是什么
  47. 同一份规则文件,对不同爬虫给出的答案一样吗?
  48. 5.2%的地址两套答案
  49. 这两个数字放在一起才有意义
  50. 2621条集中在哪几个站
  51. 为什么会出现"搜索引擎被禁而AI爬虫放行"
  52. 规则说允许,不等于真的给
  53. 六个副本该怎么收敛?
  54. 第一档:会让人看到错东西的
  55. 第二档:会稀释品牌表达的
  56. 第三档:写少了而不是写错了
  57. 分享卡片这一档有个专门的检查口
  58. 一条最省事的收敛路线
  59. 实体名称那一份单独拎出来定
  60. 验收标准写成一句话
  61. 先把这件事变成一次性的决定
  62. 怎么查自己站上的六个名字?
  63. 换个身份再抓一次
  64. 别只看状态码
  65. 结构化数据那一份要单独取
  66. 把六个字段拉成一张表
  67. 盯住那两个没有回退链的
  68. 把检查接进日常
  69. 一个更省事的做法:让页面自己报数
  70. 常见问题解答
  71. 标题和H1不一样,会影响排名吗?
  72. 六个字段里,哪个最不该省?
  73. 分享标题一定要和标题标签一样吗?
  74. H1被轮播横幅占了,怎么改最省事?
  75. 结构化数据里的名称该填什么?
  76. AI爬虫拿不到我的页面,我在AI答案里就消失了吗?
  77. H1可以有多个吗?
  78. 分享标题和标题不一致,会被判成作弊吗?
  79. 用什么身份做站点体检最靠谱?
  80. 标题写多长合适?六个字段要一样长吗?
  81. 为什么有些站的分享标题里有转义错误?
  82. 把六个字段全填成一样,算不算偷懒?
  83. 这些数据能代表中文站吗?
  84. 权威参考资料

摘要:一个首页最多有六个地方在自我介绍——标题标签、社交分享标题、推特卡片标题、页面H1、结构化数据里的名称、站点名称字段。153个品牌首页实测下来,标题与分享标题只有4.0%完全不同,而标题与H1完全不同的高达72.3%,五个副本一模一样的只有26个站。更麻烦的是读者本身:同一批地址换四种身份各抓一遍,浏览器拿到146个200,AI爬虫只拿到133个;六个西班牙品牌对搜索引擎和社交爬虫一律403,有个站给AI爬虫的是人机验证页。文中给出字段存在率、两两一致率、消费方取用顺序表与一套收敛办法。

8月中旬有条消息值得琢磨:OpenAI表示它那个按用户请求去取页面的抓取器,可能不适用站点根目录的规则文件。同一份文件,有的读者逐条遵守,有的读者认为它跟自己无关。

这件事换个角度看更有意思:不只是规则,连"你的页面叫什么名字"这种基本信息,不同的读者拿到的也可能不是同一个答案。

一个稍微完整的首页,自我介绍至少写了三遍,多的能写六遍:标题标签给搜索结果,社交分享标题给转发卡片,推特卡片标题给另一家平台,H1给页面本身,结构化数据里的名称给知识图谱,站点名称字段给面包屑。

它们本该说同一件事。但没有任何机制保证这一点,也没有任何工具会因为它们不一致而报错。

保哥拿171个海外品牌站的首页做了两件事:一是把这六个字段全部抽出来两两比对,二是换四种身份各抓一遍,看不同的读者拿到的是不是同一份页面。

一个首页到底有几个地方在自我介绍?

先数字段。样本是171个站,其中153个能拿到可解析的完整首页。

字段有这个字段的站覆盖率主要读者
标题标签14896.7%搜索引擎、浏览器标签栏
社交分享标题10166.0%Facebook、LinkedIn、Slack等
推特卡片标题7750.3%X平台
站点名称字段7448.4%搜索结果里的站点名
结构化数据里的名称7247.1%知识图谱、AI摘要
页面H16542.5%页面结构提取、辅助技术

为什么是六个而不是三个

十年前这件事简单得多:写好标题标签,顺手加个描述,完事。后来每出现一个新的分发渠道,就多一个字段。

社交分享标题是2010年前后随着一套开放协议进来的,为的是让转发出去的链接有个像样的卡片。推特卡片标题是另一家平台自己搞的一套,语义几乎一样,但字段名不同,于是又多一份。结构化数据里的名称是搜索引擎为了理解实体加的。站点名称字段是为了让搜索结果里显示品牌名而不是域名。

六个字段代表六次渠道扩张,每一次都在原有基础上加,没有一次是替换。这就是为什么它们从来没有被统一过——它们从来不是一批人在同一时间设计的。

可以预见的是,这个数字还会继续涨。给AI代理准备的清单、内容授权信号,这些新东西都在往同一个方向走:多一个读者,多一份声明。

覆盖率从96.7%一路掉到42.5%

标题标签几乎人人都写,往下每一层都在掉。到H1这一层只剩四成多。

掉的原因各不相同。社交分享标题缺席,多半是因为没人管转发场景;结构化数据缺席,是因为它需要额外的开发工作;H1缺席则完全是另一回事——现代电商首页的顶部是轮播横幅,标题在图片里,视觉上一点都不缺,只是语义标签没了。

样本与口径先交代清楚

171个站是从海外品牌站清单里取的,多数是直面消费者的电商站,技术栈以Shopify和几家企业级电商平台为主。抓取时间是同一天之内,四种身份分轮进行,每一轮跑完再换下一种,避免同一个站在短时间里被连续请求而触发限流——把限流当成身份差异,是这类实验最容易犯的错。

153这个可解析数是按"响应体超过2000字节且能解析出head"算的。剩下18个站要么被拦,要么返回的是几百字节的空壳。

字段抽取只看服务端返回的原始HTML,前端脚本运行之后补进去的不算。这会低估一部分站的字段覆盖率——有些框架把元信息放在客户端渲染阶段写入。不过这个口径恰恰贴近多数消费方的真实处境:社交平台的抓取器和大部分AI爬虫都不执行脚本。

H1的统计只在能完整取到body的文档上做,被截断的样本不参与。

六个副本齐全的站有多少

153个站里,六个字段全都写了的只有一小部分。更值得看的是另一个数字:把标题、分享标题、推特标题、H1、结构化数据名称这五个能取到的字段放在一起,取值完全相同的只有26个站。

26比153,不到两成。剩下八成的站,在不同的读者眼里叫着不同的名字。

这几个名字说的是同一件事吗?

把能同时取到的字段两两比对,分成三类:完全相同、一个包含另一个、完全不同。

比对的两个字段可比样本完全相同包含关系完全不同完全不同率
标题vs社交分享标题10090644.0%
社交分享标题vs推特标题7675011.3%
标题vs推特标题7669345.3%
标题vs结构化数据名称728521216.7%
标题vs H1651174772.3%

社交那三个字段几乎是同一份

标题和分享标题完全相同的有90个,社交分享标题和推特标题完全相同的有75个。这说明绝大多数站是用同一个变量输出了三遍——模板里写一次,三个字段一起填。

这个做法谈不上精细,但它保证了一致性。真正做过区分的站很少:4个站的标题和分享标题完全不同,其中有几个是有意为之——搜索结果要塞关键词,转发卡片要好读。

结构化数据里的名称是另一种关系

标题和结构化数据名称的比对结果很特别:完全相同只有8个,包含关系52个,完全不同12个。

52个包含关系里,绝大多数是结构化数据只写品牌名,标题写的是品牌名加一串描述。这是正确的用法——那个字段本来就该填实体的名称,不是页面的标题。所以这一列的16.7%完全不同,才是真正需要看的部分。

标题和H1那个72.3%

65个能同时取到标题和H1的站,只有1个两者完全一样,17个是包含关系,47个完全不同。

这个数字第一眼看着像质量问题,细看会发现它是产品形态决定的。下一节专门说。

为什么H1和标题差得最远?

把那47个完全不同的案例抽出来看,H1的内容有很强的规律。

H1变成了促销位

几个典型的例子:

cotopaxi.com的标题是品牌名加口号加免运费门槛,H1是"HOLIDAY GIFT WITH PURCHASE"——一句当期促销。

monos.com的标题是品牌名加品类加产地,H1是"Save with a set"——套装优惠。

mejuri.com的标题是品类加品牌,H1是"OUR SUSTAINABILITY PROGRESS"——可持续发展报告的入口。

columbia.com的标题是三个品类加品牌,H1是"STAY COOL & UV PROTECTED"——夏季主题。

这四个H1有个共同点:它们说的不是"这个页面是什么",而是"这一周我们想让你看什么"。H1的位置被轮播横幅占了,而横幅的内容每周都在换。

这47个站是不是都该改

不是。把47个案例摊开看,大致能分成三种。

第一种是H1填了当期促销,但页面主题在别处有明确表达——标题标签写清楚了、结构化数据也对。这种影响有限,属于可改可不改。

第二种是H1填了促销,而页面上再没有别的地方说清楚主题。这种要改,因为除了标题标签之外,机器和辅助技术都拿不到主题信息。

第三种是H1填了跟页面完全无关的东西——弹层标题、导航项、按钮文案。这种是实现问题,直接修。

三种的比例大致是第一种最多、第三种最少。所以72.3%这个数字不该直接读成"七成的站有问题",它更像一个需要人工分诊的清单。

还有一类更离谱的

otto.de的H1是"E-Mail-Adresse bestätigen & fertig!",翻成中文是"确认邮箱地址就完成了"。这是一个邮件订阅弹层里的标题,因为它在DOM里出现得比页面主标题早,就成了这个页面的第一个H1。

peakdesign.com的结构化数据名称写的是"Home - Bags + Camera Gear",把页面标题连着分隔符一起填进了实体名称字段。那个字段该填的是"Peak Design"。

那17个包含关系是怎么回事

除了完全不同的47个,还有17个站是包含关系——H1的内容是标题的一部分,或者反过来。

典型写法是标题写"品类关键词 | 品牌名",H1只写品牌名或者只写品类。这种是健康的:两者服务的场景不同,标题要在搜索结果里争眼球,H1要在页面上做主标题,重叠但不必相同。

只有1个站两者完全一样。完全一样也不算错,只是把两个字段当成了一个用,浪费了标题标签能塞关键词的那点空间。用像素级预览看一眼标题在搜索结果里的截断位置,通常能发现标题还有不少可用长度。

这算问题吗

分情况。

如果H1是促销横幅,搜索引擎那边影响有限——它主要看标题标签,H1只是众多信号之一。但辅助技术会把H1读给使用者听,AI摘要在提取页面主题时也会参考它。用户听到的第一句话是"套装优惠",跟他想知道的"这是个卖什么的站"完全不搭。

如果H1是弹层标题,那就是纯粹的实现问题,该修。

判断办法很简单:把H1的文字单独念出来,如果它没法回答"这是什么页面",那它就占错了位置。轮播横幅的文案应该是H2或者干脆用div加样式,把H1留给页面主题。

谁读哪一个字段?

不一致本身不构成危害,危害来自"不同的读者拿走了不同的那一份"。所以得先搞清楚谁读哪个。

读者优先取的字段取不到时回退到
搜索结果标题标题标签H1、正文里的显著文字,也可能自行改写
Facebook、LinkedIn分享卡片社交分享标题标题标签
X平台卡片推特卡片标题社交分享标题,再回退到标题标签
Slack、Discord等预览社交分享标题标题标签
知识图谱与富结果结构化数据里的名称不回退,缺了就没有
辅助技术的页面导览H1不回退
AI摘要与引用无统一口径,常见组合是标题加H1加结构化数据各家实现不同

这张表里有两条容易被忽略的分界

第一条:搜索结果里显示的站点名,取的不是标题标签,而是站点名称字段。这两个是分开的——很多站以为在标题里写了品牌名就够了,结果搜索结果里的站点名被引擎自己猜了一个。样本里48.4%的站写了这个字段,另一半交给引擎去推断。

第二条:H1没有回退链,结构化数据名称也没有。它们缺席就是缺席,不会有别的字段替补。这跟社交那几个字段完全不同——分享标题缺了,卡片上照样显示标题标签的内容,用户根本看不出你少写了一个字段。

有回退链的字段,缺席是隐形的;没有回退链的字段,缺席是真空。做体检的时候后者优先。

回退链是这张表里最实用的部分

Open Graph协议的定义里,分享标题是一个独立字段,协议本身不规定回退行为;回退是各家消费方自己实现的。X平台的文档写得比较明确:推特卡片标题缺席时用社交分享标题补,再缺席才用标题标签。

这条链子的实际意义是:你可以只写标题标签,让所有读者都回退到它——这比写三份互相打架的更安全。写多份的前提是你真的想让不同场景显示不同文案,而且愿意维护它们。

最后一行是眼下最不确定的

AI摘要读什么,没有一份公开文档给出确切答案。从可观察的行为看,它们通常会同时用到标题、H1和结构化数据,权重各家不同。这意味着一件事:过去只维护标题标签就够了,现在这个策略的覆盖面在变窄。

这也是结构化数据这几年重新变重要的原因。结构化数据对AI搜索到底有没有用那篇把官方说法和实测放在一起对过,结论是它不直接提排名,但它是少数几个能让机器无歧义地读到"这个实体叫什么"的地方。

再往深一层,schema堆满了但实体之间的关系没人审那篇讲的是下一个台阶:名称对上了只是第一步,实体和实体之间的关系完整不完整,才决定机器能不能把你放进它的知识结构里。

搜索结果里的标题还可能被改写

表格第一行有个附注值得单独说:Google不保证按你写的标题显示。它会在判断你的标题不合适时自行改写,来源可能是H1、可能是正文里的显著文字、也可能是外部链接的锚文本。

这件事的改写率不低。Google用AI重写标题那篇实测的改写率是76%。换句话说,六个副本之外还有第七个名字——搜索引擎自己拼出来的那个。你能做的是让前六个足够清楚一致,减少它自作主张的理由。

缺席比不一致更常见,也更容易补

回到覆盖率那张表:分享标题缺席34%,推特标题缺席近一半,结构化数据名称缺席53%。这些缺口比"写得不一致"影响更大,而且补起来更简单——在模板里加一行,一次覆盖全站。

缺席的实际后果分两种。有回退链的字段,缺了就回退到标题标签,问题不大;没有回退链的两个字段——结构化数据名称和H1——缺了就是真的没有。

所以补的顺序很清楚:先补没有回退链的那两个,再补有回退链的。这跟直觉相反——多数人会先去补分享标题,因为转发场景看得见。

那些不一致的站,具体差在哪儿?

光看比例不够,几个具体的例子更能说明问题。

先说一个不该被当成问题的

有一类"不一致"其实是对的:同一个品牌在不同语言市场用不同的名字。日本站用片假名,中东站用阿拉伯语,这不是字段打架,是本地化。

判断的办法是看它们指不指向同一个实体。如果结构化数据里用同一个官方地址或者同一个社交主页把几个语言版本串起来,那机器能认出这是一家;如果每个市场各写各的、互不引用,那就真的变成几个不相干的名字了。

三个名字各说各话

allbirds.com的三份自我介绍:标题写的是品牌名加"舒适、可持续的鞋履与服饰",分享标题写的是"世界上最舒服的鞋",H1写的是"Wildly Comfortable. Super Natural."

三句话都不错,也都在说同一个品牌,但它们是三个不同的定位句。搜索结果里出现一个,转发到群里出现另一个,屏幕阅读器念出来的是第三个。

五个副本全不一样

purple.com把这件事做到了极致:标题是"Shop Purple Mattresses: Less pain. Better sleep.",分享标题是"The World's First Comfort Tech Company Backed by Science | Purple",推特标题是"Comfort Tech Backed by Science | Purple",H1是"Up to $1199 off a mattress + base",结构化数据名称是"Purple Innovation, LLC."

五个字段,五个不同的答案。其中结构化数据那个填的是公司注册名,H1填的是当期折扣。一个读者能从这个页面上拿到什么名字,完全取决于他读的是哪个字段。

一个转义引发的显示事故

fromourplace.com的分享标题里写着Essential Cookware & Dinnerware——和号被转义了两次。标题标签里是正常的&,只有分享标题这一份出了问题。

后果是转发到社交平台时,卡片上会实实在在地显示出&这五个字符。这类问题只在特定字段上出现,而多数人从来不看那个字段的实际渲染效果。

把品牌名从名称字段里弄丢的那几个

结构化数据名称那一列有12个完全不同的案例,值得逐类看。

一类是填成了页面标题,peakdesign那种。一类是填成了公司注册名——purple.com填的是"Purple Innovation, LLC.",法律主体名称对搜索引擎理解实体没坏处,但它不是消费者认识的那个名字。还有一类是填成了带地区后缀的变体,nike中国站的"nike (China)"属于这种。

这三类的共同点是:填的人把这个字段理解成了"这是什么",而它问的其实是"它叫什么"。schema.org对名称属性的定义很简短,就是实体的名称,没有别的意思。

一个反例:做对了的长什么样

anker.com的四个字段是这样的:标题"Anker | Live Charged. - Anker US",分享标题"Anker | Live Charged.",H1"Anker | Live Charged.",结构化数据名称"Anker"。

标题最长,带上了地区标识;分享标题去掉地区;H1和分享标题一致;结构化数据只留品牌名。四层递减,每一层都恰好是那个场景需要的粒度。这不是碰巧,是有人认真设计过。

样本里这样的站不多,26个五字段完全一致的站里,多数是"全都填了同一个值"这种省事做法。真正做过分层设计的更少。

中国站的三重身份

nike.com的中国站是另一种情况:标题是一长串中文品牌词堆叠,分享标题是其中一段,H1是"今秋,即将登场",结构化数据名称是"nike (China)"。

四个字段分别服务于四个目的——搜索排名、社交转发、当季营销、实体识别。它们不一致是有意的,但代价是任何一个读者都拿不到完整的品牌表达。

四个字段一起错的那种

前面几个例子都是某一个字段出偏差。还有一种是整组都跟着模板走,模板本身设计得不对。

bugaboo.com的H1是"Homepage Bugaboo"——这是个内部命名,多半是内容管理系统里那个页面的名字直接输出到了H1。同一个站的标题和分享标题都写得挺好,唯独H1漏了一层处理。

casper.com的H1是"Casper Sleep",公司名;标题、分享标题、推特标题三个字段完全一致,都是一句完整的价值主张。这个组合说明写标题的人和写模板的人不是同一拨,两边各按各的理解填。

这类问题的根源不在某个字段,在于没有人负责把这六个字段当成一组来看。标题归内容团队,H1归前端,结构化数据归技术SEO,分享标题可能归社媒运营——四拨人,六个字段,没有一个交汇点。

换一个身份去抓,拿到的还是同一个页面吗?

前面所有比对都建立在一个假设上:不同读者看到的是同一份HTML。这个假设需要验证。

四种身份,同一批地址

171个站的首页,用四种身份各抓一轮:普通浏览器、搜索引擎爬虫、社交平台的分享抓取器、AI爬虫。每一轮之间隔开时间,避免把限流当成身份差异。

身份拿到200被403可解析正文
普通浏览器14620153
搜索引擎爬虫13928147
社交平台抓取器13928147
AI爬虫13334142

从146到133,掉了13个站。同一批地址,换个身份就有13个页面消失了。

18个站从一开始就没进样本

171减去153,有18个站四种身份下都拿不到可解析的内容。这一批不是本节讨论的对象,但值得单独记一笔:它们对任何自动化访问都关着门,其中还有几个返回的是几百字节的空壳页。

拿不到内容的站,六个副本一个都测不到。做站点清单的时候这类样本要单列,别混进"字段缺席"里——两者的成因完全不同,一个是没写,一个是不给看。

六个西班牙品牌,一个都不给

与浏览器相比,状态码发生变化的站里有一组特别整齐:bershka、mango、massimodutti、oysho、pullandbear、stradivarius——这六个都属于同一家西班牙服装集团,对浏览器返回200,对搜索引擎爬虫和社交抓取器一律403。

六个站的响应体也一致,都是三百多字节的拦截页。这不是各站分别配置的结果,是集团统一的防护策略。

先排除掉自己造成的差异

四轮抓取是串行的,中间隔着时间。所以看到差异的第一反应不该是"这个站在区别对待",而是"会不会是我自己造成的"。

排除的办法有三条。一是看差异的方向:如果所有差异都指向后抓的那一轮变差,那更可能是限流累积。实测的结果不是这样——AI爬虫那一轮虽然被拦得最多,但社交抓取器和搜索引擎爬虫的结果完全一致,两轮之间隔着几分钟,说明不是时间因素。

二是看差异的形态:限流通常返回429或者503,而这里拿到的是403加固定长度的拦截页,形态整齐得像一条规则。

三是找反向案例:如果存在"后抓的那一轮反而更好"的站,就说明不是单调衰减。farfetch.com就是这个反例。

三条都对上,才敢说这是身份差异。做跨身份对比,验证方法比结论本身更值得写下来。

还有一个反过来的

farfetch.com刚好相反:对普通浏览器403,对搜索引擎爬虫200。它把浏览器身份当成了可疑流量,反而放行了自称爬虫的请求。

这个方向的差异更少见,但它提醒了一件事:用浏览器身份做站点体检,测出来的可能不是搜索引擎看到的那个站。体检至少要跑两种身份。

为什么AI爬虫被拦得最多?

AI爬虫身份下的403是34个,比浏览器多14个,比搜索引擎爬虫多6个。

多出来的那几个是谁

在搜索引擎爬虫已经被拦的基础上,AI爬虫额外撞墙的站有:article.com、boohoo.com、iittala.com、laneige.com、billie.com。

拦截的形态还不一样。article.com和boohoo.com返回919字节的拦截页;laneige.com返回150字节;billie.com只返回25个字节——连一句完整的话都没有。

iittala那个最值得看

iittala.com对AI爬虫返回的是200,但内容不是首页。它的标题从"Progressive Nordic living since 1881 | Iittala"变成了"Attention Required! | Cloudflare",响应体从26739字节缩到5484字节。

这是个人机验证页。状态码是成功的,内容是一道验证题。如果只按状态码判断抓取是否成功,这个站会被记成正常,而实际拿到的东西一个字都用不上。

这也是做爬取审计时最容易翻车的地方:200不等于拿到了内容。判断标准得往下走一层,看正文长度、看标题是不是变了、看有没有出现验证页的特征词。

体积也是一种差异

除了状态码,响应体积也值得对一眼。有几个站四种身份都返回200,但给AI爬虫的那一份明显更小。

缩小的原因有几种:给爬虫身份返回了不带脚本的精简版、按身份关掉了个性化模块、或者干脆是缓存命中了不同的版本。前两种是有意设计,最后一种是意外。

判断方法是看内容而不是看体积——把两份响应的标题、H1、结构化数据抽出来对,字段一样就说明只是外围模块的差异,字段变了才是真的给了两份东西。iittala那个例子就是靠字段变化认出来的:体积从26739掉到5484,标题也换成了验证页的标题。

拦截可能不是站点自己决定的

看到403很容易归因成"这个站不想让AI抓"。实际情况往往更绕。

拦截可能来自站点自己的规则,也可能来自前面那层防护服务的默认策略,还可能来自主机服务商的统一配置。最后这种最隐蔽——托管主机悄悄拦AI爬虫、站点方完全不知情,那篇讲的就是这种情况:AI引用数归零,监控没报警,因为站点本身一切正常。

怎么区分?看规则文件里有没有对应的规则组。样本里那六个西班牙品牌的规则文件都没写禁止搜索引擎爬虫,403是在更靠前的一层做出来的。规则文件里没写却被拦,说明这个决定不在你能改的地方。

还有一种误伤:防护服务按行为特征判断,把某些爬虫误判成攻击流量。拦AI爬虫怎么不误伤搜索引擎爬虫那篇给了几条配置层面的判据,核心是反向域名校验——光看请求头里自称什么是不够的。

验证身份这件事本身也是双向的

本文用的是自称法:请求头里写上某个爬虫的标识。这只能测出"站点对这个标识怎么反应",测不出真爬虫来的时候会怎样,因为真爬虫的地址段是可以被校验的。

所以这批数据的准确说法是:站点对这个身份标识的反应。多数站点的判断就停在标识这一层,所以两者通常一致;但对做了反向校验的站,真爬虫可能反而畅通。怎么验证一个自称Googlebot的请求是不是真的那套办法,反过来也是站点该做的功课。

被拦不完全是坏事

拦AI爬虫是一个正当的商业选择,不是配置错误。真正需要注意的是它的连带效果:一旦你的页面进不了AI爬虫的抓取范围,那你在AI答案里的名字就不是你写的六个副本里的任何一个——它来自别人对你的转述。

要不要拦是策略问题,拦AI爬虫该不该拦、用哪一层拦那篇给的选型框架可以直接用。这里只提醒一点:拦之前先想清楚你希望AI提到你的时候说什么。

这件事的量级在变

几年前这个决策不太要紧,因为AI爬虫的抓取量小得可以忽略。现在不是了——AI爬虫的抓取量已经超过搜索引擎爬虫好几倍,它们成了很多站点最主要的机器访客。

抓取量大意味着两件事:一是服务器成本真实存在,拦的理由更充分了;二是被拦的代价也更高,因为你放弃的是一个正在扩大的分发渠道。

更细的一点:AI搜索里的"提及"和"引用"是两件事——被提到名字和被链接过去,中间有很大的落差。一个页面拿不到抓取,通常还能被提及,但引用基本没戏。

名字不统一在AI这一层放大了

搜索引擎有很强的实体消歧能力,同一个品牌的三种写法它多半能合并。AI摘要在这方面弱一些,尤其是在没有结构化数据兜底的情况下。

所以六个副本的一致性,在AI这一层的收益比在传统搜索那边更明显。给品牌搭一个实体主页的思路就是从这里来的:先有一个明确的地方说清楚"我是谁",其他页面再指过去。

13个站消失,损失的到底是什么

从146到133,掉的这13个站在AI这一侧丢的不只是一次抓取。

抓不到页面,六个副本一个都读不到,实体名称、品类描述、价值主张全都进不了模型的候选材料。那么当有人问起这个品牌,答案从哪来?从别人写的东西里来——媒体报道、评测、论坛讨论、竞品的对比文章。

这些二手材料未必不准确,但它们的措辞不是品牌自己定的,时效性也差。精选摘要那一块被AI概览吃掉一半之后的经验是:能被直接引用的原文,权重远高于被转述的内容。

还有个容易忽略的连带项:抓取体积也有上限。Googlebot的抓取体积上限实测那篇讲的是另一种"拿不到"——不是被拦,是页面太大读不完。这两种在结果上是一样的:机器手上没有你的原文。

同一份规则文件,对不同爬虫给出的答案一样吗?

身份差异不只出现在防护层,也出现在站点自己写的规则里。

5.2%的地址两套答案

拿161份能解析的规则文件,去核对同一批站点提交在站点地图里的50783条地址,分别按搜索引擎爬虫和AI爬虫的规则组判一遍。

判定组合地址数占比
两边都允许4812594.8%
搜索引擎允许、AI爬虫被禁26215.2%
两边都禁290.06%
搜索引擎被禁、AI爬虫允许80.02%

2621条地址对两种身份给出不同答案,这部分是站点有意为之:写了专门针对AI爬虫的规则组,把它挡在外面。

反过来那8条更像是意外——搜索引擎被禁而AI爬虫放行,多半是规则组写得不完整,通配组和具名组的覆盖范围没对齐。规则文件的分组不继承这件事是这类错误的常见成因。

这两个数字放在一起才有意义

94.8%两边都允许,5.2%区别对待。单看后者会觉得"原来这么多站在拦AI",单看前者又会觉得"几乎没人拦"。

正确的读法是把它跟前面那批实测放在一起:规则文件层面只有5.2%的地址被区别对待,而实测抓取层面AI爬虫的成功率比浏览器低了8个百分点。两个数字对不上,说明大部分区别对待发生在规则文件之外的地方。

这个落差是本节最值得记住的一点。查规则文件能看到的,只是站点愿意写下来的那部分意图;真正在起作用的规则,很多压根没写在任何一份公开文件里。

2621条集中在哪几个站

这2621条不是均匀分布的。写了AI爬虫专属规则组的站本来就少,一旦写了,它名下的地址就整批受影响。所以这个数字更适合读成"少数站点的大量地址",而不是"很多站点在这么做"。

规则的形态也值得看一眼:多数是直接对某个AI爬虫标识写全站禁止,少数是禁掉特定目录。前者是态度,后者是取舍——后者的写法通常出现在有付费内容或者原创图库的站上。

为什么会出现"搜索引擎被禁而AI爬虫放行"

那8条反向案例,成因基本能归到规则组的匹配逻辑上。

规则文件的匹配规则是:优先取最具体的那个爬虫标识组,取不到才用通配组。如果一个站给搜索引擎爬虫写了专属组、又在通配组里放行了某些路径,那么AI爬虫走通配组反而更宽松——因为它没有专属组,不受那些针对搜索引擎的限制约束。

写规则的人多半没意识到这个后果。他以为自己在"额外限制搜索引擎",实际上同时造成了"AI爬虫比搜索引擎权限更大"。规则组不继承这件事,在多爬虫时代的后果比过去严重得多。

规则说允许,不等于真的给

规则文件放行只是第一关。规则文件说允许、AI爬虫仍有10个站进不去那篇量的就是这个落差:声明层允许,传输层照样拦。

本文这一批数据也印证了同一件事——那六个西班牙品牌的规则文件里没有一条禁止搜索引擎爬虫,403是在更靠前的一层做出来的。声明和交付是两回事,只查规则文件会得出过于乐观的结论。

六个副本该怎么收敛?

不是所有不一致都要修。按后果排一下。

顺序上有个前提:先确认这几个字段真的能被读到,再谈它们说得对不对。如果页面是纯客户端渲染,服务端返回的是空壳,那六个副本一个都不存在——不同渲染方式下AI爬虫的引用率差异那篇量过这一层的落差,先把内容送出去,再谈名字统一。

第一档:会让人看到错东西的

分享标题里的转义错误、结构化数据名称填成了页面标题、H1是弹层文案。这三类会直接让某个读者拿到明显不对的内容,发现一条改一条。

这一档还有个共同点:它们都是"看得见的错"。转义符号会显示在卡片上,实体名称错了会出现在富结果里,H1错了屏幕阅读器会念出来。凡是能被人直接看见的错误,改的优先级都排在只有机器能察觉的问题前面。

第二档:会稀释品牌表达的

标题、分享标题、H1说着三句不同的定位话。这一类不算错,但它意味着你的品牌在三个场景里各有一副面孔。要不要统一是品牌决策,不是技术决策——技术这边能做的是把现状摆出来,让做品牌的人看见。

第三档:写少了而不是写错了

结构化数据缺席、分享标题缺席。这一类靠回退链兜着,短期不出事。但缺席意味着你把决定权交给了消费方的回退逻辑,而那个逻辑可能随时变。

分享卡片这一档有个专门的检查口

社交平台的预览效果不能靠读源码猜,得看实际渲染。转义错误、图片尺寸不对、标题被截断,这三类问题都只在渲染出来之后才看得见。逐字段体检四大平台社交卡片那套办法是按平台分开看的,因为同一份字段在不同平台的截断长度和裁切比例都不一样。

图片那一侧还有单独的坑。分享图的尺寸与动态生成那篇讲的是另一半——标题对了图不对,卡片照样难看。

一条最省事的收敛路线

模板层收一个出口:定义一个"页面主名称"变量,标题标签、分享标题、推特标题都从它派生,只在需要区分的场景做显式覆盖。结构化数据名称单独定义成"实体名称",填品牌名而不是页面标题。H1留给页面主题,横幅文案降级为H2。

这套改动的收益不在某个具体指标,而在于以后任何一个新读者出现的时候,它拿到的都是同一个答案。

实体名称那一份单独拎出来定

六个字段里,结构化数据名称是唯一一个不该跟着页面走的。它描述的是实体,不是这一页。

具体做法:站点级定义一个实体名称常量,首页的组织标记、每个页面页脚的站点标记、面包屑的根节点,全都引用它。改品牌名的时候只改一处。用图结构把实体串起来那套写法在这里特别合适——所有标记指向同一个实体节点,而不是各写各的名字。

验收标准写成一句话

改完之后怎么算合格?给一个可以直接用的判据:

把六个字段的值打印在一张纸上,随便找个不了解这个项目的人看,他能不能一眼说出这是同一个网站。

能,就合格了。这个判据比任何指标都实在——因为消费方做的判断,本质上就是这件事。

先把这件事变成一次性的决定

收敛之所以难做,是因为它看起来像一件要反复维护的事。其实不是——只要出口收成一个,后面就不用再管了。

难的是第一次。第一次要把散在主题、插件、营销代码里的输出全部找出来,确认哪一路是当前生效的,再把其余几路关掉。这个过程跟同一个字段被写了两遍时谁生效那篇说的是同一件事:先搞清楚现状,再谈统一。

做完之后加一条流水线检查,字段值对不上就让构建失败。这样新来的人往模板里加一路输出的时候,会当场知道。

怎么查自己站上的六个名字?

一条命令把六个字段一起拉出来。

U=https://example.com/
curl -s -m 20 "$U" | tr '\n' ' ' | grep -o -iE \
 '<title>[^<]*|og:title" content="[^"]*|twitter:title" content="[^"]*|og:site_name" content="[^"]*|<h1[^>]*>[^<]*'

输出里逐行看,六个值放在一起就能看出差异。结构化数据里的名称要单独取:

curl -s -m 20 "$U" \
  | grep -o -zE '<script[^>]*application/ld\+json[^>]*>[^<]*' \
  | grep -o -aE '"name" *: *"[^"]*"' | head

换个身份再抓一次

for ua in \
 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/126.0 Safari/537.36" \
 "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
 "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" \
 ; do
  code=$(curl -s -o /tmp/p.html -w '%{http_code}' -m 25 -A "$ua" "$U")
  size=$(wc -c < /tmp/p.html)
  ttl=$(grep -o -iE '<title>[^<]*' /tmp/p.html | head -1)
  printf '%s\t%s\t%s\n' "$code" "$size" "$ttl"
done

三行输出对着看:状态码一样吗?体积差得多吗?标题变了吗?只要有一行不一样,你的站对不同读者就是两个站。

别只看状态码

前面iittala那个例子说明了原因。加一条判断:

grep -ciE 'attention required|verify you are human|checking your browser|enable javascript' /tmp/p.html

结果不是0,那个200就得打个问号。

结构化数据那一份要单独取

前面那条命令抓不到结构化数据里的名称,因为它在脚本块里,而且可能有好几块。多块的时候还要判断哪一块描述的是组织、哪一块描述的是网站。

最省事的办法是在浏览器控制台里跑,让JSON自己解析:

[...document.querySelectorAll('script[type="application/ld+json"]')]
  .flatMap(s => { try { return [JSON.parse(s.textContent)].flat(); } catch (e) { return []; } })
  .flatMap(o => o['@graph'] || [o])
  .filter(o => o && o.name)
  .map(o => [o['@type'], o.name])

输出是类型和名称的配对。看两件事:组织或网站那一条的名称填的是不是品牌名;同一个类型有没有出现两条名称不同的。

把六个字段拉成一张表

要批量对一批页面,最好把结果落成表格再看。下面这段把每个地址的五个字段抽成一行制表符分隔:

while read -r u; do
  h=$(curl -s -m 20 "$u" | tr '\n' ' ')
  g() { printf '%s' "$h" | grep -o -iE "$1" | head -1 | sed -E "s/$2//"; }
  t=$(g '<title>[^<]*' '<title>')
  o=$(g 'og:title" content="[^"]*' 'og:title" content="')
  w=$(g 'twitter:title" content="[^"]*' 'twitter:title" content="')
  n=$(g '<h1[^>]*>[^<]*' '<h1[^>]*>')
  printf '%s\t%s\t%s\t%s\t%s\n' "$u" "$t" "$o" "$w" "$n"
done < urls.txt > names.tsv

拿到表之后,用一列简单的判断就能挑出要处理的行:标题列和H1列不一样的、分享标题列为空的、任何一列里出现&amp;的。

这段脚本用的是纯文本匹配,遇到属性顺序不同、单引号、或者标签中间换行的写法会漏。要严谨得用带HTML解析器的语言重写,或者直接在无头浏览器里读DOM。日常巡检用文本版够,漏掉的手工补。

盯住那两个没有回退链的

如果时间只够查一件事,就查这两个:结构化数据里的名称有没有、H1是不是页面主题。前面说过,它们缺席不会被任何机制补上。

curl -s -m 20 "$U" | grep -c 'application/ld+json'
curl -s -m 20 "$U" | grep -o -icE '<h1[^>]*>' 

第一条返回0,说明整页没有结构化数据;第二条返回0说明没有H1,返回大于1说明有好几个。这两个数字加起来不到十个字符,却能覆盖本文说的大半问题。

把检查接进日常

这几条脚本的价值在于成本极低。挑十个最重要的页面,每周跑一次,把输出存下来做对比。变化出现的时候你会第一时间知道——而不是等到某天有人问"为什么搜索结果里我们的名字是这个"。

一个更省事的做法:让页面自己报数

如果站点是自己开发的,可以在模板里加一个只在测试环境输出的调试块,把六个字段的最终值打印在页面底部。开发和内容同事在浏览器里就能看见它们,不用去翻源码。

这个做法的好处是把检查从"专人定期跑脚本"变成"任何人打开页面都能看见"。样本里那些四个字段各说各话的站,问题多半不是技术难度,是没人同时看见过这四个值。

生产环境记得关掉,或者用只有带特定参数才输出的方式。

常见问题解答

标题和H1不一样,会影响排名吗?

直接影响很小。搜索引擎主要看标题标签,H1是辅助信号之一。但它会影响两件事:一是辅助技术的使用者听到的第一句话,二是AI摘要在提取页面主题时的判断。样本里72.3%的站两者完全不同,说明这已经是行业常态,不是个别失误。

六个字段里,哪个最不该省?

标题标签,因为所有消费方都会回退到它。第二重要的是结构化数据里的名称——它不回退,缺了就是没有,而AI摘要越来越依赖实体识别。

分享标题一定要和标题标签一样吗?

不一定,但要有理由。搜索结果的标题需要塞关键词,转发卡片的标题需要好读,两者分开写是合理的。问题在于分开写之后就有两套内容要维护,改一处忘一处比一开始就统一更糟。

H1被轮播横幅占了,怎么改最省事?

把横幅里的标题从H1降成H2或者div,然后在页面上加一个真正的H1。如果设计上不想让它显示,可以用视觉隐藏但屏幕阅读器可读的方式处理——注意不要用display:none,那样辅助技术也读不到了。

结构化数据里的名称该填什么?

填实体的名称。如果标记的是组织,填品牌名或公司名;如果标记的是网站,填站点名。别把页面标题连着分隔符一起填进去——样本里就有站点这么干,那个字段变成了"Home - Bags + Camera Gear"。

AI爬虫拿不到我的页面,我在AI答案里就消失了吗?

不会消失,但你失去了对表述的控制。AI仍然可能通过第三方转述提到你——媒体报道、评测文章、社交讨论。区别在于那些内容里的说法不是你写的。要不要接受这个交换,取决于你更在意抓取成本还是表述准确。

H1可以有多个吗?

规范上允许,实践中不建议。HTML规范里标题层级元素那一节几经修改,现在的共识是一个页面用一个H1标明主题,其余层级用H2往下排。样本里有站点的首页出现了13个H1,那已经不是层级问题,是把H1当样式用了。

更实际的判据是:如果你的H1有好几个,那"这个页面讲什么"这个问题就有好几个答案,机器只能自己挑一个。

分享标题和标题不一致,会被判成作弊吗?

不会。这两个字段服务于不同场景,不一致是合法的,也很常见。会出问题的是另一种情况——给爬虫看的内容和给用户看的内容不一样,那属于另一码事,判据是"同一个身份看到的东西是否一致",不是"不同字段是否一致"。

用什么身份做站点体检最靠谱?

至少两种:普通浏览器和搜索引擎爬虫。样本里有10个站两者的状态码不同,只用一种身份会漏掉一半事实。如果关心AI可见度,再加一种AI爬虫身份。

标题写多长合适?六个字段要一样长吗?

不用一样长。标题标签受搜索结果的显示宽度限制,超出会被截断;分享标题在各平台的截断长度不同,通常比搜索结果更短;H1没有长度限制,它受排版约束;结构化数据名称应该最短,就是实体名。

合理的形态是从长到短递减。样本里anker.com那一组就是这个样子:标题最长、分享标题去掉地区标识、H1与分享标题一致、结构化数据只留品牌名。

为什么有些站的分享标题里有转义错误?

因为那个字段的值经过了两次转义。模板先把&转成实体,输出到属性里的时候框架又转了一次,结果变成实体的实体。标题标签通常不出这个问题,因为它是文本节点不是属性值,两条处理路径不一样。

排查方法是直接看源码里那个属性的原始字符,别看浏览器渲染后的开发者工具面板——面板会帮你解一次码,看不出问题。

把六个字段全填成一样,算不算偷懒?

算,但它是安全的偷懒。全填一样的坏处是浪费了各字段的场景特性,好处是永远不会自相矛盾。样本里26个五字段一致的站多数属于这一类。

相比之下,填了六个不同的值又没人维护,风险大得多。如果没有专人盯着这几个字段,统一成一个值是更稳的选择。

这些数据能代表中文站吗?

字段一致性那部分可以参考,因为它由模板实现方式决定,跟站点在哪个市场无关。身份差异那部分不能直接套——国内的防护策略、爬虫构成、平台生态都不一样,要自己重新量。

权威参考资料

分享到
标签
版权声明

本文标题:《首页的title、og:title和H1,说的常常不是同一件事》

本文链接:https://zhangwenbao.com/self-description-copies-title-og-h1-schema-audit.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交