From b062d96742f2d97d75e6182d3f9d54613c4401a1 Mon Sep 17 00:00:00 2001 From: PetrichorFun <127877748+PetrichorFun@users.noreply.github.com> Date: Fri, 8 May 2026 17:14:13 +0800 Subject: [PATCH] fix/detail-page-image (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fix can`t get imgurls on the page * fix: 优化详情页图片下载逻辑,添加加载等待重试机制 * perf: 为打开see full view添加兜底机制 * fix(amazon): 使用 ul 类名 XPath 抓取五点描述 chore: 将扩展 displayName 更新为 v0.7.1.10-beta Co-authored-by: Cursor --------- Co-authored-by: Cursor --- .gitignore | 1 + package.json | 2 +- src/env.ts | 3 +- src/page-worker/services/base.ts | 11 ++++- src/page-worker/web-injectors/amazon.ts | 55 ++++++++++++++++++++++--- 5 files changed, 64 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index c0348c7..5fc4637 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.pem *.xpi *.zip +*.7z dist dist-ssr extension/manifest.json diff --git a/package.json b/package.json index 500bb3f..fc861e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "azon-seeker", - "displayName": "Azon Seeker v0.7.1.7-beta", + "displayName": "Azon Seeker v0.7.1.10-beta", "version": "0.7.2", "private": true, "description": "Starter modify by honestfox101 and PetrichorFun", diff --git a/src/env.ts b/src/env.ts index c27b5e4..11eeafc 100644 --- a/src/env.ts +++ b/src/env.ts @@ -16,6 +16,7 @@ export const isFirefox = navigator.userAgent.includes('Firefox'); // export const remoteHost = __DEV__ ? '127.0.0.1:8000' : '47.251.4.191:8000'; // export const remoteHost = __DEV__ ? '127.0.0.1:18000' : 'vm8nc3zr-18000.usw2.devtunnels.ms'; -export const remoteHost = __DEV__ ? 'ogsm-dev.rekeymed.com:8888' : 'amzplugin.rekeymed.com'; +// export const remoteHost = __DEV__ ? 'ogsm-dev.rekeymed.com:8888' : 'amzplugin.rekeymed.com'; +export const remoteHost = __DEV__ ? '127.0.0.1:18000' : 'amzplugin.rekeymed.com'; // export const remoteHost = __DEV__ ? '127.0.0.1:18000' : 'amzplugin.rekeymed.com'; // export const remoteHost = '47.251.4.191:8000'; diff --git a/src/page-worker/services/base.ts b/src/page-worker/services/base.ts index b34779b..0ead32c 100644 --- a/src/page-worker/services/base.ts +++ b/src/page-worker/services/base.ts @@ -22,7 +22,16 @@ const httpClient = createAlova({ method.config.headers['x-public-key'] = publicKeyBase64Data; }, responded: { - onSuccess: (response) => response.json(), + // 使用 text() 而不是 json() 来避免 Response body 被重复读取的问题 + // 参考: https://github.com/alovajs/alova/issues/XXX + onSuccess: async (response) => { + const text = await response.text(); + // 检查空响应 + if (!text || text.trim() === '') { + return null; + } + return JSON.parse(text); + }, onError: (response: Response) => { const message = useMessage(); message.error(`HTTP Error: ${response.status}`); diff --git a/src/page-worker/web-injectors/amazon.ts b/src/page-worker/web-injectors/amazon.ts index 520ab70..b28e12a 100644 --- a/src/page-worker/web-injectors/amazon.ts +++ b/src/page-worker/web-injectors/amazon.ts @@ -490,11 +490,17 @@ export class AmazonDetailPageInjector extends BaseInjector { public async getImageUrls() { return this.run(async () => { const overlay = document.querySelector('.overlayRestOfImages'); + if (overlay) { if (document.querySelector('#ivThumbs')!.getClientRects().length === 0) { - overlay.click(); + // Click to see full view + document.querySelector('#canvasCaption > a')?.click(); await new Promise((resolve) => setTimeout(resolve, 1000)); } + } else { + // finally click to see full view if not clicked before + document.querySelector('#canvasCaption > a')?.click(); + await new Promise((resolve) => setTimeout(resolve, 1000)); } let script = document.evaluate( `//script[starts-with(text(), "\nP.when(\'A\').register") or contains(text(), "\nP.when('A').register")]`, @@ -512,7 +518,46 @@ export class AmazonDetailPageInjector extends BaseInjector { /(?<="large":")https:\/\/m.media-amazon.com\/images\/I\/[\w\d\.\-+]+(?=")/g, ); } - document.querySelector('header > [data-action="a-popover-close"]')?.click(); + + if (urls.length === 0) { + const divs: NodeListOf = + document.querySelectorAll('.ivRow div.ivThumbImage'); + await new Promise((resolve) => setTimeout(resolve, 500 + ~~(500 * Math.random()))); + for (const div of divs) { + // click div com + div.click(); + + // wait for image to load + await new Promise((resolve) => setTimeout(resolve, 500 + ~~(500 * Math.random()))); + + // if img src is not loading gif, then get url and break, otherwise continue to wait, with a max retry count to avoid infinite loop + let retryCount = 0; + const maxRetries = 5; + + while (true) { + const loadingGifUrl = + 'https://m.media-amazon.com/images/G/01/ui/loadIndicators/loading-large_labeled._CB485921664_.gif'; + // get img dom + const imgDom = document.querySelector('#ivLargeImage > img'); + + // get url from img dom src attribute + if (imgDom && 'src' in imgDom && imgDom.src !== loadingGifUrl) { + urls.push(imgDom.src as string); + break; + } else { + // wait for 500ms and try again + await new Promise((resolve) => setTimeout(resolve, 500 + ~~(500 * Math.random()))); + retryCount++; + if (retryCount >= maxRetries) { + console.error('在detail页面下载图片,已达最大重试次数:'); + break; + } + } + } + } + } + + document.querySelector('body > div.a-modal-scroller.a-declarative')?.click(); return urls; }); } @@ -621,9 +666,9 @@ export class AmazonDetailPageInjector extends BaseInjector { } return nodes.length > 0 ? nodes : undefined; }; - const abouts = $x( - `//*[normalize-space(text())='About this item']/following-sibling::ul[1]/li`, - )?.map((el) => el.innerText); + const abouts = $x( + `(//ul[contains(concat(' ', normalize-space(@class), ' '), ' a-unordered-list ') and contains(concat(' ', normalize-space(@class), ' '), ' a-vertical ') and contains(concat(' ', normalize-space(@class), ' '), ' a-spacing-mini ')])[1]/li`, + )?.map((el) => el.innerText.trim()); const brand = $x(`//*[./span[normalize-space(text())='Brand']]/following-sibling::*[1]`)?.[0] .innerText; const flavor = $x(