你通过德国的出口打开一个页面,看到的是英文。同事打开同一个地址,得到的却是美国商店页面。你们两个用的都是正确的代理,那到底发生了什么?网站很少只凭一个信号来判断你的国家。它们会综合多个信号,而且每个网站组合这些信号的顺序都不一样。如果你在做本地化 QA或监控本地页面,了解这些信号能省去不少困惑。
本指南将介绍网站使用的四种信号、一个经过实测的真实网站组合方式示例,以及如何检查你关心的某个网站。
四种信号
| 信号 | 通常决定什么 | 你如何控制它 |
|---|---|---|
| IP 地址 | 国家,有时还有语言 | 代理的出口国家 |
| Accept-Language 标头 | 某个国家内的语言 | 你的浏览器或客户端设置 |
| URL | 其所指定的内容,优先于其他一切 | 你请求的地址 |
| cookie 或已保存的选择 | 你上次选择的内容 | 清除 cookie,或使用全新会话 |
有些网站在服务器端完全不使用这些信号,而是展示一个让你自行选择的页面。
真实网站的实际表现
我们在 2026 年 11 月 6 日通过不同国家的住宅代理出口、配合不同的浏览器语言,加载了几个知名页面,并分别确认了每个出口国家。脚本很短,只需要 requests。凭证来自环境变量。
from __future__ import annotations
import os
import re
import requests
GATEWAY = "p.shifter.io:443"
USER, PASSWORD = os.environ["PROXY_USER"], os.environ["PROXY_PASS"]
BROWSER = ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/130.0 Safari/537.36")
def visit(url, country, language):
"""Load a URL from an exit in one country with one browser language."""
proxy = f"http://{USER}-country-{country}:{PASSWORD}@{GATEWAY}"
s = requests.Session()
s.proxies = {"http": proxy, "https": proxy}
s.headers.update({"User-Agent": BROWSER, "Accept-Language": language})
r = s.get(url, timeout=40)
lang = re.search(r'<html[^>]*\blang=["\']?([\w-]+)', r.text, re.I)
return r.url, lang.group(1) if lang else None
CASES = [
# url, exit country, Accept-Language
("https://www.netflix.com/", "us", "en-US"),
("https://www.netflix.com/", "de", "en-US"),
("https://www.netflix.com/", "de", "de-DE"),
("https://www.netflix.com/", "br", "en-US"),
("https://www.google.com/", "us", "en-US"),
("https://www.google.com/", "de", "en-US"),
("https://www.google.com/?hl=en", "de", "en-US"),
("https://www.apple.com/de/", "us", "en-US"),
("https://www.ikea.com/", "de", "de-DE"),
]
if __name__ == "__main__":
for url, country, language in CASES:
for attempt in range(3):
try:
final, lang = visit(url, country, language)
break
except requests.RequestException:
final, lang = "error", None
asked = url.replace("https://www.", "")
got = final.replace("https://www.", "")
print(f"{asked:22} exit {country.upper()} {language:6} -> {got:22} lang={lang}")
输出结果,展示了请求的地址、出口国家和浏览器语言、实际到达的页面以及该页面的语言:
netflix.com/ exit US en-US -> netflix.com/ lang=en
netflix.com/ exit DE en-US -> netflix.com/de-en/ lang=en
netflix.com/ exit DE de-DE -> netflix.com/de/ lang=de
netflix.com/ exit BR en-US -> netflix.com/br-en/ lang=en
google.com/ exit US en-US -> google.com/ lang=en
google.com/ exit DE en-US -> google.com/ lang=de
google.com/?hl=en exit DE en-US -> google.com/?hl=en lang=en-DE
apple.com/de/ exit US en-US -> apple.com/de/ lang=de-DE
ikea.com/ exit DE de-DE -> ikea.com/ lang=en
四个网站,四种不同的行为。
Netflix 同时使用 IP 和语言。 出口决定了国家路径,浏览器语言决定了变体:德国出口配合英文浏览器得到 /de-en/,配合德文浏览器得到 /de/。巴西出口配合英文浏览器得到 /br-en/。
Google 保持同一个 URL,但依据 IP 来决定语言。 即使浏览器是英文的,德国出口依然得到德文页面。在 URL 中加上 ?hl=en 后切换为英文,说明 URL 的优先级高于 IP。
Apple 让 URL 来决定一切。 美国出口请求 /de/ 时得到的是德国站点。IP 没有将其重定向到任何其他地方。
IKEA 完全没有重定向。 德国出口配合德文浏览器,得到的依然是英文的国际页面,这说明选择权留给了访问者自己。
这对你的检查工作意味着什么
- 同时设置出口和语言。 用英文浏览器测试德国市场,可能得到真实访客永远不会看到的组合,正如 Netflix 那一行所示。时区也要匹配,因为有些网站会检查时区。
- 记录最终的 URL。 你请求的地址和你到达的页面常常不一样。把两者都记下来,这样重定向就不会被忽略。
- 每个市场都用全新会话开始。 之前访问留下的 cookie 可能会覆盖 IP 的判断。为每个国家使用新的会话。
- 不要只信任 URL。 在像 Google 这样的网站上,同一个 URL 会按 IP 展示不同内容。在像 Apple 这样的网站上,URL 决定一切,IP 无关紧要。测试一下你面对的是哪一种。
- 根据你想扮演的访客身份来选择出口。 我们关于选择出口国家的文章讲述了地理位置何时重要、何时不重要。
如果你是网站运营方
地理重定向可能对你不利。Google 的指导建议是,不要根据你推测的用户语言自动将其从一个语言版本重定向到另一个,因为这可能导致用户和搜索引擎无法访问到每一个版本。它还指出,Googlebot 通常从美国的 IP 地址进行抓取,且不发送 Accept-Language 标头,因此根据地理位置调整内容的网站,可能无法让每个版本都被收录。
更稳妥的做法是上面大多数网站都在以某种形式采用的模式:按国家或语言设置独立的 URL,基于访客信号给出建议,并提供便捷的切换方式。
结论
网站判断你所在地的方式,是 IP、浏览器语言、URL 和记忆这几种信号的组合,而每个网站组合的方式都不同。当页面显示的国家不对时,先检查这四个信号,再去怀疑代理;而在测试时,一次只改变一个信号,这样你才能知道网站到底依据哪一个来判断。
来源与参考资料
- Google Search Central, Managing multi-regional and multilingual sites: developers.google.com
- Google Search Central, How Google crawls locale-adaptive pages: developers.google.com