汽车之家item_search - 根据地区获取二手车列表接口对接全攻略:从入门到精通

简介: 汽车之家二手车搜索接口(item_search)支持按地区、品牌、价格、车龄等多维度精准筛选,返回结构化车辆数据;提供分页、排序、字段定制及多语言SDK(Python/Java/PHP),适用于比价平台、推荐系统等场景。

一、接口概览
1.1 接口简介
item_search接口是汽车之家开放平台的核心接口之一,专门用于二手车信息检索。支持按地区、品牌、价格、车龄等多维度筛选二手车,返回结构化的车辆列表信息。
1.2 核心功能
✅ 地区筛选:按省市区精准定位二手车源
✅ 多条件搜索:品牌、车系、价格、里程、车龄等
✅ 分页查询:支持大数据量的分页加载
✅ 排序功能:按价格、里程、发布时间等排序
✅ 字段选择:可指定返回字段,优化网络传输
二、准备工作
2.1 环境配置

requirements.txt

requests>=2.28.0
python-dotenv>=1.0.0
pydantic>=2.0.0
aiohttp>=3.8.0
redis>=4.5.0
2.2 认证配置

config.py

import os
from dotenv import load_dotenv

load_dotenv()

class Config:

# 汽车之家API配置
AUTOHOME_APP_KEY = os.getenv('AUTOHOME_APP_KEY')
AUTOHOME_APP_SECRET = os.getenv('AUTOHOME_APP_SECRET')
AUTOHOME_API_BASE = os.getenv('AUTOHOME_API_BASE', 
    'https://openapi.autohome.com.cn/api/v1'
)

# 请求配置
REQUEST_TIMEOUT = 30
MAX_RETRIES = 3
DEFAULT_PAGE_SIZE = 20
MAX_PAGE_SIZE = 100

# 缓存配置
CACHE_TTL = 3600  # 1小时

三、接口详解
3.1 接口地址
GET /usedcar/search
3.2 请求参数详解
基础参数
参数名

类型

必填

说明

示例

app_key

string

应用标识

autohome_app_2024

timestamp

int

时间戳

1706774400

sign

string

请求签名

详见签名算法

format

string

返回格式

json(默认)

version

string

API版本

1.0
搜索参数
参数名

类型

必填

说明

示例

province_id

int

省份ID

11(北京)

city_id

int

城市ID

1101(北京市)

district_id

int

区县ID

110101(东城区)

brand_id

int

品牌ID

1(奥迪)

series_id

int

车系ID

10(A6L)

min_price

float

最低价格(万元)

10.0

max_price

float

最高价格(万元)

50.0

min_mileage

int

最低里程(万公里)

1

max_mileage

int

最高里程(万公里)

20

min_year

int

最低年份

2018

max_year

int

最高年份

2023

fuel_type

string

燃油类型

汽油/柴油/新能源

transmission

string

变速箱类型

自动/手动

body_type

string

车身类型

轿车/SUV/MPV

keyword

string

搜索关键词

"奥迪A6L 2020款"

sort_field

string

排序字段

price/mileage/year/publish_time

sort_order

string

排序方向

asc/desc(默认desc)

page_no

int

页码

1(默认)

page_size

int

每页条数

20(默认)

fields

string

返回字段

id,title,price,mileage,year
四、完整代码实现
4.1 Python完整实现
import requests
import time
import hashlib
import hmac
import json
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta
from dataclasses import dataclass
from urllib.parse import urlencode
import redis

@dataclass
class UsedCarBasicInfo:
"""二手车基本信息"""
car_id: int
title: str
price: float
original_price: float
mileage: float
year: int
month: int
city: str
district: str
brand: str
series: str
model: str
fuel_type: str
transmission: str
body_type: str
publish_time: str
thumbnail_url: str
source_type: str # 个人/商家

@dataclass
class UsedCarDetail:
"""二手车详细信息"""
basic_info: UsedCarBasicInfo
images: List[str]
specs: Dict[str, str]
seller_info: Dict[str, Any]
inspection_report: Dict[str, Any]

@dataclass
class SearchResult:
"""搜索结果"""
success: bool
code: int
message: str
data: Dict[str, Any]
used_cars: List[UsedCarBasicInfo]
pagination: Dict[str, Any]

class AutoHomeUsedCarAPI:
"""汽车之家二手车API客户端"""

def __init__(self, app_key: str, app_secret: str, sandbox: bool = True, redis_client=None):
    self.app_key = app_key
    self.app_secret = app_secret
    self.base_url = "https://sandbox-openapi.autohome.com.cn" if sandbox else "https://openapi.autohome.com.cn"
    self.session = requests.Session()
    self.session.headers.update({
        'User-Agent': 'AutoHome-UsedCar-API/1.0',
        'Accept': 'application/json'
    })
    self.redis = redis_client
    self._access_token = None
    self._token_expires = None

def _generate_signature(self, params: Dict[str, Any], timestamp: int) -> str:
    """生成请求签名"""
    # 排序参数
    sorted_params = sorted(params.items())
    param_str = '&'.join([f"{k}={v}" for k, v in sorted_params])

    # 构建签名字符串
    sign_str = f"{self.app_key}{param_str}{timestamp}{self.app_secret}"

    # 计算HMAC-SHA256签名
    signature = hmac.new(
        self.app_secret.encode('utf-8'),
        sign_str.encode('utf-8'),
        hashlib.sha256
    ).hexdigest()

    return signature

def _get_access_token(self) -> str:
    """获取访问令牌"""
    # 检查token是否有效
    if self._access_token and self._token_expires and self._token_expires > datetime.now():
        return self._access_token

    # 获取新token
    timestamp = int(time.time())
    params = {
        'app_key': self.app_key,
        'timestamp': timestamp,
        'grant_type': 'client_credentials'
    }

    # 生成签名
    signature = self._generate_signature(params, timestamp)
    params['sign'] = signature

    # 请求token
    url = f"{self.base_url}/oauth/token"
    response = self.session.post(url, data=params)

    if response.status_code == 200:
        data = response.json()
        self._access_token = data['access_token']
        self._token_expires = datetime.now() + timedelta(seconds=data['expires_in'] - 300)  # 提前5分钟过期
        return self._access_token
    else:
        raise Exception(f"获取token失败: {response.status_code} - {response.text}")

def search_used_cars(
    self,
    province_id: Optional[int] = None,
    city_id: Optional[int] = None,
    district_id: Optional[int] = None,
    brand_id: Optional[int] = None,
    series_id: Optional[int] = None,
    min_price: Optional[float] = None,
    max_price: Optional[float] = None,
    min_mileage: Optional[float] = None,
    max_mileage: Optional[float] = None,
    min_year: Optional[int] = None,
    max_year: Optional[int] = None,
    fuel_type: Optional[str] = None,
    transmission: Optional[str] = None,
    body_type: Optional[str] = None,
    keyword: Optional[str] = None,
    sort_field: str = "publish_time",
    sort_order: str = "desc",
    page_no: int = 1,
    page_size: int = 20,
    fields: Optional[List[str]] = None
) -> SearchResult:
    """
    搜索二手车

    Args:
        province_id: 省份ID
        city_id: 城市ID
        district_id: 区县ID
        brand_id: 品牌ID
        series_id: 车系ID
        min_price: 最低价格(万元)
        max_price: 最高价格(万元)
        min_mileage: 最低里程(万公里)
        max_mileage: 最高里程(万公里)
        min_year: 最低年份
        max_year: 最高年份
        fuel_type: 燃油类型
        transmission: 变速箱类型
        body_type: 车身类型
        keyword: 搜索关键词
        sort_field: 排序字段
        sort_order: 排序方向
        page_no: 页码
        page_size: 每页条数
        fields: 返回字段列表

    Returns:
        搜索结果
    """
    # 获取访问令牌
    access_token = self._get_access_token()

    # 构建请求参数
    params = {
        'app_key': self.app_key,
        'timestamp': int(time.time()),
        'format': 'json',
        'version': '1.0',
        'sort_field': sort_field,
        'sort_order': sort_order,
        'page_no': page_no,
        'page_size': min(page_size, Config.MAX_PAGE_SIZE)
    }

    # 添加可选参数
    if province_id:
        params['province_id'] = province_id
    if city_id:
        params['city_id'] = city_id
    if district_id:
        params['district_id'] = district_id
    if brand_id:
        params['brand_id'] = brand_id
    if series_id:
        params['series_id'] = series_id
    if min_price:
        params['min_price'] = min_price
    if max_price:
        params['max_price'] = max_price
    if min_mileage:
        params['min_mileage'] = min_mileage
    if max_mileage:
        params['max_mileage'] = max_mileage
    if min_year:
        params['min_year'] = min_year
    if max_year:
        params['max_year'] = max_year
    if fuel_type:
        params['fuel_type'] = fuel_type
    if transmission:
        params['transmission'] = transmission
    if body_type:
        params['body_type'] = body_type
    if keyword:
        params['keyword'] = keyword
    if fields:
        params['fields'] = ','.join(fields)

    # 生成签名
    signature = self._generate_signature(params, params['timestamp'])
    params['sign'] = signature

    # 添加认证头
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }

    # 发送请求
    url = f"{self.base_url}/api/v1/usedcar/search"

    try:
        response = self.session.get(
            url,
            params=params,
            headers=headers,
            timeout=Config.REQUEST_TIMEOUT
        )

        if response.status_code == 200:
            result = response.json()

            # 解析结果
            used_cars = self._parse_used_cars(result.get('data', {}).get('list', []))
            pagination = result.get('data', {}).get('pagination', {})

            return SearchResult(
                success=result.get('success', False),
                code=result.get('code', 0),
                message=result.get('message', ''),
                data=result.get('data', {}),
                used_cars=used_cars,
                pagination=pagination
            )
        elif response.status_code == 401:
            # Token过期,重新获取
            self._access_token = None
            return self.search_used_cars(
                province_id=province_id, city_id=city_id, district_id=district_id,
                brand_id=brand_id, series_id=series_id, min_price=min_price, max_price=max_price,
                min_mileage=min_mileage, max_mileage=max_mileage, min_year=min_year, max_year=max_year,
                fuel_type=fuel_type, transmission=transmission, body_type=body_type, keyword=keyword,
                sort_field=sort_field, sort_order=sort_order, page_no=page_no, page_size=page_size,
                fields=fields
            )
        else:
            return SearchResult(
                success=False,
                code=response.status_code,
                message=f"HTTP {response.status_code}",
                data={},
                used_cars=[],
                pagination={}
            )

    except requests.exceptions.Timeout:
        return SearchResult(
            success=False,
            code=408,
            message="请求超时",
            data={},
            used_cars=[],
            pagination={}
        )
    except requests.exceptions.RequestException as e:
        return SearchResult(
            success=False,
            code=500,
            message=f"网络请求异常: {str(e)}",
            data={},
            used_cars=[],
            pagination={}
        )

def _parse_used_cars(self, car_list: List[Dict[str, Any]]) -> List[UsedCarBasicInfo]:
    """解析二手车列表数据"""
    used_cars = []

    for car_data in car_list:
        try:
            basic_info = UsedCarBasicInfo(
                car_id=car_data.get('id'),
                title=car_data.get('title', ''),
                price=car_data.get('price', 0),
                original_price=car_data.get('original_price', 0),
                mileage=car_data.get('mileage', 0),
                year=car_data.get('year', 0),
                month=car_data.get('month', 0),
                city=car_data.get('city', ''),
                district=car_data.get('district', ''),
                brand=car_data.get('brand', {}).get('name', ''),
                series=car_data.get('series', {}).get('name', ''),
                model=car_data.get('model', ''),
                fuel_type=car_data.get('fuel_type', ''),
                transmission=car_data.get('transmission', ''),
                body_type=car_data.get('body_type', ''),
                publish_time=car_data.get('publish_time', ''),
                thumbnail_url=car_data.get('thumbnail_url', ''),
                source_type=car_data.get('source_type', '个人')
            )
            used_cars.append(basic_info)
        except Exception as e:
            print(f"解析车辆数据失败: {e}, 数据: {car_data}")
            continue

    return used_cars

def search_all_used_cars(
    self,
    max_pages: int = 10,
    **search_params
) -> List[UsedCarBasicInfo]:
    """
    获取所有符合条件的二手车(自动处理分页)

    Args:
        max_pages: 最大页数限制
        **search_params: 搜索参数

    Returns:
        二手车列表
    """
    all_cars = []
    page_no = 1

    while page_no <= max_pages:
        result = self.search_used_cars(page_no=page_no, **search_params)

        if not result.success:
            print(f"第{page_no}页查询失败: {result.message}")
            break

        # 添加当前页数据
        all_cars.extend(result.used_cars)
        pagination = result.pagination

        print(f"已获取第{page_no}页,共{len(result.used_cars)}条,总计{len(all_cars)}条")

        # 检查是否还有下一页
        has_next = pagination.get('has_next', False)
        total_pages = pagination.get('total_pages', 0)

        if not has_next or page_no >= total_pages:
            break

        page_no += 1

        # 避免请求过于频繁
        time.sleep(0.5)

    return all_cars

def get_used_car_detail(self, car_id: int) -> Optional[UsedCarDetail]:
    """
    获取二手车详细信息
    """
    # 获取访问令牌
    access_token = self._get_access_token()

    # 构建请求
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }

    url = f"{self.base_url}/api/v1/usedcar/detail/{car_id}"

    try:
        response = self.session.get(url, headers=headers, timeout=30)

        if response.status_code == 200:
            data = response.json().get('data', {})

            # 解析基础信息
            basic_info = UsedCarBasicInfo(
                car_id=data.get('id'),
                title=data.get('title', ''),
                price=data.get('price', 0),
                original_price=data.get('original_price', 0),
                mileage=data.get('mileage', 0),
                year=data.get('year', 0),
                month=data.get('month', 0),
                city=data.get('city', ''),
                district=data.get('district', ''),
                brand=data.get('brand', {}).get('name', ''),
                series=data.get('series', {}).get('name', ''),
                model=data.get('model', ''),
                fuel_type=data.get('fuel_type', ''),
                transmission=data.get('transmission', ''),
                body_type=data.get('body_type', ''),
                publish_time=data.get('publish_time', ''),
                thumbnail_url=data.get('thumbnail_url', ''),
                source_type=data.get('source_type', '个人')
            )

            # 解析详细信息
            images = data.get('images', [])
            specs = data.get('specs', {})
            seller_info = data.get('seller_info', {})
            inspection_report = data.get('inspection_report', {})

            return UsedCarDetail(
                basic_info=basic_info,
                images=images,
                specs=specs,
                seller_info=seller_info,
                inspection_report=inspection_report
            )
        else:
            return None

    except Exception as e:
        print(f"获取车辆详情失败: {e}")
        return None

使用示例

def demo_used_car_api():
"""二手车API使用演示"""

# 初始化客户端
client = AutoHomeUsedCarAPI(
    app_key=Config.AUTOHOME_APP_KEY,
    app_secret=Config.AUTOHOME_APP_SECRET,
    sandbox=True
)

print("=== 示例1:按地区搜索二手车 ===")
result = client.search_used_cars(
    province_id=11,  # 北京
    city_id=1101,    # 北京市
    min_price=10,
    max_price=30,
    min_year=2018,
    max_year=2022,
    page_size=5
)

if result.success:
    for car in result.used_cars:
        print(f"{car.brand} {car.series} - {car.price}万 - {car.mileage}万公里 - {car.year}年")

print("\n=== 示例2:按品牌搜索 ===")
result = client.search_used_cars(
    brand_id=1,  # 奥迪
    min_price=20,
    max_price=50,
    sort_field="price",
    sort_order="asc"
)

print("\n=== 示例3:获取所有符合条件的二手车 ===")
all_cars = client.search_all_used_cars(
    province_id=11,
    min_price=15,
    max_price=25,
    min_year=2019,
    max_mileage=15
)
print(f"共找到 {len(all_cars)} 辆符合条件的二手车")

if name == "main":
demo_used_car_api()
4.2 Java实现
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;

public class AutoHomeUsedCarClient {
private static final Logger logger = LoggerFactory.getLogger(AutoHomeUsedCarClient.class);

private final String appKey;
private final String appSecret;
private final String baseUrl;
private final OkHttpClient httpClient;
private final ObjectMapper objectMapper;

private String accessToken;
private LocalDateTime tokenExpires;

public AutoHomeUsedCarClient(String appKey, String appSecret, boolean sandbox) {
    this.appKey = appKey;
    this.appSecret = appSecret;
    this.baseUrl = sandbox ? 
        "https://sandbox-openapi.autohome.com.cn" : 
        "https://openapi.autohome.com.cn";

    this.httpClient = new OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(30, TimeUnit.SECONDS)
            .build();

    this.objectMapper = new ObjectMapper();
    this.objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}

public UsedCarSearchResult searchUsedCars(UsedCarSearchParams params) throws IOException {
    // 获取访问令牌
    String token = getAccessToken();

    // 构建请求参数
    Map<String, Object> requestParams = new HashMap<>();
    requestParams.put("app_key", appKey);
    requestParams.put("timestamp", System.currentTimeMillis() / 1000);
    requestParams.put("format", "json");
    requestParams.put("version", "1.0");

    // 添加搜索参数
    if (params.getProvinceId() != null) {
        requestParams.put("province_id", params.getProvinceId());
    }
    if (params.getCityId() != null) {
        requestParams.put("city_id", params.getCityId());
    }
    // ... 其他参数

    // 生成签名
    String signature = generateSignature(requestParams, (Long) requestParams.get("timestamp"));
    requestParams.put("sign", signature);

    // 构建请求URL
    HttpUrl.Builder urlBuilder = HttpUrl.parse(baseUrl + "/api/v1/usedcar/search").newBuilder();
    for (Map.Entry<String, Object> param : requestParams.entrySet()) {
        urlBuilder.addQueryParameter(param.getKey(), param.getValue().toString());
    }

    // 发送请求
    Request request = new Request.Builder()
            .url(urlBuilder.build())
            .addHeader("Authorization", "Bearer " + token)
            .addHeader("User-Agent", "AutoHome-Java-Client/1.0")
            .build();

    try (Response response = httpClient.newCall(request).execute()) {
        if (response.isSuccessful()) {
            String responseBody = response.body().string();
            Map<String, Object> result = objectMapper.readValue(responseBody, Map.class);
            return parseSearchResult(result);
        } else {
            throw new IOException("请求失败: " + response.code());
        }
    }
}

// 省略其他方法...

}

class UsedCarSearchParams {
private Integer provinceId;
private Integer cityId;
private Integer districtId;
private Integer brandId;
private Integer seriesId;
private Double minPrice;
private Double maxPrice;
private Double minMileage;
private Double maxMileage;
private Integer minYear;
private Integer maxYear;
private String fuelType;
private String transmission;
private String bodyType;
private String keyword;
private String sortField = "publish_time";
private String sortOrder = "desc";
private Integer pageNo = 1;
private Integer pageSize = 20;

// 省略getter/setter方法

}
4.3 PHP实现
<?php
class AutoHomeUsedCarService
{
private $appKey;
private $appSecret;
private $baseUrl;
private $accessToken;
private $tokenExpires;

public function __construct($appKey, $appSecret, $sandbox = true)
{
    $this->appKey = $appKey;
    $this->appSecret = $appSecret;
    $this->baseUrl = $sandbox 
        ? 'https://sandbox-openapi.autohome.com.cn'
        : 'https://openapi.autohome.com.cn';
}

public function searchUsedCars($params = [])
{
    // 获取访问令牌
    $token = $this->getAccessToken();

    // 构建请求参数
    $requestParams = [
        'app_key' => $this->appKey,
        'timestamp' => time(),
        'format' => 'json',
        'version' => '1.0'
    ];

    // 合并搜索参数
    $requestParams = array_merge($requestParams, $params);

    // 生成签名
    $signature = $this->generateSignature($requestParams);
    $requestParams['sign'] = $signature;

    // 发送请求
    $url = $this->baseUrl . '/api/v1/usedcar/search?' . http_build_query($requestParams);

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $token,
            'User-Agent: AutoHome-PHP-Client/1.0'
        ]
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 200) {
        return json_decode($response, true);
    } else {
        throw new Exception("请求失败: HTTP {$httpCode}");
    }
}

private function getAccessToken()
{
    // 检查token是否有效
    if ($this->accessToken && $this->tokenExpires && $this->tokenExpires > time()) {
        return $this->accessToken;
    }

    // 获取新token
    $timestamp = time();
    $params = [
        'app_key' => $this->appKey,
        'timestamp' => $timestamp,
        'grant_type' => 'client_credentials'
    ];

    $signature = $this->generateSignature($params);
    $params['sign'] = $signature;

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $this->baseUrl . '/oauth/token',
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => http_build_query($params),
        CURLOPT_TIMEOUT => 30
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($httpCode === 200) {
        $result = json_decode($response, true);
        $this->accessToken = $result['access_token'];
        $this->tokenExpires = time() + $result['expires_in'] - 300; // 提前5分钟过期
        return $this->accessToken;
    } else {
        throw new Exception("获取token失败: HTTP {$httpCode}");
    }
}

private function generateSignature($params)
{
    // 移除sign参数并排序
    unset($params['sign']);
    ksort($params);

    // 拼接参数字符串
    $paramStr = '';
    foreach ($params as $key => $value) {
        $paramStr .= $key . '=' . $value . '&';
    }
    $paramStr = rtrim($paramStr, '&');

    // 构建签名字符串
    $signStr = $this->appKey . $paramStr . $params['timestamp'] . $this->appSecret;

    // 计算HMAC-SHA256
    return hash_hmac('sha256', $signStr, $this->appSecret);
}

}

// 使用示例
try {
$service = new AutoHomeUsedCarService('your_app_key', 'your_app_secret');

$result = $service->searchUsedCars([
    'province_id' => 11,
    'city_id' => 1101,
    'min_price' => 10,
    'max_price' => 30,
    'min_year' => 2018,
    'page_size' => 10
]);

if ($result['success']) {
    foreach ($result['data']['list'] as $car) {
        echo "{$car['brand']['name']} {$car['series']['name']} - {$car['price']}万\n";
    }
}

} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
?>
五、返回结果解析
5.1 成功响应示例
{
"success": true,
"code": 200,
"message": "成功",
"data": {
"list": [
{
"id": 12345,
"title": "2020款 奥迪A6L 45 TFSI 臻选致雅型",
"price": 28.5,
"original_price": 45.8,
"mileage": 5.2,
"year": 2020,
"month": 6,
"city": "北京市",
"district": "朝阳区",
"brand": {
"id": 1,
"name": "奥迪"
},
"series": {
"id": 10,
"name": "A6L"
},
"model": "45 TFSI 臻选致雅型",
"fuel_type": "汽油",
"transmission": "自动",
"body_type": "轿车",
"publish_time": "2026-01-15 14:30:00",
"thumbnail_url": "https://img.autohome.com.cn/usedcar/12345.jpg",
"source_type": "商家"
}
],
"pagination": {
"page_no": 1,
"page_size": 20,
"total_count": 125,
"total_pages": 7,
"has_next": true,
"has_previous": false
},
"summary": {
"avg_price": 25.8,
"avg_mileage": 6.5,
"avg_year": 2019.5,
"brand_distribution": {
"奥迪": 15,
"宝马": 12,
"奔驰": 10
}
}
}
}
5.2 错误响应示例
{
"success": false,
"code": 400,
"message": "参数错误:province_id无效",
"data": null
}
5.3 状态码说明
状态码

说明

处理建议

200

成功

-

400

参数错误

检查请求参数格式

401

认证失败

检查API密钥和签名

403

权限不足

检查API权限范围

404

数据不存在

检查搜索条件

429

请求频率超限

降低请求频率

500

服务器错误

稍后重试
六、高级功能实现
6.1 智能搜索建议
class IntelligentUsedCarSearch:
"""智能二手车搜索服务"""

def __init__(self, api_client):
    self.client = api_client
    self.search_history = []

def smart_search(self, query: str, location: str = None) -> SearchResult:
    """
    智能搜索:自动识别搜索类型

    Args:
        query: 搜索查询字符串
        location: 地区信息

    Returns:
        搜索结果
    """
    # 解析查询类型
    search_type = self._detect_search_type(query)

    # 构建搜索参数
    params = self._build_search_params(query, search_type, location)

    # 执行搜索
    result = self.client.search_used_cars(**params)

    # 记录搜索历史
    self._record_search_history(query, search_type, result)

    return result

def _detect_search_type(self, query: str) -> str:
    """自动识别搜索类型"""
    import re

    # 检查是否为价格范围
    if re.match(r'^\d+-\d+万$', query):
        return 'price_range'

    # 检查是否为年份范围
    if re.match(r'^\d+-\d+年$', query):
        return 'year_range'

    # 检查是否为里程范围
    if re.match(r'^\d+-\d+万公里$', query):
        return 'mileage_range'

    # 检查是否为品牌+车系
    brand_patterns = ['奥迪', '宝马', '奔驰', '大众', '丰田', '本田']
    for brand in brand_patterns:
        if brand in query:
            return 'brand_model'

    # 默认为关键词搜索
    return 'keyword'

def _build_search_params(self, query: str, search_type: str, location: str) -> Dict[str, Any]:
    """根据搜索类型构建参数"""
    params = {}
    import re

    if search_type == 'price_range':
        # 解析价格范围
        match = re.match(r'^(\d+)-(\d+)万$', query)
        if match:
            params['min_price'] = float(match.group(1))
            params['max_price'] = float(match.group(2))

    elif search_type == 'year_range':
        # 解析年份范围
        match = re.match(r'^(\d+)-(\d+)年$', query)
        if match:
            params['min_year'] = int(match.group(1))
            params['max_year'] = int(match.group(2))

    elif search_type == 'mileage_range':
        # 解析里程范围
        match = re.match(r'^(\d+)-(\d+)万公里$', query)
        if match:
            params['min_mileage'] = float(match.group(1))
            params['max_mileage'] = float(match.group(2))

    elif search_type == 'brand_model':
        # 解析品牌和车型
        params['keyword'] = query

    else:
        params['keyword'] = query

    # 添加地区信息
    if location:
        # 这里可以集成地理编码服务将地址转换为ID
        pass

    return params

6.2 数据缓存优化
import redis
from functools import lru_cache

class CachedUsedCarAPI(AutoHomeUsedCarAPI):
"""带缓存的二手车API"""

def __init__(self, app_key, app_secret, redis_client, sandbox=True):
    super().__init__(app_key, app_secret, sandbox)
    self.redis = redis_client
    self.cache_prefix = "autohome:usedcar:"

def search_used_cars_cached(self, cache_key: str, **params) -> SearchResult:
    """
    带缓存的二手车搜索
    """
    # 检查缓存
    cached = self.redis.get(cache_key)
    if cached:
        data = json.loads(cached)
        return SearchResult(**data)

    # 调用API
    result = super().search_used_cars(**params)

    # 缓存结果
    if result.success:
        # 根据数据量设置缓存时间
        ttl = self._calculate_ttl(result)
        self.redis.setex(
            cache_key,
            ttl,
            json.dumps(result.__dict__)
        )

    return result

def _calculate_ttl(self, result: SearchResult) -> int:
    """根据搜索结果计算缓存时间"""
    total_count = result.pagination.get('total_count', 0)

    if total_count == 0:
        return 1800  # 30分钟
    elif total_count <= 100:
        return 3600  # 1小时
    else:
        return 7200  # 2小时

def get_cache_key(self, **params) -> str:
    """生成缓存键"""
    # 移除分页参数
    cache_params = params.copy()
    cache_params.pop('page_no', None)
    cache_params.pop('page_size', None)

    # 生成唯一键
    param_str = json.dumps(cache_params, sort_keys=True)
    return f"{self.cache_prefix}{hashlib.md5(param_str.encode()).hexdigest()}"

6.3 批量处理优化
from concurrent.futures import ThreadPoolExecutor, as_completed

class BatchUsedCarProcessor:
"""批量二手车处理器"""

def __init__(self, api_client):
    self.client = api_client

def batch_search_by_regions(
    self,
    regions: List[Dict[str, int]],
    search_params: Dict[str, Any],
    max_workers: int = 3
) -> Dict[str, List[UsedCarBasicInfo]]:
    """
    按地区批量搜索二手车

    Args:
        regions: 地区列表 [{"province_id": 11, "city_id": 1101}, ...]
        search_params: 搜索参数
        max_workers: 最大并发数

    Returns:
        按地区分组的搜索结果
    """
    results = {}

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        # 提交所有地区搜索任务
        future_to_region = {
            executor.submit(
                self.client.search_all_used_cars,
                **{**search_params, **region}
            ): region
            for region in regions
        }

        # 收集结果
        for future in as_completed(future_to_region):
            region = future_to_region[future]
            try:
                region_cars = future.result(timeout=300)  # 5分钟超时
                region_key = f"{region.get('province_id')}_{region.get('city_id')}"
                results[region_key] = region_cars
            except Exception as e:
                print(f"地区 {region} 搜索失败: {e}")

    return results

def analyze_regional_prices(
    self,
    regional_results: Dict[str, List[UsedCarBasicInfo]]
) -> Dict[str, Dict[str, float]]:
    """
    分析地区价格差异
    """
    analysis = {}

    for region_key, cars in regional_results.items():
        if not cars:
            continue

        prices = [car.price for car in cars if car.price > 0]
        mileages = [car.mileage for car in cars if car.mileage > 0]
        years = [car.year for car in cars if car.year > 0]

        analysis[region_key] = {
            'avg_price': sum(prices) / len(prices) if prices else 0,
            'avg_mileage': sum(mileages) / len(mileages) if mileages else 0,
            'avg_year': sum(years) / len(years) if years else 0,
            'car_count': len(cars)
        }

    return analysis

七、实战应用场景
7.1 二手车比价平台
class UsedCarPriceComparator:
"""二手车比价平台"""

def __init__(self, api_client):
    self.client = api_client
    self.price_history = {}

def compare_prices_by_model(
    self,
    brand: str,
    model: str,
    regions: List[Dict[str, int]],
    year_range: Tuple[int, int] = (2018, 2023)
) -> Dict[str, Any]:
    """
    按车型比较地区价格差异
    """
    # 搜索各地区的同款车型
    search_params = {
        'min_year': year_range[0],
        'max_year': year_range[1],
        'keyword': f"{brand} {model}"
    }

    regional_results = self.client.batch_search_by_regions(regions, search_params)

    # 分析价格差异
    price_analysis = self.client.analyze_regional_prices(regional_results)

    # 生成价格对比报告
    report = {
        'brand': brand,
        'model': model,
        'year_range': year_range,
        'regional_prices': price_analysis,
        'recommendation': self._generate_recommendation(price_analysis)
    }

    return report

def track_price_trend(
    self,
    car_id: int,
    duration_days: int = 30
) -> List[Dict[str, Any]]:
    """
    跟踪二手车价格趋势
    """
    price_history = []

    # 模拟获取历史价格数据
    for i in range(duration_days, 0, -1):
        # 实际应用中可以从数据库获取历史数据
        # 这里简化实现
        price_point = {
            'date': (datetime.now() - timedelta(days=i)).strftime('%Y-%m-%d'),
            'price': 25.5 + random.uniform(-1, 1),  # 模拟价格波动
            'market_avg': 26.0 + random.uniform(-0.5, 0.5)
        }
        price_history.append(price_point)

    return price_history

7.2 二手车推荐系统
class UsedCarRecommender:
"""二手车推荐系统"""

def __init__(self, api_client):
    self.client = api_client

def recommend_cars_by_budget(
    self,
    budget: float,
    user_preferences: Dict[str, Any],
    region: Dict[str, int]
) -> List[UsedCarBasicInfo]:
    """
    根据预算推荐二手车
    """
    # 构建搜索参数
    search_params = {
        'province_id': region.get('province_id'),
        'city_id': region.get('city_id'),
        'min_price': max(1, budget * 0.7),  # 预算的70%作为最低价
        'max_price': budget * 1.1,  # 预算的110%作为最高价
        'min_year': user_preferences.get('min_year', 2018),
        'max_mileage': user_preferences.get('max_mileage', 15),
        'fuel_type': user_preferences.get('fuel_type'),
        'body_type': user_preferences.get('body_type'),
        'sort_field': 'publish_time',
        'sort_order': 'desc'
    }

    # 执行搜索
    result = self.client.search_used_cars(**search_params)

    if not result.success:
        return []

    cars = result.used_cars

    # 应用推荐算法
    recommended_cars = self._apply_recommendation_algorithm(cars, user_preferences)

    return recommended_cars[:10]  # 返回前10个推荐

def _apply_recommendation_algorithm(
    self,
    cars: List[UsedCarBasicInfo],
    preferences: Dict[str, Any]
) -> List[UsedCarBasicInfo]:
    """应用推荐算法"""
    scored_cars = []

    for car in cars:
        score = 0

        # 价格得分(越接近预算上限得分越高)
        target_price = preferences.get('target_price', car.price)
        price_diff = abs(car.price - target_price)
        price_score = max(0, 100 - price_diff * 10)
        score += price_score * 0.3

        # 车龄得分
        current_year = datetime.now().year
        car_age = current_year - car.year
        age_score = max(0, 100 - car_age * 5)
        score += age_score * 0.25

        # 里程得分
        mileage_score = max(0, 100 - car.mileage * 2)
        score += mileage_score * 0.2

        # 品牌偏好得分
        preferred_brands = preferences.get('preferred_brands', [])
        if car.brand in preferred_brands:
            score += 50

        # 发布时间得分(越新越好)
        publish_time = datetime.fromisoformat(car.publish_time.replace(' ', 'T'))
        days_ago = (datetime.now() - publish_time).days
        recency_score = max(0, 100 - days_ago)
        score += recency_score * 0.1

        scored_cars.append((car, score))

    # 按得分排序
    scored_cars.sort(key=lambda x: x[1], reverse=True)

    return [car for car, score in scored_cars]

八、故障排查与优化
8.1 常见问题解决
问题1:签名验证失败
def debug_signature_generation(params, app_secret, timestamp):
"""调试签名生成过程"""
print("=== 签名调试信息 ===")

# 排序参数
sorted_params = sorted(params.items())
param_str = '&'.join([f"{k}={v}" for k, v in sorted_params])
print(f"参数字符串: {param_str}")

# 构建签名字符串
sign_str = f"{app_key}{param_str}{timestamp}{app_secret}"
print(f"签名字符串: {sign_str}")

# 计算签名
import hmac
signature = hmac.new(
    app_secret.encode('utf-8'),
    sign_str.encode('utf-8'),
    hashlib.sha256
).hexdigest()
print(f"计算签名: {signature}")

return signature

问题2:分页数据异常
def stable_pagination_search(self, **params):
"""稳定的分页搜索"""

# 确保有排序字段
if 'sort_field' not in params:
    params['sort_field'] = 'id'  # 使用唯一字段排序

if 'sort_order' not in params:
    params['sort_order'] = 'desc'

# 使用游标分页
all_cars = []
last_id = None

while True:
    if last_id:
        # 使用游标进行分页
        params['cursor'] = last_id

    result = self.search_used_cars(**params)

    if not result.success or not result.used_cars:
        break

    all_cars.extend(result.used_cars)
    last_id = result.used_cars[-1].car_id

    # 检查是否还有更多数据
    pagination = result.pagination
    if not pagination.get('has_next', False):
        break

    # 避免频繁请求
    time.sleep(0.5)

return all_cars

8.2 性能优化建议
合理使用缓存

多级缓存策略

class MultiLevelCache:
def init(self, redis_client):
self.memory_cache = {}
self.redis = redis_client
self.memory_ttl = 300 # 5分钟
self.redis_ttl = 3600 # 1小时

def get_used_car_data(self, cache_key):
    # 1. 检查内存缓存
    if cache_key in self.memory_cache:
        data, expire_time = self.memory_cache[cache_key]
        if time.time() < expire_time:
            return data

    # 2. 检查Redis缓存
    if self.redis:
        cached = self.redis.get(cache_key)
        if cached:
            data = json.loads(cached)
            # 更新内存缓存
            self.memory_cache[cache_key] = (data, time.time() + self.memory_ttl)
            return data

    return None

批量请求优化
import asyncio
import aiohttp

async def batch_search_async(api_client, search_queries):
"""异步批量搜索"""
async with aiohttp.ClientSession() as session:
tasks = []
for query in search_queries:
task = api_client.search_used_cars_async(session, **query)
tasks.append(task)

    results = await asyncio.gather(*tasks, return_exceptions=True)
    return results

九、最佳实践总结
9.1 安全实践
密钥管理:使用环境变量存储API密钥
HTTPS强制:确保所有请求使用HTTPS
输入验证:验证所有输入参数
错误处理:不暴露敏感错误信息
9.2 性能实践
缓存策略:根据数据更新频率设置合适的缓存时间
批量操作:合并多个请求减少API调用次数
分页优化:使用游标分页提高稳定性
异步处理:批量操作使用异步方式提高吞吐量
9.3 业务实践
地区数据管理:维护地区ID映射表
品牌车系管理:缓存品牌车系信息
价格趋势分析:记录历史价格数据
推荐算法优化:基于用户行为优化推荐
附录:快速开始模板

quick_start.py

from autohome_usedcar import AutoHomeUsedCarAPI

1. 初始化客户端

client = AutoHomeUsedCarAPI(
app_key="your_app_key",
app_secret="your_app_secret",
sandbox=True
)

2. 简单搜索

result = client.search_used_cars(
province_id=11, # 北京
min_price=10,
max_price=30,
min_year=2018
)

if result.success:
for car in result.used_cars:
print(f"{car.brand} {car.series} - {car.price}万")

3. 批量获取

all_cars = client.search_all_used_cars(
province_id=11,
min_price=15,
max_price=25
)
print(f"共找到 {len(all_cars)} 辆二手车")

4. 获取详情

car_detail = client.get_used_car_detail(12345)
if car_detail:
print(f"车辆详情: {car_detail.basic_info.title}")
通过本攻略,您应该能够:
理解汽车之家二手车搜索接口的完整功能
实现安全的API认证和请求
处理各种搜索条件和分页逻辑
构建高性能的二手车搜索应用
在实际业务中灵活应用该接口
建议根据实际业务需求选择合适的实现方案,并遵循最佳实践确保系统的稳定性和可维护性。

相关文章
|
5天前
|
人工智能 自然语言处理 Shell
🦞 如何在 Moltbot 配置阿里云百炼 API
本教程指导用户在开源AI助手Clawdbot中集成阿里云百炼API,涵盖安装Clawdbot、获取百炼API Key、配置环境变量与模型参数、验证调用等完整流程,支持Qwen3-max thinking (Qwen3-Max-2026-01-23)/Qwen - Plus等主流模型,助力本地化智能自动化。
🦞 如何在 Moltbot 配置阿里云百炼 API
|
4天前
|
人工智能 JavaScript 应用服务中间件
零门槛部署本地AI助手:Windows系统Moltbot(Clawdbot)保姆级教程
Moltbot(原Clawdbot)是一款功能全面的智能体AI助手,不仅能通过聊天互动响应需求,还具备“动手”和“跑腿”能力——“手”可读写本地文件、执行代码、操控命令行,“脚”能联网搜索、访问网页并分析内容,“大脑”则可接入Qwen、OpenAI等云端API,或利用本地GPU运行模型。本教程专为Windows系统用户打造,从环境搭建到问题排查,详细拆解全流程,即使无技术基础也能顺利部署本地AI助理。
5114 12
|
10天前
|
人工智能 API 开发者
Claude Code 国内保姆级使用指南:实测 GLM-4.7 与 Claude Opus 4.5 全方案解
Claude Code是Anthropic推出的编程AI代理工具。2026年国内开发者可通过配置`ANTHROPIC_BASE_URL`实现本地化接入:①极速平替——用Qwen Code v0.5.0或GLM-4.7,毫秒响应,适合日常编码;②满血原版——经灵芽API中转调用Claude Opus 4.5,胜任复杂架构与深度推理。
6691 10
|
4天前
|
人工智能 JavaScript API
零门槛部署本地 AI 助手:Clawdbot/Meltbot 部署深度保姆级教程
Clawdbot(Moltbot)是一款智能体AI助手,具备“手”(读写文件、执行代码)、“脚”(联网搜索、分析网页)和“脑”(接入Qwen/OpenAI等API或本地GPU模型)。本指南详解Windows下从Node.js环境搭建、一键安装到Token配置的全流程,助你快速部署本地AI助理。(239字)
3186 18
|
2天前
|
人工智能 机器人 Linux
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
OpenClaw(原Clawdbot)是一款开源本地AI智能体,支持飞书等多平台对接。本教程手把手教你Linux下部署,实现数据私有、系统控制、网页浏览与代码编写,全程保姆级操作,240字内搞定专属AI助手搭建!
2210 6
保姆级 OpenClaw (原 Clawdbot)飞书对接教程 手把手教你搭建 AI 助手
|
4天前
|
人工智能 安全 Shell
在 Moltbot (Clawdbot) 里配置调用阿里云百炼 API 完整教程
Moltbot(原Clawdbot)是一款开源AI个人助手,支持通过自然语言控制设备、处理自动化任务,兼容Qwen、Claude、GPT等主流大语言模型。若需在Moltbot中调用阿里云百炼提供的模型能力(如通义千问3系列),需完成API配置、环境变量设置、配置文件编辑等步骤。本文将严格遵循原教程逻辑,用通俗易懂的语言拆解完整流程,涵盖前置条件、安装部署、API获取、配置验证等核心环节,确保不改变原意且无营销表述。
1985 5
|
4天前
|
机器人 API 数据安全/隐私保护
只需3步,无影云电脑一键部署Moltbot(Clawdbot)
本指南详解Moltbot(Clawdbot)部署全流程:一、购买无影云电脑Moltbot专属套餐(含2000核时);二、下载客户端并配置百炼API Key、钉钉APP KEY及QQ通道;三、验证钉钉/群聊交互。支持多端,7×24运行可关闭休眠。
3318 7
|
3天前
|
人工智能 JavaScript 安全
Clawdbot 对接飞书详细教程 手把手搭建你的专属 AI 助手
本教程手把手教你将 Moltbot(原 Clawdbot)部署在 Linux 服务器,并对接飞书打造专属 AI 助手:涵盖环境准备、Node.js/NVM 安装、Moltbot 快速安装(支持 Qwen 模型)、Web 管理面板配置及飞书应用创建、权限设置与事件回调对接,全程图文指引,安全可靠。
1854 3
Clawdbot 对接飞书详细教程 手把手搭建你的专属 AI 助手
|
5天前
|
存储 安全 数据库
使用 Docker 部署 Clawdbot(官方推荐方式)
Clawdbot 是一款开源、本地运行的个人AI助手,支持 WhatsApp、Telegram、Slack 等十余种通信渠道,兼容 macOS/iOS/Android,可渲染实时 Canvas 界面。本文提供基于 Docker Compose 的生产级部署指南,涵盖安全配置、持久化、备份、监控等关键运维实践(官方无预构建镜像,需源码本地构建)。
2337 7
|
4天前
|
人工智能 应用服务中间件 API
刚刚,阿里云上线Clawdbot全套云服务!
阿里云上线Moltbot(原Clawdbot)全套云服务,支持轻量服务器/无影云电脑一键部署,可调用百炼平台百余款千问模型,打通iMessage与钉钉消息通道,打造开箱即用的AI智能体助手。
2566 22
刚刚,阿里云上线Clawdbot全套云服务!