feat: 开发采集、采集箱和商品编辑功能
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 用真实保存的 Ozon 页面验证采集逻辑(不依赖浏览器)
|
||||
* 用法:先 esbuild 打包再 node 运行(见 README / 命令注释)
|
||||
*/
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { extractOzonState } from '../src/collector/ozon-state';
|
||||
import { extractJsonLd } from '../src/collector/jsonld';
|
||||
import { toOriginalUrl, toThumbUrl, pickBestFromSrcset } from '../src/collector/url';
|
||||
|
||||
class FakeEl {
|
||||
id: string;
|
||||
attrs: Record<string, string>;
|
||||
constructor(id: string, attrs: Record<string, string>) {
|
||||
this.id = id;
|
||||
this.attrs = attrs;
|
||||
}
|
||||
getAttribute(name: string): string | null {
|
||||
return this.attrs[name] ?? null;
|
||||
}
|
||||
get textContent(): string {
|
||||
return this.attrs['text'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
function buildFakeDoc(html: string) {
|
||||
const stateEls: FakeEl[] = [];
|
||||
const re = /<div\s+id="state-([^"]+)"\s+data-state='(.*?)'\s*>/gs;
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = re.exec(html))) {
|
||||
stateEls.push(new FakeEl('state-' + m[1], { 'data-state': m[2] }));
|
||||
}
|
||||
const ldEls: FakeEl[] = [];
|
||||
const re2 = /<script[^>]*type="application\/ld\+json"[^>]*>(.*?)<\/script>/gs;
|
||||
while ((m = re2.exec(html))) {
|
||||
ldEls.push(new FakeEl('', { text: m[1] }));
|
||||
}
|
||||
return {
|
||||
querySelectorAll(sel: string): FakeEl[] {
|
||||
if (sel === 'div[id^="state-"]') return stateEls;
|
||||
if (sel === 'script[type="application/ld+json"]') return ldEls;
|
||||
return [];
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function check(name: string, actual: unknown, expected: unknown): void {
|
||||
const a = JSON.stringify(actual);
|
||||
const e = JSON.stringify(expected);
|
||||
const ok = a === e;
|
||||
console.log(`${ok ? '✅' : '❌'} ${name}`);
|
||||
if (!ok) {
|
||||
console.log(' expected:', e);
|
||||
console.log(' actual :', a);
|
||||
}
|
||||
}
|
||||
|
||||
for (const fn of ['../reference/ozon1.html', '../reference/ozon2.html']) {
|
||||
console.log(`\n========== ${fn} ==========`);
|
||||
const html = readFileSync(join(process.cwd(), fn), 'utf8');
|
||||
(globalThis as any).document = buildFakeDoc(html);
|
||||
|
||||
const state = extractOzonState();
|
||||
console.log('state:', JSON.stringify({
|
||||
title: state.title,
|
||||
price: state.price,
|
||||
originalPrice: state.originalPrice,
|
||||
rating: state.rating,
|
||||
reviewCount: state.reviewCount,
|
||||
gallery: state.galleryImages.length,
|
||||
videos: state.videos,
|
||||
variants: state.skuVariants,
|
||||
characteristics: state.characteristics,
|
||||
}, null, 1));
|
||||
|
||||
const ld = extractJsonLd();
|
||||
console.log('jsonld:', JSON.stringify(ld));
|
||||
}
|
||||
|
||||
// ── URL 工具验证 ──
|
||||
console.log('\n========== url tools ==========');
|
||||
const rules = [
|
||||
{ match: /\/wc\d+\//, replace: '/' },
|
||||
{ match: /\/c\d+\//, replace: '/' },
|
||||
{ match: /(?<!:)\/{2,}/g, replace: '/' },
|
||||
{ match: /[?&](width|height|size|quality|w|h)=[^&]+/g, replace: '' },
|
||||
];
|
||||
check('wc1000 → 原图', toOriginalUrl('https://ir.ozone.ru/s3/multimedia-1-5/wc1000/9290076089.jpg', rules), 'https://ir.ozone.ru/s3/multimedia-1-5/9290076089.jpg');
|
||||
check('wc140 → 原图', toOriginalUrl('https://ir.ozone.ru/s3/multimedia-1-q/wc140/9290076002.jpg', rules), 'https://ir.ozone.ru/s3/multimedia-1-q/9290076002.jpg');
|
||||
check('c50 → 原图', toOriginalUrl('https://ir.ozone.ru/s3/multimedia-1-5/c50/9290076089.jpg', rules), 'https://ir.ozone.ru/s3/multimedia-1-5/9290076089.jpg');
|
||||
check('原图不变', toOriginalUrl('https://ir.ozone.ru/s3/multimedia-1-5/9290076089.jpg', rules), 'https://ir.ozone.ru/s3/multimedia-1-5/9290076089.jpg');
|
||||
check('带 query 尺寸', toOriginalUrl('https://cdn.x.com/a.jpg?width=200&h=300', rules), 'https://cdn.x.com/a.jpg');
|
||||
check('缩略图', toThumbUrl('https://ir.ozone.ru/s3/multimedia-1-5/9290076089.jpg'), 'https://ir.ozone.ru/s3/multimedia-1-5/wc200/9290076089.jpg');
|
||||
check('已带标记不再缩略', toThumbUrl('https://ir.ozone.ru/s3/multimedia-1-5/wc50/9290076089.jpg'), 'https://ir.ozone.ru/s3/multimedia-1-5/wc50/9290076089.jpg');
|
||||
check('srcset 取最大', pickBestFromSrcset('https://ir.ozone.ru/s3/a/wc50/1.jpg 1x, https://ir.ozone.ru/s3/a/wc100/1.jpg 2x'), 'https://ir.ozone.ru/s3/a/wc100/1.jpg');
|
||||
|
||||
console.log('\n全部验证结束');
|
||||
Reference in New Issue
Block a user