适用场景与接口定位
域名交易市场的公开数据对以下几类开发者有直接价值:
- 站长/域名投资人:按用量说明、长度、后缀筛选目标域名,快速缩小选品范围。
- 行业研究:拉取一段时间内的交易记录,分析热门后缀分布、用量说明区间走势。
- 估值参考:结合同后缀、同长度的成交用量说明,辅助判断某个域名的合理估值区间。
该接口定位为只读的数据查询接口,返回的是 EDNS 域名交易市场的公开挂牌/成交信息。它不承担下单、竞价、支付等交易链路,接入前应明确这一点:接口只负责数据,不负责业务闭环。
接口能力边界
在写代码之前,先确认几个事实:
| 项目 | 说明 |
|---|---|
| 请求方法 | GET |
| 请求地址 | https://v1.apizero.cn/api/domain-trade |
| 分类 | 金融数据 |
| QPS 上限 | 5 / s |
| 鉴权方式 | HeaderX-API-Key |
| 数据返回 | JSON 数组格式的响应体 |
QPS 5/s 意味着单机并发拉取需要做限速。如果你的任务需要遍历全部数据页,建议每次请求间隔 200ms 以上,避免触发限流。
鉴权方式
接口通过请求头X-API-Key传递 API Key,例如:
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/domain-trade?page=1&pagesize=10"$APIZERO_API_KEY是环境变量占位,实际调用时请替换为你自己的 Key。不要把 Key 硬编码到前端页面或公开仓库中。
Query 参数逐个拆解
接口共支持 6 个查询参数,全部非必填。参数之间是**叠加过滤(AND)**关系,即同时传入多个参数时,返回的数据要同时满足所有条件。
page
- 类型:number
- 默认值:1
- 语义:页码
- 注意点:页码从 1 开始。如果传 0 或负数,接口行为未在文档中明确,稳妥做法是在业务层拦截非法值。
pagesize
- 类型:number
- 默认值:50
- 上限:100
- 语义:每页返回的域名记录数
这里有一个容易忽略的细节:pagesize 的合法范围是 1 ≤ pagesize ≤ 100。传 0 或大于 100 的值,接口可能拒绝或按上限截断。为了行为可控,建议在构造请求前先做一次入参归一化:
pagesize = max(1, min(pagesize, 100))max_price
- 类型:number
- 语义:最高用量说明(元)
- 过滤方向:只返回用量说明 ≤
max_price的记录
用量说明字段在响应中是字符串类型(如"5000"),但入参是数字类型。构造筛选条件时,不要把max_price写成带单位的字符串,也不要传小数位数过多的浮点数。建议以整数元为单位。
max_length
- 类型:number
- 语义:域名最大长度
这个参数需要特别留意:长度计算的基准是什么?是否包含后缀?例如max_length=8时,abcdefg.com是算 7 个字符还是 11 个字符?不同数据源的口径可能不同,建议在接入前通过文档或少量抽样请求确认口径。若文档未明确,默认按域名主标签(不含点号和后缀)长度理解,但生产环境应以上游实际行为为准。
suffix
- 类型:string
- 语义:后缀过滤
传值时带上点号,例如.com、.net。如果你用com这种无点号的写法,可能匹配不到预期结果。建议在请求前做一次格式化:
suffix = suffix.strip().lower() if not suffix.startswith("."): suffix = "." + suffixsale_type
- 类型:string
- 语义:交易类型
常见的交易类型包括一口价、竞价、拍卖等,具体枚举值以文档为准。这是一个精确匹配参数,不是模糊搜索,传值时需要与数据源使用的文案完全一致。
请求示例
基础 curl
拉取第一页 20 条数据:
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/domain-trade?page=1&pagesize=20"组合筛选 curl
筛选用量说明不超过 200、长度不超过 6 位的.com域名:
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/domain-trade?page=1&pagesize=50&max_price=2000&max_length=6&suffix=.com"Python 请求模板
import requests API_URL = "https://v1.apizero.cn/api/domain-trade" def fetch_domain_trade(api_key: str, params_pack: dict) -> dict: headers = {"X-API-Key": api_key} resp = requests.get(API_URL, headers=headers, params=params_pack, timeout=10) resp.raise_for_status() return resp.json() if __name__ == "__main__": params = { "page": 1, "pagesize": 50, "max_price": 5000, "max_length": 8, "suffix": ".com", "sale_type": "一口价", } result = fetch_domain_trade("YOUR_API_KEY", params) print(result)timeout=10是超时兜底,避免网络异常时请求线程被长时间挂起。
响应结构解读
接口的响应示例结构如下:
{ "code": 0, "msg": "成功", "data": { "count": 50, "current_page": 1, "total_pages": 1234, "list": [ { "name": "abc.com", "price": "5000", "sale_type": "一口价" } ] } }顶层字段
| 字段 | 类型 | 含义 |
|---|---|---|
code | number | 业务状态码,0 表示成功 |
msg | string | 状态描述 |
data | object | 业务数据体 |
data 对象
| 字段 | 类型 | 说明 |
|---|---|---|
count | number | 当前页实际返回的记录条数 |
current_page | number | 当前页码 |
total_pages | number | 总页数 |
list | array | 域名记录数组 |
list 内的域名对象
| 字段 | 类型 | 说明 |
|---|---|---|
name | string | 域名,如abc.com |
price | string | 用量说明(元),字符串类型 |
sale_type | string | 交易类型,如一口价 |
注意price是字符串而不是数字。如果你需要对用量说明做排序或区间统计,先做类型转换:
price_num = float(item["price"])分页遍历的坑
分页遍历最容易踩的坑是用count判断是否还有下一页。实际上count表示当前页的记录数,当最后一页数据不满一页时,count < pagesize可以辅助判断结束,但更可靠的终止条件是current_page >= total_pages。
推荐的分页遍历逻辑:
page = 1 while True: params = {"page": page, "pagesize": 50} payload = fetch_domain_trade(api_key, params) data = payload["data"] # 业务处理 for item in data["list"]: process_domain(item) if page >= data["total_pages"]: break page += 1 time.sleep(0.3) # QPS 限速兜底这个写法的好处是:不依赖count的边界行为,而是以服务端给出的total_pages作为遍历终点,语义清晰且不容易死循环。
另一个建议:如果只需要最新一页的数据,不要为了“保险”而强制翻完所有页。这既浪费配额,也容易触发限流。
常见错误排查
401 鉴权失败
- 现象:接口返回 401 或提示非法 Key
- 排查:
- 确认
X-API-Key的拼写是否正确 - 确认环境变量
$APIZERO_API_KEY是否已导出 - 确认 Key 没有被误放进 Query 参数中
- 确认
业务 code 非 0
- 现象:HTTP 200,但响应中的
code不等于 0 - 排查:
- 逐项核对每个 Query 参数的类型是否符合文档
pagesize是否超过 100max_price是否为负数suffix是否带了点号
数据与预期不符
- 现象:请求成功,但过滤结果看起来不对
- 排查:
max_length的长度口径是否包含后缀sale_type的枚举文案是否与文档完全一致- 是否同时传了多个参数,且它们之间有业务上的矛盾(如既要求低价又要求超短域名)
限流
- 现象:请求偶尔超时或返回限流提示
- 排查:检查本地是否有并发循环请求,QPS 是否超过 5/s。建议在代码中加入节流控制或请求间隔。
工程化注意事项
参数校验前置
不要把上游接口当成校验器。在业务层提前拦截非法参数:
def build_domain_trade_params( page: int = 1, pagesize: int = 50, max_price: int | None = None, max_length: int | None = None, suffix: str | None = None, sale_type: str | None = None, ) -> dict: if page < 1: raise ValueError("page must be >= 1") if not (1 <= pagesize <= 100): pagesize = 50 params = {"page": page, "pagesize": pagesize} if max_price is not None: if max_price < 0: raise ValueError("max_price must be >= 0") params["max_price"] = int(max_price) if max_length is not None: if max_length < 1: raise ValueError("max_length must be >= 1") params["max_length"] = int(max_length) if suffix: suffix = suffix.strip().lower() if not suffix.startswith("."): suffix = "." + suffix params["suffix"] = suffix if sale_type: params["sale_type"] = sale_type return params把响应封装成领域模型
响应中的price是字符串,直接用于计算容易出问题。建议在数据入口统一转换:
@dataclass class DomainTrade: name: str price: float sale_type: str def parse_domain_item(raw: dict) -> DomainTrade: return DomainTrade( name=raw["name"], price=float(raw["price"]), sale_type=raw["sale_type"], )用环境变量管理 Key
不要把 Key 写在代码仓库里。建议使用.env文件或 CI/CD 的 Secret 管理:
export APIZERO_API_KEY=your_key_here日志与监控
建议记录以下信息,便于线上排查:
- 请求的完整 URL(Key 打码)
- 响应状态码与业务 code
- 请求耗时
- 当前页与总页数
小结
域名交易市场接口整体不复杂,核心价值在于Query 参数的精确组合和分页遍历的正确终止。接入时把参数校验前置、遍历逻辑按total_pages收敛、用量说明字段统一转浮点,可以避开绝大多数使用上的坑。长度筛选的口径和交易类型枚举值建议以最新文档为准,必要时通过小批量请求验证行为。
参考文档
- 接口文档页:https://apizero.cn/aidocs/domain-trade
- 原始文档:https://apizero.cn/aidocs/domain-trade/raw.md