80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
/**
|
||
* SSR 数据提取器 - 淘宝/天猫页面内嵌 JSON
|
||
*
|
||
* 页面 HTML 里有完整商品数据挂在 window.__ICE_APP_CONTEXT__,
|
||
* 包含标题、主图、SKU(图+名)、价格、参数,比 DOM 采集稳定 10 倍:
|
||
* - 不受懒加载影响
|
||
* - 不受改版影响(JSON 结构远比 CSS 类名稳定)
|
||
* - 一次拿全所有 SKU,无需滚动
|
||
*
|
||
* 当前只支持淘宝/天猫(__ICE_APP_CONTEXT__),
|
||
* 其他平台返回 null,触发 DOM 降级。
|
||
*/
|
||
|
||
export interface SSRData {
|
||
item: {
|
||
title: string;
|
||
itemId: string;
|
||
images: string[];
|
||
videos?: Array<{ url: string; videoThumbnailURL?: string }>;
|
||
};
|
||
skuBase?: {
|
||
props: Array<{
|
||
pid: string;
|
||
name: string; // "颜色分类" / "商品规格"
|
||
values: Array<{
|
||
vid: string;
|
||
name: string; // SKU 规格名
|
||
image?: string; // SKU 图片
|
||
}>;
|
||
}>;
|
||
};
|
||
params?: {
|
||
basicParamList?: Array<{ propertyName: string; valueName: string }>;
|
||
enhanceParamList?: Array<{ propertyName: string; valueName: string }>;
|
||
};
|
||
price?: {
|
||
priceText?: string;
|
||
priceMoney?: string;
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 尝试从页面提取 SSR 数据(淘宝/天猫 __ICE_APP_CONTEXT__)
|
||
*/
|
||
export function extractSSRData(): SSRData | null {
|
||
try {
|
||
const ctx = (window as any).__ICE_APP_CONTEXT__;
|
||
if (!ctx?.loaderData?.home?.data?.res) return null;
|
||
|
||
const res = ctx.loaderData.home.data.res;
|
||
|
||
// 基础结构验证
|
||
if (!res.item?.title || !res.item?.itemId) return null;
|
||
|
||
// 提取参数(两个来源都试)
|
||
const industryParams = res.plusViewVO?.industryParamVO;
|
||
const extensionParams = res.componentsVO?.extensionInfoVO?.infos?.find(
|
||
(i: any) => i.type === 'BASE_PROPS'
|
||
);
|
||
|
||
return {
|
||
item: {
|
||
title: res.item.title,
|
||
itemId: res.item.itemId,
|
||
images: res.item.images || [],
|
||
videos: res.item.videos
|
||
},
|
||
skuBase: res.skuBase,
|
||
params: {
|
||
basicParamList: industryParams?.basicParamList || extensionParams?.items || [],
|
||
enhanceParamList: industryParams?.enhanceParamList || []
|
||
},
|
||
price: res.componentsVO?.priceVO?.price || res.componentsVO?.priceVO?.extraPrice
|
||
};
|
||
} catch (err) {
|
||
console.warn('[SSR] 提取失败:', err);
|
||
return null;
|
||
}
|
||
}
|