筛选页地址里带 color、size、sort 三个参数,用户随便换顺序就能组合出六种写法,页面 canonical 直接输出当前 URL,索引里同一批商品被拆成六份重复记录。
一开始怀疑是「分页参数和筛选参数混在一起,canonical 连页码也带上了」,查了一圈,方向不对。
原因不止一个,得分开看。canonical 用当前请求地址直接输出,没有做参数排序。还有一种是六种顺序都能返回 200,没有统一跳转。
少数情况下是CDN 缓存键按原始 query 计算,六份内容各缓存一份。
上来先对比两种参数顺序的 canonical
curl -s "https://www.example.com/list/?color=red&size=m" | findstr /i canonical
再往下确认另一种顺序返回的状态码
curl -s -o NUL -w "%{http_code}\n" "https://www.example.com/list/?size=m&color=red"
接着在服务端对参数排序后输出 canonical
curl -s "https://www.example.com/list/?size=m&color=red&sort=asc" | findstr /i canonical
给重复组合加 301 归一
curl -sI "https://www.example.com/list/?color=red&size=m" | findstr /i location
中途换过一次思路,把范围缩到最小的那一层,反而快了。
恢复的判定其实很直接。参数排序统一后,六种写法归到一个 canonical,重复记录在三周内合并成一条。
容易忽略的是,canonical 不能直接照抄当前 URL,参数顺序、大小写、尾斜杠这些都要先归一。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
