← 洞见GEO 科普

结构化数据不是给爬虫看的

泛友数字2026/10/27 11:4238 阅读
结构化数据不是给爬虫看的

JSON-LD 1.1 的 §1.6 数据模型概览只用一句话交代了这份格式在描述什么:「JSON-LD 文档所描述的数据模型,是一张带标签的有向图。」后面几百页都在展开这一句。节点是资源,节点之间是有向弧,弧上带标签,标签是属性。规范从头到尾在讲这张图怎么读,没有一节在讲「怎样让搜索引擎读懂一个页面」。

同一份推荐标准的 §8 数据模型把这句话写成了 MUST:一个有出边的节点必须是 IRI 或空白节点,并且图里不允许存在未连接的节点。这两条合起来否掉一种常见写法——把价格、库存、评分当成可以独立存在的字段。值必须挂在某个被标识的主体上。一个没有 @id 的 Offer、一个只写了 name 的 Product,在图上不构成事实,只是一条没有正确端点的弧。抽取器按主语取值,取不到主语就跳过整段。

§3.1 解释上下文:「上下文用来把词项映射到 IRI。」这句话的边界很窄。上下文只决定 price 这个键指向哪一个 IRI,不决定它后面的值是否真实。词项区分大小写,Price 与 price 是两个词,一个映射到 schema.org,另一个可能什么都不是。换一份上下文,同一段 JSON 会指向另一套词汇表,页面内容一个字没变。

§4.3 值顺序的规定最容易踩:JSON-LD 里的数组默认不表达其中元素的顺序,规范的原话是「这与常规 JSON 数组恰好相反,后者默认有序」。§9.7 把两种容器分开写:list 是有序集合,set 是无序集合。放到业务上,步骤、作者名单、议程、套餐档位都属于顺序有意义的值;写成数组,消费方拿到的是集合,它可以按任意顺序处理,也可以只取第一条。要保序只能用 @list,规范没有给第二个办法。

schema.org 的数据模型页补上主语与谓语之间的约束:每个属性可以有一个或多个 domain,也可以有一个或多个 range,属性的值应当是这些 range 中至少一个类型的实例。同一页解释了为什么允许复数:「允许多个 domain 与 range 纯粹出于实用考虑。」读法要跟着改。range 约束的是值的类型,不是值的真假,一条通过了类型检查的标注,语义仍然可能全错。

同一页的 Conformance 一节说得更直白:schema.org 采取的是务实的符合性观点,类型与属性的关联「更接近指南,而不是正式规则」,并且一条描述同时带上几个互不相干类型的属性并不算错。规范本身对宽泛标注是宽容的。惩罚不来自 schema.org,来自消费方:搜索引擎自己的展示规则要求相关性与具体性,标注在那里才失效。

§10.1 序列化与反序列化 RDF 给出流水线:文档先转成三元组,消费方按谓词 IRI 取值,再按 range 期望的类型转成数字、日期或布尔。价格字段是典型的断点。JSON-LD 允许值对象里的 @value 是字符串,所以写「面议」在语法层完全合法;到按 Number 取数那一步转换失败,多数入库脚本的处理方式是丢掉整条 Offer,页面上其余字段一起失效。区间价应当用 priceSpecification 表达,并给出 priceValidUntil,让下游知道这个价何时作废。

§7.2 容易被忽略:script 元素里的 JSON-LD 受 HTML 转义规则约束,尖括号与引号要写成实体,而且该节(标注为非规范性)注明,转义后的内容经过处理仍然保持转义。把带标签的富文本塞进 description,消费方拿到的是 < 开头的字面量。字段里放纯文本,是这一条给出的唯一稳当做法。

规范能判定的到此为止。剩下三类失效它管不到,因为那是发布政策而不是数据模型。第一类是内容不可见。Google 的结构化数据总则要求不标记读者看不到的内容,入门文档补了一句,页面不可见的信息即使信息准确也不要标。只把问答写进 JSON-LD、页面没有问答区,或者标记写了具体价格、页面写「详询」,都属于这类。后果不是排名下降;总则写的是失去富媒体展示资格,并可能触发人工处置。

第二类是类型错配。总则的 Relevance 一节给了两个官方例子:体育直播站把赛事直播标成本地活动,木工站把操作说明标成菜谱。两者的共同点是标记语义与页面内容属于不相干的类别。另一层错配在颗粒度,Specificity 要求使用 schema.org 里最具体的类型与属性名。公司简介标成 Article 且 author 写成 Organization,服务介绍标成 Product 却没有 Offer,列表页把每个条目写成指向同一地址的 Product,这几种都能通过校验。校验器查字段是否合规,不查语义是否成立。

第三类是字段与页面矛盾。总则要求结构化数据是页面内容的真实表示,要求提供最新信息。常见形态是标记里写具体价格与币种、页面上写「按配置报价」;availability 常年 InStock 而实际断货;每次改动都把发布时间改成当天。漏标也算矛盾:页面上八条评价,标记只写三条,完整性要求可见条目尽量全部标注,选择性标注会被判为误导。招聘页最经不起拖,岗位招满还挂着 JobPosting,比不标更容易出问题。

还有一种矛盾由规范自己制造。同一实体在两个 script 块里各标一次,按 §5.3 展平之后是同一个节点,属性合并,冲突的值不会互相裁决,只会成为同一谓词下的多个值,而多个值默认无序。所以标记里写具体报价、页面上写面议,在图上是两条并列事实,消费方取哪条不由你定。上线前先数页面里有几个 script 块、几个 itemscope,同一类型出现两次就合并,不要再加第三个。

页面被解析成有向图之后,抽取器只使用其中少数几条边
同一页面对人是一段话,对抽取器是一组带标签的边;少一个主语,整条边就落不了地。

验收按可交付物定,不按「已优化」定。每个关键实体对应一个 JSON-LD 块,块数与实体数一致;价格、库存、更新时间三个字段在页面可见文本里出现同样取值;有序字段用 @list,无序字段用数组;Rich Results Test 报零个 critical 错误;Search Console 的富媒体报告里该类型有效项目数不为零。五条同时满足才算做完。

边界在页面这一侧。没有可枚举实体的页面不要标,观点文章没有价格、库存、评分,硬套 Article 只换来语法合规。每周变化的活动页不适合细标,维护成本超过收益,过期标记比没有标记更糟。登录后页面、内部系统、参数化筛选页同理,抽取器取不到,标了只剩风险。值得投入的是有人来拿字段的页面:型号、规格、地址、营业时间、课程安排、职位。没有人手时只标三五个会被第三方抓走的字段,其余先空着。

效果不要用排名测。能测的是引用侧:同一批页面在第三方工具里的字段完整度、被聚合站收录的条目数、站内搜索里长参数词的命中。改标前后各取一次,不依赖搜索后台。这些数不动,说明下游没有消费方,继续加字段只是自娱。

回到 §1.6 那句话。图是给查询用的,不是给抓取用的;一张图里能查到的,只有你写上去并且写对了的那几条边。