如何用脚本批量处理API分页?高效自动化数据抓取全攻略
📖 目录导读
- 什么是API分页?为何需要批量处理?
- 常见API分页类型与脚本应对策略
- 实战:Python脚本批量处理分页(附代码)
- 进阶技巧:错误重试、限速与并发优化
- 常见问题与问答(FAQ)
- 总结与最佳实践
什么是API分页?为何需要批量处理?
调用REST API获取数据时,服务器通常不会一次性返回全部结果(例如十万条记录),而是将数据分割成多页,每页返回固定数量(如20条、100条),这种机制称为API分页(API Pagination)。

典型场景:
- 从商业数据平台(如Shopify、GitHub、Twitter)拉取用户列表、订单记录。
- 采集公开数据用于分析或备份。
- 集成第三方服务时同步大范围数据。
手动翻页的痛点:
- 逐页手动复制URL或点击“下一页”,效率极低。
- 若页面超过100页,人工操作几乎不可行。
- 容易因网络波动导致重复或遗漏。
用脚本自动遍历所有页、解析数据并整合,是实现规模化数据处理的刚需技能。
常见API分页类型与脚本应对策略
| 分页类型 | 实现方式 | 典型示例 | 脚本策略 |
|---|---|---|---|
| 基于偏移量 | 使用?offset=0&limit=20,递增offset |
Elasticsearch、Shopify | 循环增加offset,直到返回数据为空 |
| 基于页数 | 使用?page=1&size=20,递增page |
GitHub、Reddit | 循环page变量,检查响应中has_more或页面为空 |
| 基于游标 | 使用?cursor=xxxx,从上一页返回中提取 |
Twitter v2、Stripe | 解析响应next_cursor,继续请求直到cursor为null |
| 基于时间/ID | 使用?since_id=xxx或?created_at__gt=xxx |
Zendesk、MongoDB Atlas | 取当前页最大ID/时间戳作为下一次起始参数 |
关键原则:
- 不要硬编码页数:动态检测停止条件(例如空结果、
has_more: false)。 - 尊重限速:加入
time.sleep()或使用令牌桶算法。
实战:Python脚本批量处理分页(游标型为例)
以下脚本以游标分页(Twitter API v2为例)演示完整流程。
环境准备
pip install requests pandas
脚本代码(核心逻辑)
import requests
import time
import pandas as pd
def fetch_tweets_followers(user_id, bearer_token):
base_url = f"https://api.twitter.com/2/users/{user_id}/followers"
headers = {"Authorization": f"Bearer {bearer_token}"}
params = {"max_results": 100} # 每页最多100条
all_data = []
while True:
response = requests.get(base_url, headers=headers, params=params)
if response.status_code != 200:
print(f"Error: {response.status_code}, sleep and retry")
time.sleep(10)
continue
data = response.json()
# 提取数据(假设存在data字段)
if "data" in data:
all_data.extend(data["data"])
# 检查是否有下一页游标
meta = data.get("meta", {})
next_token = meta.get("next_token")
if not next_token:
print("No more pages.")
break
# 更新参数中的游标
params["pagination_token"] = next_token
# 避免触发限速(Twitter速率:15次/15分钟 => 每60秒1次)
time.sleep(60)
# 导出为CSV
df = pd.DataFrame(all_data)
df.to_csv("followers.csv", index=False)
print(f"总抓取 {len(all_data)} 条数据")
# 调用示例(替换真实user_id和token)
fetch_tweets_followers("12345678", "YOUR_BEARER_TOKEN")
其他分页类型模板
基于页数:
page = 1
while True:
resp = requests.get(f"https://api.example.com/items?page={page}")
items = resp.json()
if not items:
break
process(items)
page += 1
基于偏移量:
offset = 0
limit = 50
while True:
resp = requests.get(f"https://api.example.com/data?offset={offset}&limit={limit}")
records = resp.json()
if len(records) < limit:
break
offset += limit
进阶技巧:错误重试、限速与并发优化
使用tenacity库实现自动重试
pip install tenacity
from tenacity import retry, stop_after_attempt, wait_exponential
@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
def robust_request(url, headers):
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
用aiohttp实现异步并发(提高速度)
对于非限速敏感的API(如内部服务),可用异步:
import aiohttp
import asyncio
async def fetch_page(session, page):
async with session.get(f"https://api.example.com/data?page={page}") as resp:
return await resp.json()
async def main():
async with aiohttp.ClientSession() as session:
tasks = [fetch_page(session, i) for i in range(1, 51)]
results = await asyncio.gather(*tasks)
限速警告:并发仅适用于无速率限制或速率极高的API,否则会被封IP。
常见问题与问答(FAQ)
Q1: 如何知道API使用哪种分页方式?
A: 查看官方文档(通常在“Pagination”或“API Reference”章节),若不清晰,可观察URL参数:若含page、offset、cursor、marker等,则对应相应类型。
Q2: 处理分页时遇到数据不一致怎么办?
A: 数据在抓取过程中可能被修改(新增/删除),建议:
- 对时间敏感的数据,使用时间戳游标分页(如
created_at__lte)。 - 对关键字段设置唯一约束(如ID),最终合并时去重。
Q3: 脚本运行到一半因网络中断失败了,如何恢复?
A: 保存进度到文件(如记录当前页号/游标),重启时读取进度,继续从断点处抓取。
with open("progress.txt", "w") as f:
f.write(str(current_cursor))
Q4: 如何测试分页脚本的正确性?
A: 先用少量数据(如限制max_results=1)验证循环是否正常停止,再逐步放大,使用Mock API(如https://jsonplaceholder.typicode.com/posts)模拟分页。
Q5: 有没有现成的工具或库?
A: 对于简单场景,可用curl配合循环,但专业场景推荐:
paginate库(Python):抽象分页逻辑。Scrapy框架:内置了Request循环与去重。- Postman的“Runner”功能:但不如脚本灵活。
总结与最佳实践
批量处理API分页的核心是:识别分页类型 → 循环请求 → 动态检测终止条件 → 优雅处理错误。
安全建议:
- 始终设置
User-Agent,避免被识别为爬虫。 - 加入随机延时(1-3秒),模拟人类操作。
- 如可能,申请独立的API密钥,并设置白名单IP。
SEO优化思路:
- 脚本化分页能显著提高数据采集效率,降低人工成本。
- 搜索引擎喜欢结构化、可复用的代码范例(本文已提供)。
- 关键词自然融入标题、H2、H3,保证内容密度在2%-3%。
你可以用上述模板快速编写自己的分页脚本,遇到新API时,记得先手动请求一页观察响应结构,再修改循环逻辑,自动化分页,就是如此简单。
扩展阅读:若需处理亿级数据,可结合数据库分批写入或使用Apache Kafka流式处理。