jackwener/OpenCLI · error · EmptyResultError

No threads found on bbs.hupu.com — page structure may have c

Error message

No threads found on bbs.hupu.com — page structure may have changed

What it means

After a successful in-page extraction, getHupuHot validates that the result is a non-empty array of thread rows. An empty or non-array result means the script ran but matched nothing, which the library interprets as a changed page structure and raises EmptyResultError for the 'hupu/hot' command.

Source

Thrown at clis/hupu/hot.js:138

})()
`;
}

async function getHupuHot(page, args) {
    const limit = normalizeHotLimit(args.limit);
    await page.goto(`${HUPU_HOST}/`, { waitUntil: 'load', settleMs: 1000 });
    let rows;
    try {
        rows = await page.evaluate(buildHotScript(limit));
    } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        throw new CommandExecutionError(
            `Failed to read hupu hot threads: ${message}`,
            'bbs.hupu.com may be unreachable or its markup may have changed',
        );
    }
    if (!Array.isArray(rows) || rows.length === 0) {
        throw new EmptyResultError(
            'hupu/hot',
            'No threads found on bbs.hupu.com — page structure may have changed',
        );
    }
    return rows;
}

export const hotCommand = cli({
    site: 'hupu',
    name: 'hot',
    access: 'read',
    description: '虎扑首页热门帖子(含 lights / replies / forum / is_hot 列)',
    domain: 'bbs.hupu.com',
    strategy: Strategy.PUBLIC,
    browser: true,
    args: [
        { name: 'limit', type: 'int', default: HOT_LIMIT_DEFAULT, help: `Number of threads (1-${HOT_LIMIT_MAX})` },
    ],

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Increase the settle/wait time before evaluate so lazy-loaded rows exist in the DOM
  2. Open bbs.hupu.com in a browser and compare the current markup with buildHotScript's selectors; update them if changed
  3. Run with a logged-in/normal browser profile if the anonymous homepage variant is empty
  4. Check whether Hupu moved the hot list to an API endpoint and switch the extraction to that source

Example fix

// before
rows = await page.evaluate(buildHotScript(limit));
// after
await page.waitForSelector('.hot-thread-item, [data-hot-list]', { timeout: 10000 }).catch(() => {});
rows = await page.evaluate(buildHotScript(limit));
Defensive patterns

Strategy: fallback

Validate before calling

await page.goto('https://bbs.hupu.com/');
const hasList = await page.$('.hot-thread-item, [data-hot-list]') !== null;
if (!hasList) console.warn('Hot list selectors may be stale');

Type guard

function nonEmptyRows(v) { return Array.isArray(v) && v.length > 0; }

Try / catch

try {
  rows = await getHupuHot(page, limit);
} catch (e) {
  if (e instanceof EmptyResultError) rows = await getHotFromFallbackSource();
  else throw e;
}

Prevention

When it happens

Trigger: buildHotScript's evaluate returns [] or a non-array — the hot-list DOM no longer matches the selectors, the homepage rendered a personalized/empty variant, or the region-served page omits the expected list.

Common situations: Hupu shipped a redesign of bbs.hupu.com; the scraper runs from a region where the hot list differs; logged-out vs logged-in layouts differ from what the script assumes; content served behind lazy-load so rows are not yet in the DOM at evaluate time.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/e9de94930d3126f1. Report an issue: GitHub.