解析器启动,代码没有崩溃,数据也在返回——但价格是美元而不是卢布,文本是英文的, 而且商品与来自俄罗斯的活跃用户看到的商品不同。这是解析中最常见和令人沮丧的问题之一: 从技术上讲,一切正常,但内容“不是那个”。我们来分析一下这是为什么,以及如何构建 请求,以获取您所需的页面版本。
症状:如何判断解析器看到的不是正确版本
在修复问题之前,正确诊断它是很重要的。有三种典型情况导致解析器获取的数据与普通 浏览器用户看到的不同:
- 内容语言不匹配——您期望看到俄文文本,但返回的是英文或 乌克兰文的页面。
- 货币和价格不同——网站显示的价格是美元或欧元,而在来自俄罗斯的 浏览器中您看到的是卢布,或者数字根本不同(区域定价)。
- 商品/内容目录不同——商品的可用性、促销、整个展示窗都依赖于 网站“看到”的区域。
原因几乎总是三种之一(或它们的组合):Accept-Language头部、
缺失或错误的cookie,或者请求的IP地址的地理位置。我们将逐一分析每个原因。
Accept-Language:服务器如何选择响应语言
浏览器在每个请求中发送Accept-Language头部,
其中列出了用户的首选语言及其权重(q值)。以下是Chrome在俄语区域发送的实际示例:
Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
解析库(requests、httpx、scrapy)默认情况下要么根本不发送此头部,要么发送类似
*/*的内容。
在这种情况下,服务器要么返回默认语言(通常是英语),要么根据IP确定语言——
这时地理部分就发挥作用,下面将对此进行说明。
重要的细节:许多网站使用“Accept-Language + IP地理位置”的组合,而不是单独使用其中之一。 也就是说,即使您发送了正确的语言头部,但请求来自其他国家的IP,网站仍然可能 将您切换到该区域的英语或本地版本。
货币和区域:网站如何获取价格
货币几乎从不直接通过Accept-Language头部确定。通常使用以下三种机制之一(或它们的组合):
- GeoIP数据库——服务器查看IP来自哪个国家,并在首次访问时自动 插入相应的货币和区域。
- 之前选择的区域的cookie——如果用户曾经手动选择过国家和货币, 网站会将其保存在cookie中,并不再检查IP。
- URL参数或子域——一些平台使用显式标记,例如
?country=ru或ru.example.com。
在实践中,如果您在解析网上商店时看到价格是美元而不是卢布,80%的情况下问题不在 头部,而在于请求的IP地址。网站只是“看到了”非俄罗斯的IP,并插入了默认的 国际展示。
地理cookie:网站如何记住选择的区域
一旦网站确定了您的区域(通过IP或在“选择您的城市”横幅上手动选择),它会将此决策
保存到cookie中——通常命名为
region,
geo_city,
currency或
locale。
之后,所有带有此cookie的请求都将根据保存的区域进行处理——即使IP突然改变。
这为解析器创造了一个陷阱:如果您一次获得了“错误”的版本并保存了会话cookie, 所有后续请求将重复同样的错误,即使您修复了头部或代理。因此,在诊断时,请始终 检查使用干净的会话进行解析——没有来自先前运行的保存的cookie。
同样机制的另一面是有用的:如果您知道所需cookie的名称及其在目标区域的正确值 (例如,在所需位置的浏览器DevTools中查看),可以在请求中强制设置此值,而不更改IP。 这适用于仅通过cookie标志确定区域的网站,但如果服务器在每个请求中重新检查IP与 GeoIP数据库的匹配,则无效。
IP地址和代理在确定区域中的作用
GeoIP定位是网站了解请求实际来源的最可靠方法,因为头部和cookie可以伪造,而IP地址 是无法伪造的(只能替换为另一个真实的)。因此,为了稳定地获取“正确”的区域版本 页面,仅有HTTP头部是不够的——需要一个确实属于所需国家的IP。
在IP地址类型之间存在显著差异:
- 数据中心IP——GeoIP数据库通常能正确识别其国家,但许多大型 网站(尤其是市场和防止机器人服务)将数据中心的IP范围标记为可疑,并可能显示 削减或默认版本的内容,而不考虑地理位置。
- 住宅IP——属于真实的提供商和物理地址,因此GeoIP更准确地确定区域, 网站将请求视为来自该国家/城市的普通用户。
- 移动IP——绑定到特定国家的移动运营商,这对处理特定国家的 移动和桌面流量的网站和应用特别重要。
对于像Wildberries、Ozon或Avito等特定城市的价格监控任务,最适合使用 住宅代理——它们提供 与真实区域绑定的IP,GeoIP数据库正确识别国家和城市,而不会替换为默认的国际展示。
实践:在Python中构建正确的请求
我们将构建一个同时解决所有三个问题的请求:发送正确的Accept-Language, 使用带有所需cookie的干净会话,并通过所需区域的IP进行请求。
import requests
proxies = {
"http": "http://user:[email protected]:8080",
"https": "http://user:[email protected]:8080",
}
headers = {
"Accept-Language": "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/124.0.0.0 Safari/537.36",
}
cookies = {
"region": "ru",
"currency": "RUB",
}
session = requests.Session()
response = session.get(
"https://example.com/catalog",
headers=headers,
cookies=cookies,
proxies=proxies,
timeout=15,
)
print(response.status_code)
print(response.text[:500])
这段代码中的几个重要点:
- 使用
requests.Session(), 而不是单个requests.get(), 以便在需要时服务器可以设置额外的cookie,并在同一解析会话的请求之间保持它们。 - cookie的值
region和currency是条件的, 它们的真实名称和值需要在目标网站的DevTools(应用程序选项卡→cookie)中查看。 - 代理必须确实位于所需国家——否则即使头部和cookie正确,服务器在重新确定地理位置时也可能会覆盖它们。
JS网站:Playwright和头部/cookie管理
如果网站通过JavaScript渲染内容(价格在页面加载后通过单独请求加载), 简单的requests请求是不够的——需要无头浏览器。在Playwright中,区域、语言和代理 在浏览器上下文级别设置:
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
context = browser.new_context(
locale="ru-RU",
timezone_id="Europe/Moscow",
proxy={
"server": "http://gate.proxycove.com:8080",
"username": "user",
"password": "pass",
},
)
context.add_cookies([
{"name": "region", "value": "ru", "domain": "example.com", "path": "/"},
{"name": "currency", "value": "RUB", "domain": "example.com", "path": "/"},
])
page = context.new_page()
page.goto("https://example.com/catalog")
page.wait_for_selector(".price")
print(page.content()[:500])
browser.close()
请注意timezone_id参数——
许多网站还会将浏览器的时区与区域预期的时区进行核对,时区不一致(例如,IP来自俄罗斯,
而浏览器的时区是美国的)本身可能会被反机器人系统视为可疑请求,即使语言和货币在形式上是正确的。
常见错误和启动前的检查清单
在将解析器投入生产之前,请检查一个简短的检查清单——这可以节省几个小时的调试时间:
- ✅ Accept-Language头部已设置并符合预期区域。
- ✅ 会话是干净的——cookie没有从先前失败的请求中继承。
- ✅ 代理的IP物理上位于所需国家(在解析之前通过任何geo-IP检查器进行检查)。
- ✅ User-Agent符合真实浏览器,并且不包含无头模式的迹象。
- ✅ 浏览器的时区和区域(对于Playwright/Selenium)与IP所在国家一致。
- ✅ 如果网站使用手动选择区域的横幅——该选择的cookie手动传递。
另外要提到的是代理的轮换:如果您在每个请求中更改IP,而会话cookie保持不变, 网站可能会看到“区域A的cookie,但区域B的IP”的不一致,并重置会话。对于价格监控任务, 最好将一个IP固定在特定区域的整个解析会话中,而不是在数据收集过程中轮换它。
选择哪种类型的代理来完成任务
代理类型的选择直接影响网站确定您的区域的准确性,并且不会怀疑自动化。以下是 针对典型的区域版本网站解析任务的比较:
| 代理类型 | 地理定位准确性 | 何时使用 |
|---|---|---|
| 数据中心代理 | 中等,国家正确,但IP可能被标记为“非住宅” | 解析没有严格反机器人保护的网站,高速和大量请求 |
| 住宅代理 | 高,甚至到城市级别 | 监控市场的价格、区域内容、绕过GeoIP检查 |
| 移动代理 | 高,加上移动运营商的标记 | 特定国家的移动流量和桌面流量处理不同的网站和应用 |
如果任务是监控来自不同城市的市场目录和价格,住宅代理通常会提供最可预测的结果: GeoIP数据库看到真实的住宅地址,而不是某些网站用不同逻辑处理的数据中心范围。
结论
“解析器看到的不是页面的正确版本”问题几乎总是由三个因素组成:Accept-Language头部, 它确定首选的响应语言;cookie,它们记住之前选择的区域和货币;以及IP地址的地理位置, 服务器在首次访问时根据该地址确定请求的国家。为了获取活跃用户看到的确切网站版本, 需要同时同步这三个参数,而不是单独修复它们。
如果您定期解析区域版本的网站,监控市场上竞争对手的价格或从不同国家收集数据, 建议从选择合适的IP开始——其他设置(头部、cookie、时区)围绕它进行构建。为了准确 进入所需区域,建议尝试住宅代理, 它们提供可预测的地理定位,并将获取默认国际版本网站而不是本地版本的风险降至最低。