Ozon 商品页数据结构解析 —— widget 架构与 composer-api
2026/8/24 19:50:58 网站建设 项目流程

上一篇拆了 TikTok Shop 商品页的数据结构,这篇换Ozon(毛子电商)。同样是做要读懂的东西:一个商品页里有哪些结构化数据、按什么方式组织、怎么解析成一份干净 JSON。

Ozon 的前端架构和 TikTok 很不一样,值得单独说说。只摆事实和结果,文末附真实解析产物。


一、数据在哪:不在 HTML 里

Ozon 的商品页是Nuxt(Vue SSR)+ widget 架构。这带来一个反直觉的点:你抓到的页面 HTML,里面没有商品数据。

document.content()抓下来的 HTML,只有一层layout 骨架——一堆{"component":"webProductHeading","stateId":"..."}这样的布局占位,声明"这里有个标题 widget、那里有个价格 widget",但每个 widget 的实际内容(state)不在 HTML 里window.__NUXT__里也只有 CDN、菜单这些外壳。

商品数据要单独从一个接口取:

composer-api.bx/page/json/v2?url=<商品路径>

它返回的widgetStates才是真货,按 widget 名索引:webProductHeading(标题) /webPrice(价) /webShortCharacteristics(规格) /webGallery(图) /webAspects(变体)。

一个容易卡住的点:如果传给这个接口的商品 URL 无效(比如 id 拼错),Ozon 会把它匹配到另一个商品(一个带errorwidget 的降级页),此时widgetStates里只有 header/footer 外壳、没有商品内容。排查半天会以为接口用法错了——其实只要换成有效的商品 URL,就返回完整数据。所以用真实存在的商品链接。


二、数据怎么组织:变体是"独立商品"

解析widgetStates后,字段都很规整。这里说一个和 TikTok完全相反的设计:

  • TikTok:一个商品内含上百个 SKU(颜色×机型都在同一个商品对象里);
  • Ozon:每个颜色 / 尺码是一个独立商品(兄弟关系),各有自己的sku、URL 和价格。webAspects里列出的是这些兄弟变体。

实测一件男士 T 恤,webAspects有两个维度:颜色 38 个 × 尺码 2 个,每个变体带独立的商品链接和价格。做选品时这反而更方便——每个变体本来就是一条能单独取价的商品。


三、取价:读懂三档价的字段语义

Ozon 的价格有三个字段,做成本核算前得分清:

  • price—— 实际售价
  • cardPrice—— Ozon 卡支付价(更低)
  • originalPrice—— 划线原价

关键在originalPrice:它是个划线展示价,注水很凶。实测一条耳机划线18 900 ₽,而实际售价才2 846 ₽

如果把originalPrice当商品价来算成本,会严重偏离。成本核算只能用pricecardPrice。这不是玄学,就是读懂字段语义:划线价是营销展示值,price才是真实成交价。


四、结果

一个真实商品页(一条 Air Pro 3 耳机,5074 条评价):

右侧价格2 592 ₽(卡价) /2 846 ₽(实售) /18 900 ₽(划线)。左边 О товаре 是规格。

解析成结构化 JSON(截取):

{ "title": "Наушники беспроводные c шумоподавлением Air Pro 3", "product_id": "3577720626", "price": { "price": "2 846 ₽", "card_price": "2 592 ₽", "original_price": "18 900 ₽" }, "characteristics": [ { "name": "Тип", "values": ["Наушники"] }, { "name": "Шумоподавление", "values": ["Активное"] }, … ], "images": [ "…5 张 ozone.ru CDN 高清图…" ], "aspects": [] // 单款无变体 }

带变体的(男士 T 恤):

{ "title": "Футболка SADIQ набор футболок мужских 3 шт", "price": { "price": "1 075 ₽", "card_price": "968 ₽", "original_price": "4 999 ₽" }, "aspects": [ { "name": "Цвет", "variants": [ /* 38 个, 每个带 sku/价/独立链接/库存 */ ] }, { "name": "Размер", "variants": [ {"text":"48 RU / 48","price":"968 ₽"}, {"text":"56 RU / 56","price":"1 041 ₽"} ] } ] }

单款(耳机)+ 多变体(T 恤 38 色 × 2 码)两类都能稳定解析。

一个下游要注意的点:字段值是俄文,做匹配前要么翻译,要么直接用图(ozone.ru的 CDN 图可用)。


小结

  • Ozon 是 Nuxt + widget 架构:商品数据不在 HTML,在composer-apiwidgetStates
  • 有效商品 URL取,无效 URL 会被匹配到降级页、只返外壳。
  • 变体是独立商品(各有 sku/url/价),和 TikTok 的"内部 SKU"相反。
  • 取价读懂字段语义:originalPrice是划线展示价,price/cardPrice才是真实价

对比 TikTok:两家数据组织方式差很多,但"划线价/起步价 vs 真实价"的字段语义问题是共性——做成本核算都得挑对字段。


交流 各种电商数据

  • 微信NarraData

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询