feat(edit): 编辑上报细节优化
This commit is contained in:
@@ -29,6 +29,14 @@ type ImageGroup = {
|
||||
*/
|
||||
const DOM_IMAGE_PROFILES: Record<DomMediaPlatform, ImageGroup[]> = {
|
||||
'1688': [
|
||||
{
|
||||
role: 'source_main',
|
||||
relation: 'inherited_product_default',
|
||||
// 画廊缩略项虽小,但背景地址指向商品原图;位置与控件类型比尺寸更可靠。
|
||||
selectors: ['.od-picture-gallery-list > .v-image-cover'],
|
||||
sourceProps: ['backgroundImage'],
|
||||
excludeWithin: ['.video-image-cover', '.v-image-cover:has(.cpv-icon, .cpv-tag-name)'],
|
||||
},
|
||||
{
|
||||
role: 'source_main',
|
||||
relation: 'inherited_product_default',
|
||||
@@ -43,6 +51,7 @@ const DOM_IMAGE_PROFILES: Record<DomMediaPlatform, ImageGroup[]> = {
|
||||
'.detail-gallery-turn img.detail-gallery-img',
|
||||
'.img-list-wrapper img.od-gallery-img',
|
||||
],
|
||||
excludeWithin: ['.video-image-cover', '.v-image-cover:has(.cpv-icon, .cpv-tag-name)'],
|
||||
minWidth: 200,
|
||||
minHeight: 200,
|
||||
},
|
||||
@@ -189,15 +198,58 @@ export function collectPlatformDomAssets(
|
||||
}
|
||||
}
|
||||
}
|
||||
if (platform === '1688') add1688GalleryVideos(root, pageUrl, assets);
|
||||
return assets;
|
||||
}
|
||||
|
||||
/** 只读取商品画廊内播放器的公开直链,不扫描全页视频或根据封面猜测地址。 */
|
||||
function add1688GalleryVideos(root: Document, pageUrl: string, assets: Asset[]) {
|
||||
const selectors = [
|
||||
'[data-module="od_picture_gallery"] video',
|
||||
'.module-od-picture-gallery video',
|
||||
'.od-picture-gallery video',
|
||||
'.od-picture-gallery-list video',
|
||||
'.detail-gallery-turn video',
|
||||
'.od-gallery-turn-item-wrapper video',
|
||||
];
|
||||
const seen = new Set<string>();
|
||||
for (const selector of selectors) {
|
||||
for (const video of Array.from(root.querySelectorAll<HTMLVideoElement>(selector))) {
|
||||
const candidates = [video.currentSrc, video.getAttribute('src'),
|
||||
...Array.from(video.querySelectorAll('source')).map((source) => source.getAttribute('src'))];
|
||||
const url = candidates.map((candidate) => normaliseVideoUrl(candidate ?? '', pageUrl)).find(Boolean);
|
||||
if (!url || seen.has(url) || assets.length >= 500) continue;
|
||||
seen.add(url);
|
||||
const cover = root.querySelector<HTMLElement>('.od-picture-gallery-list > .video-image-cover');
|
||||
const poster = video.poster || video.getAttribute('poster');
|
||||
const posterUrl = (poster ? normaliseImageUrl(poster, pageUrl, '1688') : undefined) ??
|
||||
(cover ? imageUrlFromElement(cover, ['backgroundImage'], pageUrl, '1688') : undefined);
|
||||
assets.push({
|
||||
url, mediaType: 'video', role: 'source_main', relation: 'product_candidate',
|
||||
...(posterUrl?.startsWith('https://') ? { posterUrl } : {}),
|
||||
sortOrder: assets.length, evidenceRef: '1688:dom:source_video',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function normaliseVideoUrl(raw: string, pageUrl: string): string | undefined {
|
||||
if (!raw.trim()) return undefined;
|
||||
try {
|
||||
const url = new URL(raw, pageUrl);
|
||||
return url.protocol === 'https:' && /\.(mp4|webm)$/i.test(url.pathname) ? url.href : undefined;
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/** Restores the original CDN URL before payload storage and de-duplication. */
|
||||
export function normaliseImageUrl(
|
||||
raw: string,
|
||||
pageUrl: string,
|
||||
platform: SupportedMediaPlatform,
|
||||
): string | undefined {
|
||||
if (!raw.trim() || /^(?:undefined|null|none)$/i.test(raw.trim())) return undefined;
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(raw, pageUrl);
|
||||
@@ -266,9 +318,10 @@ function imageUrlFromElement(
|
||||
else if (prop === 'currentSrc')
|
||||
raw = (target as HTMLImageElement).currentSrc ?? '';
|
||||
else if (prop === 'backgroundImage') {
|
||||
// 优先使用内联地址,避免占位值 undefined 被计算样式解析成一个页面相对 URL。
|
||||
const style =
|
||||
target.ownerDocument.defaultView?.getComputedStyle(target)
|
||||
.backgroundImage ?? target.style.backgroundImage;
|
||||
target.style.backgroundImage ||
|
||||
target.ownerDocument.defaultView?.getComputedStyle(target).backgroundImage || '';
|
||||
raw = style.match(/url\(["']?(.*?)["']?\)/i)?.[1] ?? '';
|
||||
// Some 1688 SKU selectors directly match an <img> despite the
|
||||
// group being background-image-first.
|
||||
|
||||
Reference in New Issue
Block a user