SEO 伪装(cloaking)是指向搜索引擎展示一个版本的页面,而向真实用户展示另一个版本。爬虫拿到的是干净、关键词丰富、能获得排名的页面;点击进来的访客看到的却是别的内容,常见的是重定向、另一套优惠,或者直接就是垃圾内容。Google 已将伪装列入其垃圾内容政策,被发现采用伪装的网站可能会丢失单个页面乃至整个域名的排名。
大多数团队是从防守一方接触到伪装的:被黑的网站在站长从未见过的医药或博彩关键词上获得了排名,或者竞争对手的排名页面与搜索摘要所承诺的内容不符。无论哪种情况,发现伪装本质上都是一个 SEO 监控问题:你需要以每一类访客的视角查看页面,然后进行比较。
什么算作伪装
Google 的定义着眼于意图:为了操纵排名、误导用户,而向用户和搜索引擎呈现不同的内容。它给出的示例包括:向爬虫提供关于旅游目的地的页面,而访客看到的是关于折扣药品的页面;以及仅在请求方是搜索引擎时插入文本或关键词。
其机制始终相同。服务器或页面上的脚本会根据请求者看起来是谁,来决定发送什么内容。它所依据的信号包括:
- 用户代理。 粗糙的做法:凡是声明为 “Googlebot” 的请求都拿到干净页面。
- IP 地址。 谨慎的做法:来自 Google 公布的爬虫 IP 段、并通过反向 DNS 验证的请求才拿到干净页面,因此仅伪造用户代理无法解锁。
- 引荐来源。 从 Google 搜索结果页进入的访客会被重定向;直接输入 URL 的人(包括站长本人)看到的则是正常网站。
- 地点和网络。 来自目标国家、使用家庭网络的访客会收到恶意内容;办公网络、云和数据中心 IP 段则拿到干净版本,因为审核人员和安全扫描器正是来自这些地方。
- 设备。 有些方案只重定向移动端访客,因为他们就是在移动端变现的。
大多数真实案例会组合使用其中两三种信号,这也是为什么只在自己工位上检查一次,通常什么也发现不了。
什么不算伪装
许多正当的配置也会向不同访客返回不同的响应。Google 表示,只要爬虫看到的内容与同等情况下的用户所见一致,这些做法就没有问题:
- 按地理位置和语言进行个性化。 向德国访客以欧元显示价格不属于伪装。但如果对 Googlebot 的处理方式与同一地点的用户不同,那就是伪装。我们关于本地化 Google 搜索结果的指南介绍了地点如何改变用户看到的内容。
- 付费墙和受限内容。 Google 专门为付费墙内容制定了结构化数据规范,正是为了让发布商可以让爬虫看到完整文章,而不被视为伪装。
- 针对特定设备的布局。 只要主要内容相同,移动端和桌面端使用不同的标记是可以的。
- 为爬虫单独渲染。 向爬虫提供预渲染的 HTML 曾被推荐为应对大量 JavaScript 的变通方案。Google 现在称其为变通方案而非长期解决方案,但只要内容一致,就不算伪装。
判断每种情况的标准都是同一个问题:处于爬虫位置的真实用户,能否获得相同的内容?
为什么不能只从一个地方检查
伪装页面的设计目标,就是让最有可能去检查它的那些人看到干净的内容。这会给你带来三个盲点:
- 你本身就是被排除的受众。 如果你在登录状态下、在办公室里,或者通过直接输入 URL 来检查自己的网站,基于引荐来源的黑客代码永远不会现身。站长往往是从 Search Console 或客户那里才得知问题的。
- 你无法成为 Googlebot。 发送 Googlebot 用户代理只能发现粗糙的伪装。任何会验证爬虫 IP 的方案都会把你当作普通用户。
- 你所在的市场或网络不对。 一个只针对某个国家、使用家庭网络的移动端访客才触发的方案,从另一个国家的云服务器上是看不到的。
因此,检测本质上是一种比较,需要从足够多的观测点运行,以覆盖伪装方所过滤的各种条件。
检测流程
第 1 步:先获取 Google 的视角。 在 Search Console 中,URL Inspection 工具的实时测试会从 Google 自己的基础设施以 Googlebot 身份抓取页面,并显示渲染后的 HTML 和截图。对于不属于你的页面,Rich Results Test 可以做同样的事。这是查看爬虫版本的唯一可靠方式,因为请求来自真实的 Googlebot IP。
第 2 步:收集用户视角。 以普通访客身份抓取同一个 URL,每次只改变一个条件:
| 变体 | 用户代理 | 引荐来源 | 网络 |
|---|---|---|---|
| 基准 | 桌面浏览器 | 无 | 你的办公网络 |
| 来自搜索 | 桌面浏览器 | google.com 搜索结果页 | 你的办公网络 |
| 移动端来自搜索 | 移动浏览器 | google.com 搜索结果页 | 目标国家的家庭 IP |
| 桌面端来自搜索(目标市场) | 桌面浏览器 | google.com 搜索结果页 | 目标国家的家庭 IP |
| 粗糙爬虫检查 | Googlebot 字符串 | 无 | 你的办公网络 |
家庭 IP 这几行正是住宅代理发挥作用的地方:它提供你所测试国家的家庭网络连接,使请求看起来就像伪装方案正在等待的那类访客。请让区域设置、时区和语言与出口国家保持一致,具体做法见我们关于匹配代理地理位置、时区和区域设置的指南,否则设计精良的方案会把你识别为异常访客。
第 3 步:比较关键部分。 由于令牌和时间戳的存在,任意两次请求的原始 HTML 都会不同。应比较那些会影响排名或访客体验的部分:
- 重定向后的最终 URL,以及重定向链中的每一跳;
- 标题、meta 描述、canonical 和 robots 指令;
- 正文内容,经过规范化并计算哈希;
- 出站链接,尤其是指向陌生域名的链接。
第 4 步:重复检查。 黑客代码和竞争对手的方案往往只对一部分访问触发,或只在特定时段触发。一次干净的结果只是薄弱的证据。在得出页面干净的结论之前,请在不同出口和一天中的不同时段多次运行这套矩阵。
下面是一个最简化的比较脚本。将 PROXY_URL 设置为带国家定向的住宅网关,并为你关注的每个市场添加更多变体:
import hashlib, os, re
import requests
URL = "https://example.com/some-page"
DESKTOP = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0 Safari/537.36"
MOBILE = "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"
GOOGLEBOT = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"
SERP = "https://www.google.com/"
RESI = {"http": os.environ["PROXY_URL"], "https": os.environ["PROXY_URL"]}
VARIANTS = {
"baseline": dict(ua=DESKTOP, ref=None, proxies=None),
"from_search": dict(ua=DESKTOP, ref=SERP, proxies=None),
"mobile_market": dict(ua=MOBILE, ref=SERP, proxies=RESI),
"desktop_market": dict(ua=DESKTOP, ref=SERP, proxies=RESI),
"googlebot_ua": dict(ua=GOOGLEBOT, ref=None, proxies=None),
}
def tag(html, pattern):
m = re.search(pattern, html, re.I | re.S)
return m.group(1).strip() if m else ""
def fingerprint(ua, ref, proxies):
headers = {"User-Agent": ua, "Accept-Language": "en-US,en;q=0.9"}
if ref:
headers["Referer"] = ref
r = requests.get(URL, headers=headers, proxies=proxies, timeout=30)
html = r.text
text = re.sub(r"<script.*?</script>|<style.*?</style>|<[^>]+>", " ", html, flags=re.S)
text = re.sub(r"\s+", " ", text).strip().lower()
return {
"final_url": r.url,
"hops": [h.headers.get("Location", "") for h in r.history],
"title": tag(html, r"<title[^>]*>(.*?)</title>"),
"canonical": tag(html, r'<link[^>]+rel=["\']canonical["\'][^>]+href=["\']([^"\']+)'),
"robots": tag(html, r'<meta[^>]+name=["\']robots["\'][^>]+content=["\']([^"\']+)'),
"text_hash": hashlib.sha256(text.encode()).hexdigest()[:12],
}
results = {name: fingerprint(**v) for name, v in VARIANTS.items()}
base = results["baseline"]
for name, res in results.items():
diffs = [k for k in res if res[k] != base[k]]
print(f"{name:15} {'SAME' if not diffs else 'DIFFERS: ' + ', '.join(diffs)}")
仅 text_hash 不同可能只是无害的个性化。不同的 final_url、新增的重定向跳转,或者只对搜索访客出现的标题,才是需要深入调查的模式。然后再将用户视角与 URL Inspection 实时测试得到的 HTML 进行比较。
发现伪装后该怎么做
如果是你自己的网站, 首先应将其视为安全事件。如果你从未在网站上做过此类设置,那么基于引荐来源和 IP 的伪装几乎总是意味着网站已被入侵:服务器规则被注入、插件或主题被篡改,或者模板中被加入了脚本。删除这些代码,堵住让其进入的漏洞;如果 Google 已采取人工处置措施,再在 Search Console 中申请复审。之后从相同的市场重新运行比较矩阵,确认问题已经消除。
如果是竞争对手的网站, 先取证再举报。从 Rich Results Test 获取爬虫版本,记录各个用户版本及其时间戳、出口国家和设备,并保存完整的重定向链。Google 通过其搜索质量举报表单受理垃圾内容举报。对于付费搜索中的同类行为,我们关于识别伪装和地理定向广告的指南介绍了广告方面的做法。
持续监控。 如果入侵入口没有修复,黑客代码还会卷土重来,而且往往会出现在排名最好的页面上。每周从为你带来自然流量的国家,对排名靠前的着陆页运行一次检测矩阵,是一种低成本的早期预警。
常见问题
SEO 伪装违法吗?
这通常不是法律问题,而是违反搜索引擎政策的问题。Google 已将其列入垃圾内容政策,可以对使用伪装的页面降低排名或将其移除。如果伪装用于掩盖诈骗或恶意软件,内容本身可能还会涉及其他法律。
按国家显示不同内容算伪装吗?
本身不算。按国家本地化价格、语言或优惠是很正常的做法。只有当爬虫受到的对待与处于相同情况的用户不同时,才构成伪装。
把用户代理改成 Googlebot 能检查出伪装吗?
只能检查出粗糙的伪装。谨慎的方案会验证爬虫的 IP,因此伪造的用户代理会被当作普通访客对待。请使用 Search Console 的 URL Inspection 实时测试或 Rich Results Test 来查看 Google 的真实视角。
为什么检测伪装需要住宅 IP?
许多方案只向目标市场的普通访客展示恶意内容,而向办公网络、云和数据中心地址展示干净页面。从该市场的家庭网络进行检查,才能看到这些访客实际看到的内容。
总结
伪装会避开最有可能检查它的人,因此只在自己工位上看一眼几乎证明不了什么。用 Google 自己的工具获取其视角,在重要市场中跨引荐来源、设备和家庭网络收集用户视角,比较最终 URL、标题和正文内容,并在判定页面干净之前重复检查。如果是你自己的网站,应将发现的问题视为入侵事件,并修复入侵入口。如需长期跟踪页面在多个地点的展示情况,请参阅我们的地理网格排名跟踪指南。