灵猴市集Linghou Market

懂车帝车系搜索

懂车帝dongchedi-car-search

用途 按关键词搜索懂车帝车系,返回车系 ID、名称、品牌、指导价、经销商价、图片数量和车系页面链接。 执行前提 需要在懂车帝网页中执行,建议先打开 https://www.dongchedi.com/ 或任意懂车帝页面。脚本读取公开页面数据,不需要登录。若页面结构变化、网络风控或搜索结果为空,脚本会返回错误。 参数 keyword:必填,搜索关键词,例如 …

搜索车系价格
版本1.0.0
扫描passed
更新2026-06-28
超时30000ms

匹配范围

*://www.dongchedi.com/*

排除范围

未声明

能力声明

dom.read

代码

源码已展开
1return await (async () => {2  const DCD_BASE = "https://www.dongchedi.com";3  const SERIES_CELL_TYPE = 26;4  const FALLBACK_SHELL_KEYS = ["__hasUrlCity", "is_gray", "has_gray", "clientIp", "sensitiveSeriesIdList"];5 6  const input = typeof params === "object" && params ? params : {};7 8  function clean(value) {9    return String(value == null ? "" : value).replace(/\s+/g, " ").trim();10  }11 12  function fail(message) {13    throw new Error(message);14  }15 16  function requireArray(value, label) {17    if (!Array.isArray(value)) {18      fail(`${label} 返回的数据结构不符合预期,应为数组。`);19    }20    return value;21  }22 23  function requireStableId(value, label) {24    const id = String(value ?? "").trim();25    if (!/^\d+$/.test(id) || id === "0") {26      fail(`${label} 未包含稳定的数字 ID。`);27    }28    return id;29  }30 31  function requireText(value, label) {32    const text = clean(value);33    if (!text) {34      fail(`${label} 未包含稳定文本。`);35    }36    return text;37  }38 39  function requireLimit(value, fallback, max) {40    const raw = value == null || value === "" ? fallback : value;41    const n = typeof raw === "number" ? raw : Number(String(raw).trim());42    if (!Number.isInteger(n) || n < 1 || n > max) {43      fail(`limit 必须是 1 到 ${max} 之间的整数。`);44    }45    return n;46  }47 48  function extractPageProps(html) {49    const match = String(html || "").match(/<script id="__NEXT_DATA__"[^>]*>([\s\S]*?)<\/script>/);50    if (!match) return null;51    try {52      const data = JSON.parse(match[1]);53      return data && data.props && data.props.pageProps ? data.props.pageProps : null;54    } catch {55      return null;56    }57  }58 59  function isFallbackShell(pageProps) {60    if (!pageProps || typeof pageProps !== "object") return true;61    return Object.keys(pageProps).filter((key) => !FALLBACK_SHELL_KEYS.includes(key)).length === 0;62  }63 64  async function fetchPageProps(path, label) {65    const response = await fetch(`${DCD_BASE}${path}`, {66      credentials: "include",67      headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" },68    });69    if (!response.ok) {70      fail(`${label} 请求失败:HTTP ${response.status}`);71    }72    const pageProps = extractPageProps(await response.text());73    if (!pageProps) {74      fail(`${label} 未返回页面数据,页面结构可能已变化或请求被拦截。`);75    }76    if (isFallbackShell(pageProps)) {77      fail(`${label} 返回空壳页面,关键词可能无结果或页面入口已变化。`);78    }79    return pageProps;80  }81 82  function parseSearchRows(searchData, limit) {83    const data = requireArray(searchData?.data, "搜索结果");84    const rows = [];85    for (const [index, item] of data.entries()) {86      if (item?.cell_type !== SERIES_CELL_TYPE) continue;87      const seriesId = requireStableId(item?.series_id, `第 ${index + 1} 条车系结果`);88      const display = item.display || {};89      const name = requireText(display.series_name || display.title, `第 ${index + 1} 条车系名称`);90      rows.push({91        rank: rows.length + 1,92        series_id: seriesId,93        name,94        brand: clean(display.sub_brand_name),95        official_price: clean(display.official_price),96        dealer_price: clean(display.agent_price),97        pictures: Number.isFinite(Number(display.picture_num)) ? Number(display.picture_num) : null,98        url: `${DCD_BASE}/auto/series/${seriesId}`,99      });100      if (rows.length >= limit) break;101    }102    return rows;103  }104 105  const keyword = clean(input.keyword ?? input.query ?? input.q);106  if (!keyword) {107    fail("请通过 params.keyword 传入搜索关键词。");108  }109 110  const limit = requireLimit(input.limit, 15, 30);111  const pageProps = await fetchPageProps(`/search?keyword=${encodeURIComponent(keyword)}`, `搜索「${keyword}」`);112  const rows = parseSearchRows(pageProps.searchData, limit);113  if (rows.length === 0) {114    fail(`没有匹配到车系结果:${keyword}`);115  }116  return rows;117})();