如何在2026年抓取Temu商品与价格数据:代理、反爬与隐藏JSON端点全指南

Temu没有公开API,抓取商品与价格数据需在易变的HTML卡片和内部JSON端点之间做出选择。本指南涵盖反爬技术栈、curl_cffi实战代码、住宅代理城市级定位及合规要点。

How to Scrape Temu Product and Price Data in 2026: Proxies, Anti-Bot, and the Hidden JSON
本文目录

抓取Temu商品与价格数据:API端点 vs HTML解析的核心权衡

Temu是目前全球增长最快的电商平台之一,但它没有提供公开的商品或价格API。对于电商数据工程师和价格情报团队来说,这意味着你必须在两条路径之间做出选择:解析易变的HTML商品卡片,或者直接请求Temu内部的JSON端点(如 /api/poppy/v1/search 和商品详情接口)。这两条路径各有利弊,而无论选哪条,你都必须应对Cloudflare反爬体系、签名 anti_content 头以及TLS/HTTP2指纹检测。本指南将系统讲解如何在2026年抓取Temu商品与价格数据,涵盖技术上下文、实战代码、代理配置和合规边界。

核心权衡如下:HTML解析简单但脆弱——Temu频繁更新前端,CSS类名经过哈希处理,今天能用的选择器明天就可能失效;而内部JSON端点返回结构化数据(goods_id、价格、SKU列表等),稳定性更高,但需要构造正确的请求头和签名参数,且更容易触发反爬检测。对于构建Temu价格抓取管道的团队,JSON端点通常是更优选择——前提是你能正确处理反爬挑战。

技术背景:Temu的反爬技术栈

Temu的反爬体系是多层次的,理解每一层是成功抓取的前提。

Cloudflare Turnstile 与 JS Challenge

Temu前端由 Cloudflare Turnstile 保护,这是一个无需用户交互的CAPTCHA替代方案。Turnstile会在页面加载时注入JS挑战脚本,收集浏览器环境信号(Canvas指纹、WebGL参数、navigator属性等),生成一个token。如果你的请求缺少有效token或浏览器指纹不匹配,Cloudflare会返回403或503状态码,并要求完成交互式验证。

签名 anti_content 头

Temu的内部API请求需要携带一个 anti_content 参数(有时也叫 anti_token)。这是一个由前端JS生成的签名令牌,包含时间戳、设备指纹和请求参数的哈希。它的生成逻辑混淆在webpack打包的JS bundle中,逆向难度较高。没有有效的 anti_content,JSON端点会直接返回错误码而非数据。

TLS/HTTP2 指纹检测

这是最容易被忽视的一层。Temu后端会检查TLS握手特征(JA3/JA4指纹)和HTTP2设置帧参数。标准的Python requests 库使用urllib3的TLS栈,其指纹与真实Chrome浏览器差异巨大,即使IP干净也会被识别。根据 RFC 8446 (TLS 1.3) 规范,不同TLS实现在扩展顺序、密码套件列表和椭圆曲线上存在可检测的差异。这就是为什么许多团队用 requests 发请求时,即使配了住宅代理也会被秒封——问题不在IP,而在指纹。

数据中心IP即时拦截

Temu对数据中心IP段的封锁几乎是即时的。AWS、GCP、Azure、DigitalOcean等云厂商的IP段在Cloudflare的IP信誉数据库中标记为高风险。用数据中心代理抓取Temu,首次请求可能成功,但第二次就会被challenge或直接403。住宅代理是强制要求,而非可选优化。

定位数据:嵌入状态与JSON端点

Temu的商品页面和搜索结果页有两种数据获取方式。

方式一:解析嵌入的 __NEXT_DATA__ 状态块

Temu使用Next.js框架,页面HTML中嵌入一个 <script id="__NEXT_DATA__" type="application/json"> 标签,包含序列化的服务端状态。你可以用正则或BeautifulSoup提取这个JSON块,然后解析其中的商品数据。这种方式只需一次HTML请求,不需要构造 anti_content,适合快速原型。

import re, json, requests

html = response.text
match = re.search(r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>', html)
if match:
    data = json.loads(match.group(1))
    goods = data['props']['pageProps']['goods']  # 路径可能随版本变化

缺点:__NEXT_DATA__ 的结构会随Next.js版本和页面类型变化,且并非所有数据都包含在内(SKU级别的库存信息经常缺失)。

方式二:直接请求内部JSON端点

Temu的搜索和商品详情数据背后是以下端点(路径可能随版本微调):

  • 搜索/api/poppy/v1/search(POST,返回商品列表含goods_id、标题、价格、图片URL)
  • 商品详情/api/poppy/v1/goods/detail(POST,返回完整SKU列表、规格、价格层级、库存状态)

这些端点返回结构化JSON,比HTML解析稳定得多,但需要正确的请求头组合和 anti_content 签名。在浏览器DevTools的Network面板中,你可以观察到这些请求的实际参数格式。

哈希CSS类与 data-uniqid 属性

如果不得不解析HTML,注意Temu的CSS类名是哈希生成的(如 r-1qfo8i5),不能依赖语义化类名。更可靠的选择器锚点是 data-uniqid 属性和 data-pid(商品ID)属性。例如:

# XPath 示例
# 商品卡片
//div[@data-uniqid and contains(@class, 'goods')]
# 价格元素
//span[contains(@class,'price')]/span[@data-uniqid]

速率限制阈值与住宅代理的必要性

根据实际测试和社区反馈,Temu对单个IP的请求频率限制大约在每分钟20-40次请求的范围(具体阈值因端点和IP信誉而异)。超过这个阈值会触发Cloudflare的rate-limit challenge,返回429状态码或要求完成Turnstile验证。连续触发会导致IP被临时封禁约10-30分钟

更关键的是:Temu的价格和运费因地区而异。同一商品在美国和中国、甚至美国不同州的展示价格、运费和促销信息都可能不同。这意味着:

  • 你需要使用带有国家/城市级地理定位的住宅代理,例如 -country-US-country-US-city-newyork
  • 数据中心代理不仅会被反爬拦截,即使偶尔成功也无法获取真实的目标市场价格。
  • 移动代理(4G/5G)在某些场景下比住宅代理更不易被封,但延迟更高(通常200-500ms vs 住宅的50-150ms)。

对于构建Temu商品数据API替代方案的团队,建议的架构是:住宅代理池 + 城市级地理定位 + 每IP每分钟控制在15次请求以下 + 自动轮换IP。

代理类型Temu成功率地理定位精度延迟适用场景
数据中心代理<5%10-50ms不推荐
住宅代理(国家级)70-85%国家50-150ms基础价格抓取
住宅代理(城市级)80-92%城市50-150ms区域价格对比
移动代理(4G/5G)85-95%国家/运营商200-500ms高难度反爬场景

实战:用 curl_cffi + ProxyHat 抓取Temu商品页

由于Temu检测TLS指纹,标准 requests 库不可用。我们使用 curl_cffi,它基于libcurl并支持模拟Chrome的TLS/HTTP2指纹。配合ProxyHat住宅代理,完整示例如下:

安装依赖

pip install curl_cffi selectolax

Python抓取代码

from curl_cffi import requests as cffi_requests
import json, re, time, random

# ProxyHat 住宅代理配置 — 城市级地理定位
PROXY = "http://user-country-US-city-newyork:YOUR_PASSWORD@gate.proxyhat.com:8080"

HEADERS = {
    "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",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Referer": "https://www.temu.com/",
}

def fetch_product_page(goods_id: str, session_id: str = None):
    """抓取Temu商品页面并提取 __NEXT_DATA__ JSON"""
    # 使用 sticky session 保证同一IP获取一致的运费/价格
    if session_id:
        proxy = f"http://user-country-US-city-newyork-session-{session_id}:YOUR_PASSWORD@gate.proxyhat.com:8080"
    else:
        proxy = PROXY

    url = f"https://www.temu.com/goods.html?goods_id={goods_id}"

    for attempt in range(3):
        try:
            resp = cffi_requests.get(
                url,
                headers=HEADERS,
                proxies={"http": proxy, "https": proxy},
                impersonate="chrome124",
                timeout=20,
            )
            if resp.status_code == 200:
                return parse_next_data(resp.text)
            elif resp.status_code in (403, 429):
                wait = 2 ** attempt + random.uniform(0, 1)
                print(f"Blocked ({resp.status_code}), retrying in {wait:.1f}s")
                time.sleep(wait)
            else:
                print(f"Unexpected status: {resp.status_code}")
                time.sleep(1)
        except Exception as e:
            print(f"Request error: {e}")
            time.sleep(2 ** attempt)
    return None

def parse_next_data(html: str):
    """从HTML中提取 __NEXT_DATA__ JSON 块"""
    match = re.search(
        r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>',
        html, re.DOTALL
    )
    if not match:
        return None
    return json.loads(match.group(1))

# 执行抓取
data = fetch_product_page("60109951327777", session_id="temu-cart-001")
if data:
    # 提取关键字段(路径因版本而异,需根据实际响应调整)
    store = data.get("props", {}).get("pageProps", {})
    goods = store.get("goods", store.get("product", {}))
    print(json.dumps({
        "goods_id": goods.get("goodsId", goods.get("goods_id")),
        "title": goods.get("goodsName", goods.get("title")),
        "price": goods.get("minPrice", goods.get("price", {}).get("min")),
        "sku_list": goods.get("skuList", [])[:3],  # 截断示例
    }, ensure_ascii=False, indent=2))

截断的示例JSON响应

{
  "goods_id": "60109951327777",
  "title": "Wireless Bluetooth Earbuds Pro Max",
  "price": {
    "min": "12.98",
    "max": "19.99",
    "currency": "USD",
    "original": "29.99"
  },
  "sku_list": [
    {
      "sku_id": "SKU001",
      "spec": "Black",
      "price": "12.98",
      "stock": 3421,
      "thumb_url": "https://img.temu.com/.../black.jpg"
    },
    {
      "sku_id": "SKU002",
      "spec": "White",
      "price": "13.49",
      "stock": 2180,
      "thumb_url": "https://img.temu.com/.../white.jpg"
    },
    {
      "sku_id": "SKU003",
      "spec": "Blue",
      "price": "14.99",
      "stock": 0,
      "thumb_url": "https://img.temu.com/.../blue.jpg"
    }
  ]
}

Sticky Session、重试与分页策略

粘性会话(Sticky Sessions)

当抓取涉及购物车或运费计算时,你需要保证一系列请求来自同一IP(同一地理位置)。ProxyHat支持在用户名中嵌入 -session- 标志来实现粘性会话:

# 粘性会话 — 同一 session ID 在有效期内保持同一出口IP
http://user-country-US-session-temu-cart-001:PASSWORD@gate.proxyhat.com:8080

典型应用场景:先抓取商品详情页,再请求运费接口,最后检查库存——这三步必须来自同一IP同一地区,否则运费和库存数据会不一致。

重试与指数退避

遇到403/429时,采用指数退避重试。基础等待时间为 2^attempt 秒,加上0-1秒随机抖动,避免雷同的请求模式。最多重试3次,超过则记录失败并切换IP。

分页策略

Temu搜索结果采用无限滚动加载,分页参数通常为 pageoffset/limit。建议:

  • 每页请求间隔2-5秒随机延迟。
  • 每抓取10-15页后轮换IP(更换session ID)。
  • 设置最大页数限制(如50页),避免触发深层反爬。
  • 使用 SERP追踪类似的分页管理逻辑来跟踪抓取进度。

ProxyHat代理配置详解

ProxyHat提供住宅、移动和数据中心代理。对于Temu抓取,只推荐住宅代理(城市级地理定位)。以下是关键配置参数:

参数说明
网关gate.proxyhat.com统一入口
HTTP端口8080默认HTTP代理端口
SOCKS5端口1080SOCKS5代理端口
国家级定位-country-US指定出口国家
城市级定位-country-US-city-newyork指定出口城市
粘性会话-session-abc123保持同一出口IP

更多代理位置和定价信息,请访问 代理位置页面定价页面。完整API文档请参考 ProxyHat官方文档

对于大规模Temu价格抓取项目,建议结合 网页抓取用例中的架构模式,使用并发管理器控制同时活跃的会话数在50-100个并发会话左右,配合自动IP轮换。

curl 命令行快速测试

在写Python脚本之前,可以先用curl快速验证代理连通性和页面可访问性:

curl -x "http://user-country-US-city-newyork:PASSWORD@gate.proxyhat.com:8080" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  -H "Accept: text/html,application/xhtml+xml" \
  -H "Accept-Language: en-US,en;q=0.9" \
  "https://www.temu.com/goods.html?goods_id=60109951327777" \
  -o temu_product.html -w "%{http_code} %{time_total}s\n"

注意:curl的TLS指纹与Chrome不同,成功率可能低于curl_cffi。curl仅用于快速验证代理连通性。

常见错误与边界情况

  • 403/503状态码:通常是TLS指纹不匹配或IP被标记。确认使用 impersonate="chrome124" 参数,并检查代理是否为住宅类型。
  • 价格不匹配:同一商品在不同地区显示不同价格。确保代理地理定位与目标市场一致,使用粘性会话避免中途IP切换。
  • __NEXT_DATA__ 缺失:某些页面类型(如登录后的个性化页面)可能不嵌入 __NEXT_DATA__。回退到JSON端点或HTML解析。
  • SKU库存为0:可能是地区性缺货,而非全站缺货。用不同城市的代理交叉验证。
  • 反爬升级:Temu可能随时更新反爬策略。建立监控告警,当成功率下降到低于70%时触发检查流程。
  • 请求超时:住宅代理延迟波动较大。设置20-30秒超时,并实现重试逻辑。

合规与道德边界

抓取Temu数据时必须遵守以下原则:

  • 仅抓取公开目录数据:商品标题、价格、图片URL、SKU规格等公开可见信息。不抓取用户评论中的个人数据、不抓取需要登录才能访问的页面。
  • 遵守robots.txt:检查 https://www.temu.com/robots.txt 的规则,尊重禁止抓取的路径。
  • 遵守服务条款:Temu的服务条款可能禁止自动化数据采集。违反ToS可能导致法律风险,特别是在美国 CFAA(计算机欺诈和滥用法案) 框架下。
  • GDPR/CCPA注意:如果抓取的数据涉及欧盟或加州用户的个人信息(如评论中的用户名),需遵守GDPR和CCPA的数据处理规定。
  • 不抓取账户数据:不访问订单历史、支付信息、收货地址等敏感数据。
  • 控制请求频率:不对Temu服务器造成实质性负担,合理控制并发和速率。

如果你是Temu平台商家,需要获取自己店铺的数据,优先使用Temu官方的商家后台数据导出功能或商家API(如有),而非抓取。官方渠道的数据更准确、更及时,且无法律风险。

关键要点总结

核心结论:

  • Temu无公开API,需在HTML解析和内部JSON端点之间选择——JSON端点更稳定但需处理 anti_content 签名。
  • 反爬栈包括Cloudflare Turnstile、签名token、TLS/HTTP2指纹——必须用 curl_cffi 模拟Chrome指纹。
  • 数据中心IP会被秒封,住宅代理(城市级地理定位)是强制要求。
  • 价格和运费因地区而异,粘性会话保证数据一致性。
  • 仅抓取公开目录数据,遵守ToS、CFAA和GDPR/CCPA。

常见问题

抓取Temu商品与价格数据时应该用HTML解析还是JSON端点?

优先选择内部JSON端点(如/api/poppy/v1/search和goods/detail),因为它们返回结构化数据,比HTML解析更稳定。但JSON端点需要构造正确的anti_content签名头和请求参数,逆向难度较高。如果无法生成签名,可退而解析页面中嵌入的__NEXT_DATA__ JSON块作为折中方案,它只需一次HTML请求且不需要签名。

为什么抓取Temu必须使用住宅代理而非数据中心代理?

Temu通过Cloudflare对数据中心IP段进行即时封锁,数据中心代理的成功率低于5%。此外,Temu的价格和运费因地区而异,数据中心代理无法提供真实的地理定位。住宅代理(尤其是城市级定位如-country-US-city-newyork)能模拟真实用户流量,成功率可达80-92%,同时确保获取的是目标市场的真实价格数据。

哪种代理类型最适合Temu价格抓取项目?

住宅代理(城市级地理定位)是Temu价格抓取的最佳选择,成功率80-92%,延迟50-150ms,能精确控制出口城市以获取区域价格。对于反爬特别严格的场景,移动代理(4G/5G)成功率更高(85-95%),但延迟较大(200-500ms)。建议以住宅代理为主、移动代理为辅的混合策略,配合curl_cffi模拟Chrome TLS指纹。

如何避免抓取Temu时被反爬系统封锁?

关键措施包括:使用curl_cffi库模拟Chrome 124的TLS/HTTP2指纹;使用住宅代理并控制每IP每分钟请求不超过15-20次;采用指数退避重试策略应对403/429;使用粘性会话(-session-标志)保证请求一致性;每10-15页轮换IP;设置2-5秒随机请求间隔;监控成功率并在低于70%时触发告警检查反爬策略更新。

抓取Temu数据是否合法?

抓取Temu公开目录数据(商品标题、价格、SKU规格)在技术上可行,但需注意合规边界:遵守robots.txt规则、不违反Temu服务条款、不抓取用户个人信息(避免GDPR/CCPA风险)、不访问需登录的页面、不对服务器造成实质性负担。在美国CFAA框架下,违反ToS的自动化采集可能存在法律风险。商家获取自己店铺数据应优先使用官方商家后台导出功能。

准备开始了吗?

通过AI过滤访问148多个国家的5000多万个住宅IP。

查看价格住宅代理
← 返回博客