分类页开了19405个,首页只点得到一成七

分类页开了19405个,首页只点得到一成七
张文保 更新 23 分钟阅读 2,010 阅读
本文目录
  1. 一个分类同时活在三个地方,你知道它们对不对得上吗?
  2. 先说口径怎么定的
  3. 数据出口里到底有多少分类?
  4. 这些分类是什么时候建的?
  5. 首页能点到的,只有其中一成七
  6. 覆盖率低本身不是罪
  7. 出口里有、sitemap里没有的那2479个,是怎么漏的?
  8. 分类越多,两份清单越对不上
  9. 有一成的分类,一件货都没有
  10. 空货架那一页,服务器回的是什么?
  11. 怎么判断一个分类页是不是真的空?
  12. 用浏览器看一眼,答案分成四种
  13. 改完之后的判据
  14. 顺手做的一组自对照
  15. 分类页自己有内容吗?
  16. 这些分类该删、该合,还是该留?
  17. 第一档:空的、没进导航、也不打算再用
  18. 第二档:空的、但导航上还挂着链接
  19. 第三档:有货、但既不在导航也不在sitemap
  20. 第四档:活动集合
  21. 改完怎么验证
  22. 我在这次测量里踩到的三个坑
  23. sitemap把语言版本也算了一份
  24. 静态HTML抓不全首页导航
  25. 把链接条数当成分类数
  26. 常见问题解答
  27. 分类开得多本身有害吗?
  28. 空的集合到底该404还是该noindex?
  29. 怎么快速看出我的站有多少空分类?
  30. 首页导航覆盖率17.1%算低吗?该提到多少?
  31. 为什么不直接爬全站,非要用数据出口?
  32. 分类页的描述写多长合适?
  33. 这次的结论有哪些地方不成立?
  34. 这套方法能用在WooCommerce或者Magento上吗?
  35. 权威参考资料

摘要: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 这个不用登录就能读的地址,返回的是所有已经发布到网店渠道的分类。每一条都对应一个真实可访问的地址。这一族出口保哥之前写过它的商品版,那篇讲的是它泄露了什么,这次只把它当分类的权威清单用。
  • sitemap。站点主动递给爬虫的那份名单。
  • 首页导航。给人走的那条路,也是站内链接权重的起点。

这三份清单本该是同一批东西的三个副本。实测下来,58个站里只有21个站的出口清单和sitemap逐条对得上,首页导航那一份跟另外两份的差距更是数量级的。

先说口径怎么定的

出口那份翻页翻到底,一页250条。sitemap那份要按语言分卷拆开——这一步不做会算错,后面单独说。首页导航那份不能只抓静态HTML,必须用无头浏览器渲染一遍再取链接,理由跟测商品可达性那次一样:gymshark的首页静态HTML里一个分类链接都没有,渲染完有92个。

数据出口里到底有多少分类?

58个站合计19405个,中位124个,最大的那个1346个。

注意这19405个不是后台里的草稿,是已经发布、有地址、爬虫走得进去的页面。也就是说,光分类页这一类,这58个站就给搜索引擎准备了将近两万个待抓地址。

按每个分类装了多少货分档,分布是这样:

分类里有多少件货数量占比
0件205010.6%
1件9034.7%
2到5件380719.6%
6到20件522226.9%
21到100件480624.8%
101到500件18419.5%
500件以上7764.0%

中位数是12件。三分之一强的分类装的货不超过5件,这里面绝大多数是活动集合、赠品集合、某个应用自己建的辅助集合。它们都有独立地址,都能被抓,都在消耗抓取预算。

这些分类是什么时候建的?

出口会告诉你每个分类的发布时间,把19405个按年份归一下,堆积的过程一目了然:

发布年份数量占比
2019年及更早17449.0%
2020到2022年371119.1%
2023年206610.6%
2024年235112.1%
2025年485725.0%
2026年467624.1%

近两年建的占了49.1%,接近一半。这条曲线不是业务在扩张——58个站的商品总数并没有在两年里翻倍。它更像是运营节奏的副产品:每个季度、每次上新、每轮促销,都留下一批地址,而清理这件事从来没被排进过任何一个人的日程。

另一头也值得看:2019年及更早建的分类还有1744个活着,最老的那批发布于2012年。一个十四年前建的集合,今天仍然在被爬虫定期访问。它当年装的货多半早就下架了。这类页面该怎么进出sitemap,百万SKU的sitemap实战那篇给过一套进出场规则,套到分类上同样成立。

首页能点到的,只有其中一成七

把首页渲染后DOM里所有指向分类的链接抓下来,去掉查询参数再去重,跟出口那份对一遍:

出口里的分类首页能点到覆盖率
allbirds1346292.2%
thirdlove1014484.7%
untuckit769212.7%
brooklinen781293.7%
marinelayer1176484.1%
chubbiesshorts100713513.4%
parachutehome804789.7%
flyingtiger47615933.4%

全样本的中位覆盖率是17.1%,均值22.1%,最高的那个站88.9%,13个站不到一成。

这个数低到什么程度?意思是你后台里每建六个分类,只有一个在首页有入口。剩下五个要么埋在二级三级导航里,要么只能靠sitemap被发现,要么就干脆没人知道——最后这一类就是孤岛页面,只不过大家平时盯的是商品页,很少有人回头数分类页。

覆盖率低本身不是罪

这里得把话说清楚,不然容易读成“覆盖率越高越好”。

首页导航是个稀缺位置,塞不下1346个链接,也不该塞。真正该担心的是另一件事:那些不在导航里的分类,你到底打算拿它们怎么办?是让它们安静地待着不被索引,还是让它们进sitemap去争抓取预算?多数站的实际状态是第三种——既没打算,也没管过。

出口里有、sitemap里没有的那2479个,是怎么漏的?

把出口和sitemap两份清单逐条对,结果高度不对称:出口里有而sitemap里没有的,2479个;反过来sitemap里有而出口里没有的,只有115个。(reebok的分类清单翻页到上限还没到底,两侧不可比,已经从这一组数里扣掉。)

反向那115个基本可以忽略,正向这2479个才是问题。逐站看:

没进sitemap的分类占该站分类数
brooklinen724 / 78192.7%
misen188 / 21985.8%
rothys124 / 19862.6%
aloyoga288 / 60747.4%
awaytravel72 / 15546.5%
stanley191396 / 21744.2%
beistravel293 / 76038.6%
thirdlove265 / 101426.1%

brooklinen那一行很极端:781个分类,sitemap里只列了57个。剩下724个页面照样能打开、照样能被抓,只是站点自己没把它们写进名单。

这件事本身不算错。sitemap不是必须列全,把低价值页面排除在外反而是正确的用法。问题在于:没进sitemap的这批,绝大多数同时也不在首页导航里。两条发现路径都断了,页面还留着——它就成了纯粹的抓取成本,没有任何回报。这批地址还会顺手把站内权重漏掉一部分,因为导航里那些指向它们的残余链接并没有一起清掉。

顺带说一句,就算进了sitemap也不代表万事大吉。从站点地图里抽585条网址有48条是坏的那次实测,生成程序全程一次都没报错。清单本身的可信度,也得单独验一遍。

分类越多,两份清单越对不上

把58个站按“出口和sitemap是不是逐条一致”分成两组,两组的分类规模差得很清楚:

  • 完全一致的21个站,分类数中位87个。
  • 对不上的37个站,分类数中位155个,接近前者的两倍。

这个关系不难理解。分类少的时候,sitemap生成器把全部集合列一遍就行,没人会去筛。分类多起来之后,主题或者插件开始按某种规则挑——挑的规则通常写在配置里,没人复查过,于是漏掉哪些完全是偶然。生成器说格式正确的时候其实只查了三件事,少列了谁它不会告诉你。

值得强调的是,这里只能说两者同时出现,不能说分类多导致了对不上。也可能是那些分类多的站本来就用了更复杂的插件组合。要坐实因果得看同一个站在分类数增长前后的变化,这次的数据做不到。

但无论因果如何,实践上的建议是一样的:谷歌那份大站抓取预算文档把这件事叫做“感知到的库存”——搜索引擎会按它以为你有多少页面来分配抓取量。你的库存清单里塞了一堆空集合,分到每个真商品页上的额度就少一份。

有一成的分类,一件货都没有

19405个分类里,2050个的商品数是0,占10.6%。逐站看,比例差得很远:

空分类占比
fiskars26 / 2796.3%
brooklinen446 / 78157.1%
nativecos9 / 2437.5%
beistravel259 / 76034.1%
allbirds397 / 134629.5%
snowpeak185 / 66327.9%
gymshark108 / 52520.6%
chubbiesshorts166 / 100716.5%

这些空货架的去向更值得看:2050个里有1272个(62.0%)被写进了sitemap,也就是说站点主动把它们推荐给了爬虫。还有44个至今挂在首页导航上,用户点进去会看到一个什么都没有的页面。

这件事跟站点架构做得好不好关系不大,扁平三层架构该怎么搭是另一个问题,这里纯粹是没人做清理。建过活动集合的人都知道这是怎么发生的:黑五建一个 black-friday,活动结束把商品移走,集合留着明年用。明年用不用另说,这一年里它一直在那儿,一直被抓。

空货架那一页,服务器回的是什么?

这是本次实测里最值得单拎出来的一项。谷歌对这类页面的要求写得非常明确,在筛选类地址的抓取管理文档里只有一句话:当一个筛选组合没有结果时,返回HTTP 404。

我从48个站里各抽了几个声明为0件的分类,一共请求了146个页面。这里的“声明”取的是分类对象自己给的 products_count,按Shopify官方的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的纯抓取开销。

这笔账跟条件请求能省下多少抓取预算是同一本账,只是那一头省的是重复内容,这一头浪费的是空内容。

怎么判断一个分类页是不是真的空?

这一节是本次踩得最深的一个坑,写出来比结论有用。

我一开始的判据是数页面上的 /products/ 链接:零链接就是空。跑完发现146个空分类页里有124个能数到商品链接,最多的一个数到441个。这个结果显然不对——出口明明说0件。

用浏览器看一眼,答案分成四种

拿几个典型页面用无头浏览器打开,按链接所在的DOM位置分开数:

页面导航里页脚里正文区正文区可见页面怎么说
casper的frontpage108000没有任何提示
chubbies的easy-mesh-2020-lounge20650明写No Products Found
cluse的sale-700000明写这个分类里没有商品
bollandbranch的neutral-bedding916767没有任何提示

前三行说明了那124个的来历:导航和页脚会贡献几十个商品链接,筛选器还会把一批卡片预渲染进DOM再隐藏起来。/products/ 链接这把尺子,量的根本不是这个分类有没有货。

第四行是另一回事。bollandbranch那一页正文区实打实摆着67个可见的商品卡,标题、H1、canonical一应俱全。我去问了权威口径——这个分类的商品清单接口返回0件,分类对象自己也说商品数是0。两边都对:这个站的分类页内容根本不由Shopify的集合决定,是另一套系统在填。它的 /collections/sheets 直接404就是证据。

改完之后的判据

换成两条一起看:

  • 权威口径:/collections/<handle>/products.json 返回0件。
  • 人眼口径:浏览器打开后,正文区里可见的商品卡为0——不是页面上所有的商品链接为0。

按这两条重跑48个站各一页:33个是真空货架,14个正文区仍有可见商品卡(分不清是空态页上的推荐位还是像bollandbranch那样口径脱钩,所以这14个站不进比例,只当形态举例),1个页面脚本报错没读到。

真空的那33个里,只有11个页面明确告诉用户这里没有商品,另外22个什么都不说。用户点进去看到一片空白,既不知道是没货了还是页面坏了——这一屏该写什么,类目导航那篇里讨论过同一个毛病。这跟站内搜索搜不到那一页的处境几乎一模一样,只是搜索页至少有一半的站做了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个字符。

换句话说,六成以上的分类页,除了一排商品卡之外没有任何自己的文字。分类页想拿排名,靠的就是那段描述加上商品集合本身的语义——两样都没有,它跟站内另外几百个分类页在搜索引擎眼里就很难区分开,这正是电商重复内容最常见的来源之一。至于一个分类页凭什么值得被单独收录,商品列表页那97条准则里给的答案是:得有别处拿不到的东西。

这些分类该删、该合,还是该留?

先说结论:绝大多数不该删。删了会掉链接、掉历史、掉可能存在的外链,收益却只是少几个抓取地址。真正该做的是分档处理。

第一档:空的、没进导航、也不打算再用

这一档给noindex,让它继续200着。别做404——如果这个集合明年还要用,404会让它的地址信誉归零。判断标准是:这个集合有没有历史流量、有没有外链。两样都没有才归到这一档。

需要注意的是分类页的noindex只能写在页面上或者响应头里,出口地址那种没有head标签的资源就只能靠响应头,两者别搞混。

第二档:空的、但导航上还挂着链接

这一档先改导航,把链接摘掉,再按第一档处理。样本里有44个分类属于这一档,它们是唯一会被真实用户撞上的一类,优先级最高。

第三档:有货、但既不在导航也不在sitemap

这一档才是值得抢救的。它有真实内容,只是没有任何一条路通向它。做法是在相关的分类页之间加交叉链接——Shopify的交叉分类怎么做不踩重复内容的坑那篇有完整的写法,核心是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 应该出现。分面导航治理那套方案里的抓取预算监控可以直接复用,看Search Console的抓取统计里分类页那一类的请求数有没有降下来。

我在这次测量里踩到的三个坑

都不是小坑,每一个都会让结论差出一个数量级。

sitemap把语言版本也算了一份

58个站里有14个的sitemap索引里挂着 /es//de/ 这类语言分卷。直接把所有分卷的地址并起来,wusthof的商品数会变成736——444个英文的加上292个西班牙语的,而后者的handle是翻译过的,看起来就像另一批货。ice-watch更夸张,分类数被算成368,出口明明只有118。

修法是按分卷地址里的语言前缀拆开,只取根语言那一份。凡是做多语言站的清单比对,第一步就该问一句:这份清单里是不是同一件东西被算了好几遍。

静态HTML抓不全首页导航

58个站里11个渲染之后分类链接更多,gymshark从0变成92。但反过来也有8个站渲染后比静态还少——菜单还没等脚本挂上去就被读走了。两个通道都会漏,最终口径只能取并集,而且要清楚这仍然是下界。相关的坑在首页空壳那次实测里也遇到过一次。

把链接条数当成分类数

中途我一度以为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在这件事上不可靠。

权威参考资料

分享到
标签
版权声明

本文标题:《分类页开了19405个,首页只点得到一成七》

本文链接:https://zhangwenbao.com/collection-three-lists-mismatch-audit.html

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

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