fix(route/xiaohongshu): use cover as url (#22740)

This commit is contained in:
Tony 2026-07-17 02:32:37 +08:00 committed by GitHub
parent bd24a2fdcd
commit 7ad67ad56d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 35 deletions

View File

@ -98,14 +98,17 @@ async function getUserFeeds(url: string, category: string) {
const renderNote = (notes) =>
notes.flatMap((n) =>
n.map(({ id, noteCard }) => ({
title: noteCard.displayTitle,
link: new URL(noteCard.noteId || id, url).href,
guid: noteCard.displayTitle,
description: `<img src="${noteCard.cover.infoList.pop().url}" width="${noteCard.cover.width}" height="${noteCard.cover.height}"><br>${noteCard.displayTitle}`,
author: noteCard.user.nickname,
upvotes: noteCard.interactInfo.likedCount,
}))
n.map(({ noteCard }) => {
const coverUrl = noteCard.cover.infoList.pop().url;
return {
title: noteCard.displayTitle,
link: coverUrl,
guid: noteCard.displayTitle,
description: `<img src="${coverUrl}" width="${noteCard.cover.width}" height="${noteCard.cover.height}"><br>${noteCard.displayTitle}`,
author: noteCard.user.nickname,
upvotes: noteCard.interactInfo.likedCount,
};
})
);
const renderCollect = (collect) => {
if (!collect) {

View File

@ -1,3 +1,4 @@
import type { CheerioAPI } from 'cheerio';
import { load } from 'cheerio';
import { config } from '@/config';
@ -77,17 +78,22 @@ const getUser = (url, cache) =>
await page.goto(url, {
waitUntil: 'domcontentloaded',
});
await page.waitForSelector('div.reds-tab-item:nth-child(2), #red-captcha');
try {
await page.waitForSelector('div.reds-tab-item:nth-child(2), .fe-verify-box', { timeout: 3000 });
} catch {
//
}
if (await page.$('#red-captcha')) {
if (await page.$('.fe-verify-box')) {
throw new CaptchaError('小红书风控校验,请稍后再试');
}
const initialState = await page.evaluate(() => (window as any).__INITIAL_STATE__);
const content = await page.content();
const initialState = JSON.parse(extractInitialState(load(content)));
if (!(await page.$('.lock-icon'))) {
await page.click('div.reds-tab-item:nth-child(2)');
try {
await page.click('div.reds-tab-item:nth-child(2)', { timeout: 3000 });
const response = await page.waitForResponse(
(res) => {
const req = res.request();
@ -105,6 +111,10 @@ const getUser = (url, cache) =>
userPageData = userPageData._rawValue || userPageData;
notes = notes._rawValue || notes;
if (!userPageData.basicInfo) {
throw new Error(`小红书未返回用户数据,请稍后再试: ${JSON.stringify(userPageData.result)}`);
}
return { userPageData, notes, collect };
} finally {
await destroy();
@ -299,38 +309,20 @@ async function getUserWithCookie(url: string) {
}
// Add helper function to extract initial state
function extractInitialState($) {
let script = $('script')
.filter((i, script) => {
const text = script.children[0]?.data;
return text?.startsWith('window.__INITIAL_STATE__=');
})
.text();
script = script.slice('window.__INITIAL_STATE__='.length);
function extractInitialState($: CheerioAPI) {
let script = $('script:contains("window.__INITIAL_STATE__=")').text();
script = script.slice(script.indexOf('window.__INITIAL_STATE__=') + 'window.__INITIAL_STATE__='.length);
script = script.replaceAll('undefined', 'null');
return script;
}
// Add helper function to extract initial SSR state
function extractInitialSsrState($) {
let script = $('script')
.filter((i, script) => {
const text = script.children[0]?.data;
return text?.includes('window.__INITIAL_SSR_STATE__=');
})
.text();
function extractInitialSsrState($: CheerioAPI) {
const script = $('script:contains("window.__INITIAL_SSR_STATE__=")').text();
const match = script.match(/window\.__INITIAL_SSR_STATE__\s*=\s*(\{[\s\S]*?\})\s*(?:;|$)/);
if (match) {
return match[1].replaceAll('undefined', 'null');
}
// Fallback: try simple extraction
const startMarker = 'window.__INITIAL_SSR_STATE__=';
const startIndex = script.indexOf(startMarker);
if (startIndex !== -1) {
script = script.slice(startIndex + startMarker.length);
script = script.replaceAll('undefined', 'null');
return script;
}
throw new Error('Cannot extract __INITIAL_SSR_STATE__');
}