jackwener/OpenCLI · error · CommandExecutionError

Ctrip attraction links rendered but parser did not find requ

Error message

Ctrip attraction links rendered but parser did not find required sight anchors

What it means

The DOM extraction ran and returned an array, but it was empty: attraction links were considered rendered by the wait script, yet the parser found no rows with the required sight anchors (name/url in `/sight/<city><cityId>/<id>.html` form). Since a valid city always lists attractions, an empty result is treated as a parsing/consistency failure, not EmptyResultError.

Source

Thrown at clis/ctrip/attraction.js:63

    func: async (page, kwargs) => {
        const cityId = parseCityId(kwargs.city);
        const limit = parseListLimit(kwargs.limit);

        const placeUrl = buildAttractionPlaceUrl(cityId);
        await page.goto(placeUrl);
        const waitResult = await page.evaluate(buildWaitForAttractionsJs(cityId));
        if (waitResult === 'captcha') {
            throw new AuthRequiredError('you.ctrip.com', 'Ctrip is asking for a captcha; complete it in your browser session and retry');
        }
        if (waitResult !== 'content') {
            throw new CommandExecutionError(`Ctrip place page did not render attraction links for city id ${cityId} (state=${String(waitResult)}); check the city id`);
        }
        const raw = await page.evaluate(buildAttractionExtractJs(cityId));
        if (!Array.isArray(raw)) {
            throw new CommandExecutionError('Ctrip attraction DOM extraction returned malformed rows');
        }
        if (raw.length === 0) {
            throw new CommandExecutionError('Ctrip attraction links rendered but parser did not find required sight anchors');
        }
        return raw.slice(0, limit).map((r, i) => ({
            rank: i + 1,
            name: r.name,
            rating: r.rating,
            reviews: r.reviews,
            url: r.url,
        }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — transient re-render timing is the most common cause.
  2. Confirm the cityId is correct via `ctrip search`; a wrong-but-renderable id can yield links outside the requested city scope.
  3. Update the adapter if the site changed its sight-link structure.
  4. Inspect the page manually (screenshot/DOM dump) and compare against buildAttractionExtractJs's anchor requirements in clis/ctrip/utils.js.
Defensive patterns

Strategy: retry

Try / catch

async function getAttractions(cityId, attempts = 2) {
  try {
    return await opencli.ctrip.attraction(cityId);
  } catch (err) {
    if (err.message.includes('sight anchors') && attempts > 1) {
      await new Promise(r => setTimeout(r, 3000));
      return getAttractions(cityId, attempts - 1);
    }
    throw err;
  }
}

Prevention

When it happens

Trigger: `opencli ctrip attraction <cityId>` where the page shows attraction markup but buildAttractionExtractJs matches zero rows — e.g. links don't carry the expected city-scoped sight URL pattern or lack the anchors the parser requires.

Common situations: Partial rendering: links appeared for the wait check but were removed/re-rendered by client JS before extraction; A/B layout variant missing the expected anchors; mismatched cityId between wait and extract scoping; site markup change.

Related errors


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