调用接口需带Authorization头或token,分页依响应字段(next/has_more)用while循环拉取;JSON嵌套深时存为JSONB类型,时间、数值字段需安全转换;批量插入用ON CONFLICT和execute_batch提升性能。

用 requests 调接口时怎么带认证和处理分页
大多数生产接口需要 Authorization 头或参数传 token,直接裸调会返回 401 或空数据。别硬试,先看文档里「Authentication」章节——常见的是 Bearer xxx、API-Key: xxx 或 session_id 放 query 里。
分页字段五花八门:page/limit、offset/size、甚至用 cursor(比如 Twitter API)。关键不是猜,是检查响应体里有没有 next、has_more、total 这类字段,再决定用 while 循环还是递归拉取。
- 用
requests.Session()复用连接,避免每页都重连 - 每次请求后加
time.sleep(0.1),防被限流(尤其没配User-Agent时) - 遇到
502/504别直接崩,用try/except+ 指数退避重试
把 JSON 响应转成 PostgreSQL 可插的结构
接口返回的 JSON 嵌套深?别用 json_normalize 硬 flatten——它容易把数组字段炸成多行,而你实际只想存原始 JSON 字符串。PostgreSQL 有 JSONB 类型,直接 psycopg2 插入前用 json.dumps() 即可。
如果必须拆成关系表字段,注意三件事:
立即学习“Python免费学习笔记(深入)”;
-
None在 Python 是NULL,但 PostgreSQL 的JSONB字段不认None,得转成json.dumps(None)→"null",或显式过滤掉 key - 时间字段常是字符串(如
"2024-05-20T08:30:00Z"),用datetime.fromisoformat()解析,再转成datetime对象,psycopg2 才能自动映射到TIMESTAMP WITH TIME ZONE - 数值字段可能混着字符串(如
"123"),用int(x) if x.isdigit() else None安全转换,别信接口文档说的「always number」
用 psycopg2 批量插入时怎么避免主键冲突和性能崩盘
重复抓取同一批数据?用 INSERT ... ON CONFLICT DO NOTHING 最省事,但得提前确认表有唯一约束(比如 CREATE UNIQUE INDEX ON api_logs (request_id);),否则语法报错。
单条 execute() 插 1000 行?慢到怀疑人生。改用 execute_batch() 或 copy_from():
-
execute_batch(cur, "INSERT INTO t VALUES (%s,%s)", data_list, page_size=500)—— 简单可靠,适合中小量( -
copy_from()快十倍,但要求数据是文件对象或StringIO,且字段顺序必须和表定义完全一致 - 别忘在事务外执行
conn.commit(),否则脚本退出就回滚
脚本跑一半断了怎么续抓不重来
网络抖动、数据库挂了、老板突然叫你开会……脚本中断后最烦重跑全部。解决方案就一个:把「最后成功插入的标识」记下来,比如接口的 updated_at 时间戳或 id。
不要手写日志文件解析,直接建一张 job_state 表:
CREATE TABLE job_state ( job_name TEXT PRIMARY KEY, last_id BIGINT, updated_at TIMESTAMPTZ );
每次启动脚本,先查 SELECT last_id FROM job_state WHERE job_name = 'user_api';,然后请求时带上 params={'since_id': last_id};插入成功后更新该行。
这招看着土,但比任何「分布式任务队列」都稳——毕竟你只是想把接口数据落库,不是造火箭。
真正麻烦的是接口本身不支持按 ID 增量拉取,只能靠时间字段。这时候要注意时区:服务端用 UTC,你的脚本也得用 datetime.now(timezone.utc),别用本地时区硬算。


















