☰
二手车车源信息查询 API 实战:车型、图片、里程、首付与标签批量拉取
2026/9/27 5:20:21 网站建设 项目流程

二手车车源信息查询 API 实战:车型、图片、里程、首付与标签批量拉取

做二手车选品、车源同步、行情分析时,第一步往往卡在「没有数据」:公开平台的车源列表是动态渲染的,车型名称、图片、里程、首付、标签混在一堆 HTML 里,自己抓要处理分页、懒加载、反爬。本文介绍一个二手车车源信息查询接口:一次 GET 请求返回当前可查的车源列表,车型名称、图片链接、行驶里程、注册年份、首付价格、车辆标签一次拿全,且无车源返回时不收费。

  • api.xujian.tech
  • Vxujian_cq

一、车源数据显示场常见的几个坑

难点具体表现
数据是渲染出来的车源列表走 JS 动态加载,HTML 里只有空壳,直接抓页面拿不到数据
分页与懒加载图片滚动到底才加载,分页接口往往带签名,逆向成本很高
字段不规范车型名称是「长安启源E07 2025款 纯电 两驱 90kWh Max智驾版」这种长文本,年款、配置、续航都挤在一起
里程单位混乱有的写「3.2万公里」,有的写「32000」,有的写「3.2」无单位
首付价格口径不一「首付 3.8万」可能是月供,也可能是首付总额
数据量不可控一次拉回上千条,存储和渲染都吃不消

把这一步收敛成一个接口,价值在于:字段已经清洗好(里程统一为万公里数值文本、首付统一为万元、regDate统一为「年份」文本、标签已经是数组),并且可以用limit控制返回条数。

二、接口能力概览

2.1 接口基础信息

项目说明
接口地址https://api.xujian.tech/openapi/usedcar/list
接口编码usedcar.list
请求方式GET(limit放 Query String)
鉴权方式请求头X-API-Key,不做签名、时间戳或加密
返回格式JSON,Content-Type: application/json;charset=UTF-8
单次费用0.01 元/次
最多返回50 条(limit缺省即上限)
是否需要业务入参否,只有可选的limit
典型耗时数百毫秒 ~ 数秒(响应体costMs字段为本次真实耗时)
在线文档https://api.xujian.tech/api/usedcar-list

2.2 请求参数

请求头:

参数名必填说明
X-API-Key是开发者 API Key,缺失或无效直接返回失败

业务参数:

参数名必填类型示例说明
limit否Integer20期望返回条数;取值范围 1 ~ 50,缺省按上限 50 返回;传0或负数按上限处理

这个接口没有筛选入参(品牌 / 价格 / 里程等筛选需要在调用侧自己做)。设计上它是「一次拉全量、本地再筛选」的模式:单次最多 50 条,本地过滤远比在接口上堆一堆分不清的筛选参数省心。

2.3 计费上比较实在的一点

接口是先预鉴权、查到结果后再扣费的两段式流程。下面这些情况直接返回失败,不扣费、不写扣费流水、不累加调用次数:

  • 上游数据服务暂时不可用(超时或网络异常);
  • 当前没有可查车源(上游返回空列表)。

也就是说,只有真正返回了至少一条车源才计一次费用。做定时任务同步时,服务异常或空结果不会白白吃掉预算。

三、返回字段详解

3.1 顶层字段

字段类型说明
codeint0成功,非 0 失败(常见为500)
msgString结果描述,成功为success,失败为具体原因
dataObject业务数据,失败时为null

3.2 data 字段

字段类型示例说明
totalint20本次实际返回的车源条数
listArray[…]车源列表
apiCodeStringusedcar.list接口编码
apiNameString二手车信息查询接口名称
chargeTypeStringPER_CALL计费类型
balanceBigDecimal99.9800调用完成后(已扣费)的账户余额(元)
costMsLong1120本次调用耗时(毫秒)

注意:本接口返回的data不含keyword(没有业务入参),与企业系列接口的返回结构略有差异,解析时别写死取keyword。

3.3 list[] 车源对象字段

字段类型示例说明
carNameString长安启源E07 2025款 纯电 两驱 90kWh Max智驾版车型名称(含品牌、年款、配置版本)
imageUrlStringhttps://…/car.jpg车辆图片链接,可直接用于<img src>
mileageString3.20行驶里程,单位:万公里(纯数值文本)
regDateString2024年车辆注册年份
downPaymentString3.80首付价格,单位:万元(纯数值文本)
tagsArray[“新上架”,“准新车”,“0次过户”]车辆标签数组

常见的tags取值:新上架 / 准新车 / 0次过户 / 原厂质保 / 个人一手 / 支持分期 / 7天无理由退车 等,属于平台运营标签,会随车源动态变化,业务侧建议做白名单翻译而非硬编码全部枚举。

两个字段设计上的细节:一是mileage/downPayment是不带单位的数值文本(3.20表示 3.2 万公里、3.80表示 3.8 万元),拼接展示时自己补单位;二是上游的内部数据主键(dataId/dId/cid)不对外返回,需要唯一标识时建议使用carName+regDate+mileage组合键。

四、调用示例

4.1 curl

# 拉满 50 条curl-s-G"https://api.xujian.tech/openapi/usedcar/list"\-H"X-API-Key: 你的APIKey"# 只要 20 条curl-s-G"https://api.xujian.tech/openapi/usedcar/list"\--data-urlencode"limit=20"\-H"X-API-Key: 你的APIKey"

4.2 Java(Hutool)

importcn.hutool.http.HttpRequest;importcn.hutool.json.JSONArray;importcn.hutool.json.JSONObject;importcn.hutool.json.JSONUtil;publicclassUsedCarListClient{privatestaticfinalStringAPI_URL="https://api.xujian.tech/openapi/usedcar/list";/** * 查询二手车车源列表 * * @param apiKey 开发者 API Key * @param limit 期望返回条数,1 ~ 50;传 null 取上限 * @return 车源列表;无车源或查询失败返回 null,且不扣费 */publicstaticJSONArraylist(StringapiKey,Integerlimit){HttpRequestreq=HttpRequest.get(API_URL).header("X-API-Key",apiKey).timeout(20000);if(limit!=null&&limit>0){req.form("limit",limit);}JSONObjectjson=JSONUtil.parseObj(req.execute().body());Integercode=json.getInt("code");if(code==null||code!=0){System.out.println("查询失败(不收费):"+json.getStr("msg"));returnnull;}returnjson.getJSONObject("data").getJSONArray("list");}publicstaticvoidmain(String[]args){JSONArraylist=list("你的APIKey",20);if(list==null){return;}for(inti=0;i<list.size();i++){JSONObjectc=list.getJSONObject(i);System.out.printf("%s | %s万公里 | %s | 首付 %s万%n",c.getStr("carName"),c.getStr("mileage"),c.getStr("regDate"),c.getStr("downPayment"));}}}

4.3 Python

importrequestsdefusedcar_list(api_key:str,limit:int=50):""" 查询二手车车源列表 Args: api_key: 开发者 API Key limit: 期望返回条数,1 ~ 50 Returns: list: 成功返回车源列表;无车源或失败返回 None,且不扣费 """resp=requests.get("https://api.xujian.tech/openapi/usedcar/list",params={"limit":limit},headers={"X-API-Key":api_key},timeout=20,)result=resp.json()ifresult.get("code")!=0:print("查询失败(不收费):",result.get("msg"))returnNonereturnresult["data"]["list"]if__name__=="__main__":forcarinusedcar_list("你的APIKey",20)or[]:print(car["carName"],car["mileage"],car["regDate"],car["tags"])

4.4 JavaScript(浏览器 / Node 18+)

constresp=awaitfetch("https://api.xujian.tech/openapi/usedcar/list?limit=20",{headers:{"X-API-Key":API_KEY},});const{code,msg,data}=awaitresp.json();if(code===0){data.list.forEach((car)=>{console.log(car.carName,`${car.mileage}万公里`,car.tags.join("/"));});}else{console.warn("查询失败(不收费):",msg);}

五、返回示例

5.1 成功返回

{"code":0,"msg":"success","data":{"total":3,"list":[{"carName":"长安启源E07 2025款 纯电 两驱 90kWh Max智驾版","imageUrl":"https://example.com/car/e07-1.jpg","mileage":"0.50","regDate":"2025年","downPayment":"5.60","tags":["新上架","准新车","0次过户","原厂质保"]},{"carName":"大众迈腾 2021款 330TSI DSG 豪华型","imageUrl":"https://example.com/car/magotan-1.jpg","mileage":"3.20","regDate":"2021年","downPayment":"3.80","tags":["个人一手","支持分期"]},{"carName":"丰田凯美瑞 2019款 2.5G 豪华版","imageUrl":"https://example.com/car/camry-1.jpg","mileage":"6.80","regDate":"2019年","downPayment":"2.90","tags":["7天无理由退车"]}],"apiCode":"usedcar.list","apiName":"二手车信息查询","chargeType":"PER_CALL","balance":99.9800,"costMs":1120}}

5.2 无可用车源(不收费)

{"code":500,"msg":"未查询到可用车源,请稍后重试;本次调用不计费","data":null}

六、典型应用场景

6.1 车源同步落库(含去重键)

由于没有返回业务主键,落库时用组合键去重:

defsync_cars(api_key:str,db:dict,limit:int=50)->int:"""把车源同步到本地字典,返回新增条数"""cars=usedcar_list(api_key,limit)or[]added=0forcarincars:# 车型 + 年份 + 里程 组合作为去重键key=f"{car['carName']}|{car['regDate']}|{car['mileage']}"ifkeynotindb:db[key]=car added+=1returnadded

图片链接建议不要长期外链:第三方图床随时可能失效或加防盗链,同步时把图片下载到自己的对象存储更稳。

6.2 本地筛选(替代接口筛选参数)

接口没提供筛选入参,但总数据量最多 50 条,本地过滤完全够:

functionpick(cars,{maxMileage,minYear,maxDownPayment,tags}){returncars.filter((c)=>{constyear=Number(String(c.regDate).replace("年",""));constmileage=Number(c.mileage);constpay=Number(c.downPayment);return((!maxMileage||mileage<=maxMileage)&&(!minYear||year>=minYear)&&(!maxDownPayment||pay<=maxDownPayment)&&(!tags||tags.some((t)=>c.tags.includes(t))));});}

6.3 车型名称结构化

carName是长文本,展示前通常要拆出品牌、年款、配置三段:

privatestaticString[]splitCarName(StringcarName){// 长安启源E07 2025款 纯电 两驱 90kWh Max智驾版 →// [品牌+车型前缀, 2025款, 剩余配置描述]String[]parts=carName.split(" ",3);String[]arr=newString[3];arr[0]=parts.length>0?parts[0]:"";// 长安启源E07arr[1]=parts.length>1?parts[1]:"";// 2025款arr[2]=parts.length>2?parts[2]:"";// 纯电 两驱 90kWh Max智驾版returnarr;}

品牌字典可以用这张拆分结果去建:把第一段与已知品牌表做前缀匹配即可。

6.4 行情统计(首付与里程分布)

fromcollectionsimportCounterdefstats(api_key:str,limit:int=50)->dict:"""按注册年份统计车源数量与平均首付"""cars=usedcar_list(api_key,limit)or[]by_year=Counter(c["regDate"]forcincars)pays=[float(c["downPayment"])forcincarsifc.get("downPayment")]return{"byYear":dict(by_year),"avgDownPayment":round(sum(pays)/len(pays),2)ifpayselse0,}

七、提升可用性的几条实践建议

  1. limit别贪心。上限 50 条,实际场景(选品抽查、行情抽样)用 20 ~ 30 条足够,还能省带宽与解析开销。
  2. 数值字段已统一单位。mileage万公里、downPayment万元,直接Float.parseFloat即可,不要再去解析单位文本。
  3. 图片尽快转存。第三方图片链接有防盗链与过期风险,展示型业务建议同步时转存到自己的 OSS。
  4. 标签做白名单翻译。tags是运营标签、会动态增减,未知标签直接原样展示比写死枚举好。
  5. 定时任务做好幂等。没有业务主键,务必用组合键(carName+regDate+mileage)去重。
  6. 区分「无车源」与「服务异常」。前者是未查询到可用车源……本次调用不计费,后者是数据服务暂时不可用……,重试策略应不同。

八、错误码与排查

codemsg(示例)处理建议
0success调用成功
500缺少请求头 X-API-Key在请求头补充X-API-Key
500API Key 无效 / API Key 已停用检查 Key 是否正确,或在控制台重新启用
500客户不存在或已停用联系平台确认账号状态
500接口不存在或已停用确认usedcar.list当前是否维护中
500余额不足,请先充值按次计费接口调用前校验余额,余额不足不扣费,充值后重试
500未查询到可用车源……上游暂无车源,稍后重试;不计费
500二手车服务未启用 / 二手车服务未配置(上游凭证缺失)平台侧配置问题,稍后重试;不计费
500数据服务暂时不可用(请求上游超时或网络异常)稍后重试,不计费

九、计费与接入

项目说明
单次费用0.01 元/次
计费方式按次计费,调用前校验余额,返回车源后才扣费
不计费场景服务暂时不可用、上游返回空车源列表
返回条数最多 50 条,用limit收敛

接入流程:注册开发者账号 → 控制台创建 API Key → 请求头带上X-API-Key即可调用,无需签名或加密。控制台可查看调用量、扣费流水与余额。

控制台地址:https://api.xujian.tech;接口接入、数据与充值相关问题可联系微信xujian_cq。

十、总结

车源数据的难点从来不在算法,而在「拿到干净的结构化数据」这一层。这个接口的价值就是把渲染型页面里最难处理的部分——车型长文本、图片链接、里程与首付的单位统一、动态运营标签——提前处理好,调用方拿到 JSON 就能直接入库或渲染。

几个关键取舍值得留意:

  • 无车源不收费:定时任务遇到空结果不会产生费用;
  • 单位收敛到字段语义:mileage万公里、downPayment万元,都是可直接 parse 的数值文本;
  • 不放一堆看不懂的筛选参数:总数据量上限 50 条,本地过滤比堆接口参数更灵活;
  • 内部标识不外传:上游dataId/cid等主键不返回,避免调用方依赖一个随时可能变的内部约定。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询