外贸独立站多语言版本被判重复先别删页面。按 Google 官方文档口径只有网页主要内容没翻译时本地化版本才会被当作重复网页标注写错则整组 hreflang 会被忽略。下面4处按顺序查。去年接手过一个站英文版和德语版产品页主内容是各自写的德语版照样进不了索引站长后台提示重复网页。前后看过七八个类似的站现象都长得差不多成因分两类一类是主内容确实只做了模板翻译另一类内容没问题、标注本身被搜索引擎丢掉了。这两类的修法完全不同混着做会白改好几轮。一、先分清是主内容没本地化还是标注被忽略Google 在本地化版本文档里写了两句需要连起来读的话。一句是如果网页的主要内容未经翻译则该网页的本地化版本仅会被视为它的重复网页。另一句是如果两个网页没有互指系统将会忽略相关标记。前一句管内容后一句管标注。所以动手前先回答一个问题被判重复的那一版主内容到底翻没翻。只翻译了导航和页脚、主体还是原文落在前一句覆盖的范围里先补内容主内容是独立写的问题在标注再往下查。围绕外贸独立站怎么做的讨论里这两件事经常被合成一句多语言容易被判重复其实是两条独立的问题线。用 Search Console 的网址检查看具体地址常见三种结果。网址检查显示说明什么处理方向重复网页Google 选择了不同规范网址组内另一版被选为对外展示版本先确认它选的是不是你要的那一版再核标注重复网页未编入索引这一版被判与组内其他版雷同且没被选中核对主内容有没有本地化再补标注已编入索引这一版状态正常换组内下一个语言版本继续查网址检查里还能展开看 Google 抓取到的 HTML。这个视图的用处是确认标注是否真的出现在服务端返回的 head 里。如果后台编辑器里能看到标注、抓取到的 HTML 里没有那问题不在写法上在渲染时机上往下查标注也没有意义。二、标注有三种落地方式官方说它们等效Google 官方文档列出的是三种方式HTML 的 head 标签、HTTP 响应标头、XML 站点地图。文档的表述是这三种方法从 Google 的角度看等效选最适合站点的那一种。同一段还提醒可以三种同时用但对搜索表现没有好处管理三套实现要难得多。这句话值得单独记下来。实操里出问题的站很多是因为模板里写了一套 head 标注站点地图生成器又输出了一套两套内容对不上等于自己给搜索引擎发了矛盾信号。选一种写完整语言版本增减时只改这一处。落地位置能否覆盖 PDF 等非 HTML 文件增减一个语言版本要动什么适合的站页面 head 的 link 标签不能模板改动全站重新发布语言数少、模板统一的站HTTP 响应标头能服务端或 CDN 规则改动有本地化 PDF、能自己控服务器的站XML 站点地图能重新生成一个文件语言和页面数量多、希望集中管理的站方式一HTML head 里的 link 标签三个语言版本为一组组内每个页面的 head 里放同一套标注包含自己、两个兄弟版本以及兜底页。下面用螺栓产品页举例。link relalternate hreflangen hrefhttps://example.com/en/products/m8-bolt/ / link relalternate hreflangde hrefhttps://example.com/de/produkte/m8-bolt/ / link relalternate hreflanges hrefhttps://example.com/es/productos/m8-bolt/ / link relalternate hreflangx-default hrefhttps://example.com/products/m8-bolt/ /这四行要原样出现在英文版、德语版、西语版三个页面的 head 里一行不差。德语版用的是/de/produkte/这样的本地化 URL不是英文 URL 加语言前缀。示例域名换成真实域名之前先想清楚一件事标注里的 href 必须和这一页的规范地址逐字符一致协议、主机名、结尾斜杠三样都要对上/fr和/fr/在搜索引擎眼里是两个地址。方式二HTTP 响应标头这套写法对 PDF 规格书、参数表这类没有 HTML head 的文件是唯一可行的方式。响应头里用 Link 字段按同样的顺序列出来。Link: https://example.com/en/products/m8-bolt/; relalternate; hreflangen, https://example.com/de/produkte/m8-bolt/; relalternate; hreflangde, https://example.com/es/productos/m8-bolt/; relalternate; hreflanges验证不用猜直接看线上返回的响应头。注意要取线上的不是本地配置文件。$ curl -sI https://example.com/en/products/m8-bolt/ | grep -i ^link: Link: https://example.com/en/products/m8-bolt/; relalternate; hreflangen, ...方式三XML 站点地图站点地图方式把标注集中到一个文件里语言版本增减只改一处出错面最小。先在 urlset 上声明 xhtml 命名空间再让每个 url 节点把组内所有版本列全同样包含自己。?xml version1.0 encodingUTF-8? urlset xmlnshttp://www.sitemaps.org/schemas/sitemap/0.9 xmlns:xhtmlhttp://www.w3.org/1999/xhtml url lochttps://example.com/en/products/m8-bolt//loc xhtml:link relalternate hreflangen hrefhttps://example.com/en/products/m8-bolt// xhtml:link relalternate hreflangde hrefhttps://example.com/de/produkte/m8-bolt// xhtml:link relalternate hreflanges hrefhttps://example.com/es/productos/m8-bolt// xhtml:link relalternate hreflangx-default hrefhttps://example.com/products/m8-bolt// /url !-- 德语版、西语版各写一个同样的 url 节点四行 xhtml:link 完全相同 -- /urlset三、4处最容易出错的地方第一处回指有没有断官方原文是如果两个网页没有互指系统将会忽略相关标记。断掉的那一对会被丢掉组内其余互指的对仍然处理。这句规则后面还跟着一句解释说这么定是为了防止别的网站随意加一个标记把自己的页面声明成你页面的备用版本。工程上的解法不是逐对去核对而是让同一组标注从同一个数据源生成。三个语言版本的 head 里那一套 link 标签应当逐字节相同走站点地图方式时每个 url 节点的 xhtml:link 子节点也应当完全相同。手工维护九个页面八个写对、一个漏了一行整组的关系就断在漏掉的那一处而且页面打开看还是正常的。第二处自己有没有被列进去x-default 有没有官方原文是每个语言版本都必须列出其自身以及所有其他语言版本。三个语言版本加一个兜底页每个页面的 head 里应当是四行不是三行。少的那一行往往是自己这类错误在 Search Console 里看不到提示但整组标注会因此不被采纳。x-default 是给语言和地区都与站点不匹配的访问者准备的兜底页。官方说明它专为语言选择器页面设计所以最合适的位置就是那个让用户自己选语言的页面。这句话反过来说也成立x-default 不要机械地指向首页。产品页所在的那一组里兜底页指向一个与产品无关的首页等于把找不到匹配语言的用户丢到一个不相关的页面兜底就失去了意义。第三处语言和地区代码的写法官方规则是第一个代码为语言代码采用 ISO 639-1 格式后面跟一个可选的地区代码采用 ISO 3166-1 Alpha 2 格式中间用短划线分隔只支持这两套标准里列出的代码。下面这几类写法都会出问题。常见写法问题在哪应该怎么写en-UKUK 是被预留作他用的代码这部分注解会被忽略en-GBes-419不在 ISO 639-1 与 ISO 3166-1 标准内不支持拆成具体国家代码或只写语言代码 esen_US分隔符用错标准用的是短划线en-USbebe 是白俄罗斯语的语言代码不是比利时面向比利时按语言写 de-BE、fr-BE 或 nl-BEzh-TW写法可用文字由地区推断需要明确文字时写 zh-Hant 或 zh-Hans还有一条容易被误解的官方说明Google 不使用 hreflang 或 HTML lang 属性来判断网页的语言它用算法判断。也就是说 hreflang 不是告诉搜索引擎这页是什么语言的手段它是告诉搜索引擎这一组页面互为语言变体的关系声明。代码写错的后果不是被当成别的语言而是这条关系不被采纳。第四处和 canonical 打架这一处最隐蔽因为两个标签单独看都没写错。每个语言版本的 canonical 应当指向自己一旦德语页的 canonical 指向英文页就等于同时告诉搜索引擎两件相反的事hreflang 说这几页是本地化变体、按用户语言分别展示canonical 说忽略这一页、把它并到那个地址上。两个信号冲突时被合并掉的那一版通常不会再出现在索引里再补 hreflang 也救不回来。Google 的规范网址文档对这件事的要求是使用 hreflang 时应为页面指定同语言的规范网址找不到同语言版本时才退而指向最接近的替代语言版本。落到操作上就是一句话每个语言版本的 canonical 写自己这一版。这类问题在从默认语言自动生成多语言版本的建站系统上出现频率偏高因为规范地址常常由默认站点配置带出来多语言版本跟着继承。查的时候逐个语言版本确认不要只看默认语言那一版就下结论。做独立站SEO 的核对清单里canonical 与 hreflang 这一项建议单独列一行它和收录问题缠在一起时最难分开看。四、把4处合成一个脚本跑完逐页肉眼比对不现实。用 Python 标准库写个检查输入组内任一页面的 URL抓取该页面输出三样东西标注条数、自己有没有被列进去、每一对回指是否成立另外顺带标出不符合 ISO 格式的代码写法。# hreflang_check.py # 用法: python hreflang_check.py https://example.com/en/products/m8-bolt/ import sys, re import urllib.request from html import unescape PAIR_RE re.compile(rhreflang[\]([^\])[\][^\]*href[\]([^\])[\], re.I) VALID re.compile(r^(x-default|[a-z]{2,3}(-[a-z]{4})?(-[a-z]{2})?)$, re.I) def fetch(url): req urllib.request.Request(url, headers{User-Agent: Mozilla/5.0}) with urllib.request.urlopen(req, timeout20) as resp: return resp.read().decode(utf-8, ignore) def parse(html): return [(code, unescape(href)) for code, href in PAIR_RE.findall(html)] def main(url): anns parse(fetch(url)) if not anns: print(未找到标注: url) return codes [code for code, _ in anns] hrefs [href.rstrip(/) for _, href in anns] print(标注条数: %d % len(anns)) print(自指: %s % (已包含 if url.rstrip(/) in hrefs else 缺失)) print(x-default: %s % (已包含 if x-default in codes else 缺失)) for code in codes: if not VALID.match(code): print(代码格式可疑: %s % code) for code, href in anns: if code x-default: continue try: back [h.rstrip(/) for _, h in parse(fetch(href))] except Exception as exc: print(抓取失败: %s (%s) % (href, exc)) continue if url.rstrip(/) not in back: print(回指缺失: %s 没有指回 %s % (href, url)) if __name__ __main__: main(sys.argv[1])脚本只覆盖 HTML head 这一种方式。站点走站点地图或响应头时把抓取与解析两段换掉即可站点地图用xml.etree.ElementTree取 xhtml:link 节点响应头把curl -sI的输出喂给同一个正则。脚本里的域名一律写成 example.com换成真实域名后记得确认rstrip(/)没有把两个不同的地址判成同一个。五、Search Console 已经不提供 hreflang 报错报告了这一点比技术细节更容易踩。网上大量教程还在教打开 Search Console进指定国际目标报告看语言定位那一栏的缺少返回链接。Google 的帮助文档已经写明指定国际目标报告已淘汰Google 会继续支持并使用网页上的 hreflang 标记但这项功能不再提供。也就是说没有替代报告全站级的标注问题不会在 Search Console 里给你列成一张待修清单。现在能用的三类手段网址检查逐页看 Google 抓取到的 HTML自己跑一遍上面的脚本或任意能解析 hreflang 的爬虫按组比对官方文档在调试一节里列了两个第三方工具并注明这些工具不由 Google 维护或检查用之前心里有数。单靠 Search Console 一块面板是查不出标注问题的。六、改完之后的验证顺序改完标注不要只看首页。按这个顺序走一遍把组内每个 URL 在网址检查里各跑一次确认 Google 抓到的 HTML 里标注齐全把站点地图重新提交一次对改动过的页面提交重新抓取然后把每个版本当前的状态、核对日期、改了什么记进同一张表。状态更新有它自己的节奏。改完后几天没动静不代表没生效。隔两三周回查同一批地址有记录才对比得出来。这是独立站搭建交付后最容易被跳过的一步改完不记录下一轮又得从头查一遍。七、几个常被问到的问题标注齐全了某一版还是没被索引。先把两件事分开标注决定的是哪一版展示给谁索引由另一套判定决定。回到第一处那个问题看这一版的主内容是否真的做了本地化内容与其他版本是否只是换了语言。能用 JavaScript 把标注注入进去吗。官方列出的三种方式都落在服务端可见的位置。写在客户端渲染之后才出现的 DOM 里等于把这件事交给渲染时机。用网址检查看 Google 抓到的 HTML 里到底有没有没有就挪到服务端输出。能不能按访问者所在地区或浏览器语言自动跳转到对应版本。官方文档在这件事上给的是明确建议不要自动重定向。原因写在同一页里Googlebot 抓取时通常来自美国请求头里也不设置 Accept-Language自动跳转会让它只能看到一个版本其余版本可能因此发现不了。稳妥做法是每个语言版本各有独立网址、都能直接打开再在页面上放一组指向其他语言版本的超链接让用户自己选。用 Cookie 或浏览器设置切换同一地址上的内容语言同样落在不被推荐的写法里。某个语言版本要下线怎么办。不要只删自己那一页的标注。先把它从组内其他所有页面的标注里去掉再决定这个地址是 301 到同语言的替代页还是保留 410。让别人继续指向一个已经下线的地址那一对被忽略还可能连带影响同组的其他对。只翻译了模板、主内容还是英文要不要标。官方把主要内容用单一语言、只翻译模板列为建议标注的情形之一所以标注该做但它和主内容未翻译时本地化版本会被视为重复网页是两回事。标注解决的是关系声明解决不了主内容没有本地化的问题。改标注要逐个语言版本动 head语言一多工作量会跟着涨。我自己的站用的是 NeoGress多语言版本的标注可以在同一处生成语言增减时改动少一些来回但标注有没有断开、代码写没写对、canonical 有没有打架仍然得按上面4处一条条查工具不解决这件事。你的站是标注写全了还被忽略还是某一版从头到尾没进过索引这两种情况的排查起点不一样评论区说一句你落在哪一种我按你的语言组给核对顺序。
阅读完成 · 觉得有帮助?