/** * Ozon商品页采集配置 * * 设计原则: * 1. 人工控制触发,不做复杂等待 * 2. 多套选择器并存,应对Ozon的A/B测试 * 3. 优先采集跟卖必需的字段 */ import type { SiteProfile } from './types'; export const profileOzon: SiteProfile = { id: 'ozon', name: 'Ozon', // URL匹配 urlPatterns: [ /^https:\/\/www\.ozon\.ru\/product\//, /^https:\/\/www\.ozon\.ru\/context\/detail\/id\// ], // 提取商品ID extractItemId: (url) => { // Ozon URL格式: https://www.ozon.ru/product/name-123456789/ const match = url.match(/\/product\/[^\/]+-(\d+)/); return match?.[1] ?? null; }, // 简单的就绪检测 - 只要关键元素存在即可 readySelectors: [ '[data-widget="webProductHeading"]', // 标题区 '[data-widget="webGallery"]' // 图片画廊 ], readyTimeoutMs: 5_000, // 快速失败,不等太久 // 图片来源属性优先级 defaultSrcProps: ['data-src', 'currentSrc', 'src'], refererOrigin: 'https://www.ozon.ru', // ========================================== // 文本素材规则 // ========================================== textRules: [ // 1. 标题 (必需) { kind: 'title', selectors: [ '[data-widget="webProductHeading"] h1', '.tsHeadline500Medium', 'h1[itemprop="name"]' ], extract: 'first', required: true }, // 2. 价格 { kind: 'price', selectors: [ '[data-widget="webPrice"] span[class*="tsBodyControl500"]', '[data-widget="webPrice"] span', '.c2h9_27 span', // 可能的备用类名 'span[itemprop="price"]' ], extract: 'first' }, // 3. 参数表 (特性) { kind: 'params', selectors: [ '[data-widget="webCharacteristics"] dl', '[data-widget="webDetailedCharacteristics"] dl', '.k1p_27 dl' ], extract: 'table', tableKeySelector: 'dt', tableValueSelector: 'dd' }, // 4. 简介/卖点 { kind: 'selling_point', selectors: [ '[data-widget="webFeatures"]', '[data-widget="webAO"]', '.h9o_27' // About this item ], extract: 'join' }, // 5. 详细描述 { kind: 'desc', selectors: [ '[data-widget="webDescription"]', '[data-widget="webRichContent"]', '.RA-a1' ], extract: 'join' } ], // ========================================== // 图片素材规则 // ========================================== imageGroups: [ // 主图画廊 { key: 'main', name: '主图', type: 'img', selectors: [ '[data-widget="webGallery"] img[class*="Image"]', '[data-widget="webGallery"] source', // picture元素 '[data-widget="webPhotoGallery"] img', '.b013-a img' // 旧版选择器 ], minWidth: 200, minHeight: 200 }, // SKU变体图 (颜色/尺寸) { key: 'sku', name: 'SKU图片', type: 'img', selectors: [ '[data-widget="webDetailSKU"] button img', '[data-widget="webVariants"] img', '[data-widget="webSku"] img', '.k3r_27 img' // SKU容器 ], // SKU规格名提取 nameSelectors: [ 'span[class*="Value"]', 'span[class*="Text"]', '.tsBodyControl400Small' ], minWidth: 20, minHeight: 20 }, // 详情图 (描述中的图片) { key: 'detail', name: '详情图', type: 'img', selectors: [ '[data-widget="webDescription"] img', '[data-widget="webRichContent"] img', '[data-widget="webFeatures"] img', '.RA-a1 img' ], minWidth: 300, minHeight: 100 }, // 视频 (如果有) { key: 'video', name: '视频', type: 'video', selectors: [ '[data-widget="webGallery"] video', '[data-widget="webVideo"] video', 'video[class*="Video"]' ] } ], // ========================================== // 图片URL处理规则 // ========================================== originalUrlRules: [ { // Ozon CDN缩略图处理 // 例: /wc200/xxx.jpg → /wc1200/xxx.jpg (获取更高分辨率) match: /\/wc\d+\//, replace: '/wc1200/' }, { // 或者移除尺寸参数 // 例: image.jpg?width=200 → image.jpg match: /\?(width|height|size|quality)=[^&]+&?/g, replace: '' } ] }; // ========================================== // Ozon特殊处理函数 // ========================================== /** * Ozon页面额外的数据提取 * (可选) 从页面的JSON-LD结构化数据中提取 */ export function extractOzonStructuredData(): { brand?: string; sku?: string; availability?: string; } | null { try { const scripts = document.querySelectorAll('script[type="application/ld+json"]'); for (const script of scripts) { const data = JSON.parse(script.textContent || '{}'); if (data['@type'] === 'Product') { return { brand: data.brand?.name, sku: data.sku, availability: data.offers?.availability }; } } } catch (e) { console.warn('Failed to extract structured data:', e); } return null; } /** * 检测Ozon页面是否已就绪 * (简化版 - 只检查关键元素存在) */ export function isOzonPageReady(): { ready: boolean; missing: string[]; } { const requiredElements = [ { selector: '[data-widget="webProductHeading"]', name: '标题' }, { selector: '[data-widget="webGallery"]', name: '图片画廊' } ]; const missing: string[] = []; for (const elem of requiredElements) { if (!document.querySelector(elem.selector)) { missing.push(elem.name); } } return { ready: missing.length === 0, missing }; } // ========================================== // 使用示例 (在content script中) // ========================================== /* import { profileOzon, isOzonPageReady } from './profiles/ozon'; // 用户点击"采集"按钮时 async function handleCollect() { // 1. 快速检查 const { ready, missing } = isOzonPageReady(); if (!ready) { alert(`页面未完全加载,缺少: ${missing.join(', ')}\n请稍候再试`); return; } // 2. 执行采集 const result = await scanCurrentPage(); // 使用通用采集引擎 // 3. 显示结果 console.log('采集完成:', result); } */