从一个需求开始:拿到博主的公开档案
做技术博客周报时,我常需要把关注博主的粉丝数、码龄、原创量汇总到一张表格里。逐个打开主页复制数据显然不现实,更可行的方式是让程序去读取公开档案。CSDN 博主信息接口解决了这个问题:只要知道对方的 CSDN 用户名,通过一个 GET 请求就能拿到昵称、头像、码龄、博客等级、原创数、粉丝数、博客排名、IP 属地、原力等级、勋章列表与成就明细等公开信息。
本文按一条完整的接入路径展开:先确认需求与接口边界,再构造请求,然后解读响应,最后讨论接入自动化任务时需要注意的工程细节。
接口能力与边界
接口地址为https://v1.apizero.cn/api/csdn-profile,请求方法为GET,分类属于内容娱乐。它接收一个username查询参数,返回该用户 CSDN 公开页面上可被公开访问的信息。
在动手之前,建议先明确两条边界。
- 接口只处理字母、数字、下划线组成的用户名。中文昵称、带空格的账号名不能作为查询参数,查询前应做格式校验。
- 接口返回的是公开档案,不包含私信、邮箱、手机号等非公开数据;对任何字段缺失或为空的情况,调用方都要有容忍能力。
接口的 QPS 上限为 5 次/秒,这是一个限制而非承诺指标。单机脚本单线程调用通常没有问题,但并发高于这个量级时会触发限流,需在客户端自行控制请求节奏。
查询参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| username | string | 是 | CSDN 用户名,仅字母/数字/下划线,例如 weixin_44906759 |
请求必须携带username,其余参数请以文档页说明为准。
鉴权方式
请求需要在 HTTP Header 中携带 API Key,字段名为X-API-Key。Key 属于敏感凭证,不应写死在代码仓库里,建议通过环境变量或配置中心注入。API Key 的获取与使用规则,请查看接口文档页的鉴权说明。
最小可用请求:curl 示例
curl -sS \ -X GET \ -H "X-API-Key: $APIZERO_API_KEY" \ "https://v1.apizero.cn/api/csdn-profile?username=weixin_44906759"执行前确认APIZERO_API_KEY已在当前 shell 环境中导出。如果 Key 无效或缺失,接口会返回鉴权失败,具体状态码与提示信息以文档为准。
Python 接入示例
import os import re import requests API_URL = "https://v1.apizero.cn/api/csdn-profile" USERNAME_RE = re.compile(r"^[A-Za-z0-9_]+$") def fetch_csdn_profile(username: str) -> dict: if not USERNAME_RE.fullmatch(username or ""): raise ValueError("username 只能包含字母、数字、下划线") api_key = os.getenv("APIZERO_API_KEY") if not api_key: raise RuntimeError("缺少环境变量 APIZERO_API_KEY") resp = requests.get( API_URL, params={"username": username}, headers={"X-API-Key": api_key}, timeout=(3.05, 10), ) resp.raise_for_status() doc = resp.json() # 接口返回一个数组,每一项描述一种可能的响应 for item in doc: if item.get("status") == "200" and item.get("example", {}).get("code") == 0: return item["example"]["data"] raise ValueError("未找到成功响应")注意两点。
resp.raise_for_status()只处理 HTTP 层错误,业务层的code必须单独判断。- 这里对返回数组做了遍历,目的是取出
status="200"且业务码为0的那一项;如果直接下标取[0],在返回顺序变化时可能取到错误的数据结构。
返回数据解读
一次成功调用的 JSON 响应结构如下:
{ "code": 0, "data": { "code_age_years": 5, "fans_count": 1234, "nickname": "XXX" }, "msg": "成功" }其中code是业务状态码,0表示正常;msg提供人类可读的描述;data是核心数据对象。
字段说明
| 字段 | 含义 |
|---|---|
| nickname | 博主昵称 |
| code_age_years | 码龄,单位:年 |
| fans_count | 粉丝数 |
接口说明中提到的完整返回还包括头像、博客等级、原创数、博客排名、IP 属地、原力等级、勋章列表与成就明细等字段。这些字段在完整返回中对应的英文键名、是否可选,以及不同账号之间字段是否一致,请以接口实际返回和文档页为准。实际接入时建议先对目标用户名打印一次完整 JSON,再决定解析哪些 key。
出错时如何排查
接入过程中遇到异常,建议按下面的顺序排查。
- 先看 HTTP 状态码。鉴权失败、参数错误、限流都可能体现为 HTTP 层的非 200 状态,具体映射关系以文档为准。
- 再看业务
code。HTTP 200 不代表数据一定正确,必须校验响应体里的code是否为 0。 - 核对用户名。确认
username只包含字母、数字、下划线,且该账号确实存在。 - 检查是否触发限流。QPS 上限为 5,短时间内连续发送大量请求会触发限流,客户端应做退避重试。
素材没有提供完整错误码表,因此出现具体错误码时,优先查询文档页同名接口的错误码说明,比在社区里拼凑经验更可靠。
工程化接入注意事项
把上述示例放到生产或准生产环境之前,建议补齐以下四块内容。
1. 用户名预校验
import re USERNAME_RE = re.compile(r"^[A-Za-z0-9_]+$") def is_valid_username(name: str) -> bool: return bool(USERNAME_RE.fullmatch(name or ""))这能在请求发出前拦截掉明显非法的输入,减少无效调用。
2. 本地缓存
粉丝数、码龄这类数据变化频率不高,没有必要每次请求都打接口。建议以username为 key 做本地缓存,设置合理的 TTL,例如 10 到 30 分钟。这样既能加快自身页面响应,也能降低对接口的调用压力。
3. 限速与重试
批量场景下要在客户端维护一个简单的令牌桶或信号量,确保瞬时并发不超过 5。对限流类响应或网络抖动,使用指数退避重试,例如间隔 1s、2s、4s,最多重试 3 次。
4. 日志与安全
打日志时只记录username、HTTP 状态码、业务code,不要输出完整响应体,尤其不要输出请求头里的X-API-Key。Key 的轮换、权限最小化等措施应在密钥管理流程中覆盖。
参考文档
- 文档页:https://apizero.cn/aidocs/csdn-profile
- 原始文档:https://apizero.cn/aidocs/csdn-profile/raw.md