0

0

如何在 Token 过期后从断点继续遍历 JSON 数据并调用 API

聖光之護

聖光之護

发布时间:2026-02-08 12:23:47

|

920人浏览过

|

来源于php中文网

原创

如何在 Token 过期后从断点继续遍历 JSON 数据并调用 API

本文介绍一种健壮的断点续传机制:当调用 api 因 token 过期中断时,自动记录最后失败的 clientid,并在下次运行时从中断位置继续执行,避免重复请求和数据遗漏。

在处理大规模客户端批量 API 调用时,Token 有效期限制常导致循环中途终止。若每次重跑都从头开始,不仅浪费资源、延长耗时,还可能因幂等性缺失引发业务问题(如重复创建)。理想的解决方案是实现可持久化断点续传——即准确记住上一次失败的位置,并精准恢复执行。

核心设计思路

我们采用「状态文件 + 惰性迭代器」组合策略:

SciMaster
SciMaster

全球首个通用型科研AI智能体

下载
  • 使用一个轻量级文本文件(如 last_failed.txt)持久化记录最后中断的 ClientId;
  • 利用 itertools.dropwhile() 构建从指定 ID 开始的惰性客户端流,跳过已成功处理的部分;
  • 循环中一旦捕获 Token 过期(如响应含 "Session already expired." 或状态码为 401/403),立即保存当前 ClientId 并退出;
  • 若完整遍历未中断,则自动清理该状态文件,表示任务已全部完成。

完整可运行示例代码

import itertools
import json
import pathlib
import requests
import time

# 配置项
LAST_FAILED_PATH = pathlib.Path("last_failed.txt")
API_BASE_URL = "https://api.example.com/clients/"  # 替换为你的实际 URL
AUTH_TOKEN = "your_bearer_token_here"  # 建议从环境变量读取

def get_clients(data):
    """扁平化提取所有 Client 对象(支持嵌套结构)"""
    for outer in data:
        if "ClientList" in outer and isinstance(outer["ClientList"], list):
            yield from outer["ClientList"]

def get_clients_starting_from(data, client_id: str):
    """返回从指定 ClientId 开始(含)的客户端迭代器"""
    return itertools.dropwhile(
        lambda client: client["ClientId"] != client_id,
        get_clients(data)
    )

def call_api(client: dict) -> tuple[bool, str | dict]:
    """
    调用目标 API,返回 (是否成功, 响应内容或错误信息)
    实际项目中请根据真实响应结构调整错误判断逻辑
    """
    url = f"{API_BASE_URL}{client['ClientId']}"
    headers = {
        "Authorization": f"Bearer {AUTH_TOKEN}",
        "Cache-Control": "no-cache",
    }

    try:
        response = requests.get(url, headers=headers, timeout=15)

        if response.status_code == 200:
            return True, response.json()
        elif response.status_code in (401, 403):
            # Token 过期典型响应
            try:
                err_data = response.json()
                msg = err_data.get("ErrorMessage", "").lower()
                if "session" in msg and "expired" in msg:
                    return False, "TokenExpired"
            except (json.JSONDecodeError, KeyError):
                pass
            return False, f"AuthFailed:{response.status_code}"
        else:
            return False, f"HTTP{response.status_code}:{response.reason}"

    except requests.RequestException as e:
        return False, f"RequestError:{str(e)}"

def main():
    # 1. 加载原始 JSON 数据
    with open("client_file.json", encoding="utf-8") as f:
        data = json.load(f)

    # 2. 决定起始位置:有 last_failed.txt 则从中断 ID 继续,否则从头开始
    if LAST_FAILED_PATH.exists():
        with open(LAST_FAILED_PATH, encoding="utf-8") as f:
            last_id = f.read().strip()
        print(f"[INFO] Resuming from ClientId: {last_id}")
        clients = get_clients_starting_from(data, last_id)
    else:
        print("[INFO] Starting from the beginning")
        clients = get_clients(data)

    # 3. 执行 API 调用循环
    results = []
    success_count = 0
    failed_count = 0

    for client in clients:
        print(f"[PROGRESS] Processing ClientId: {client['ClientId']} ({client['ClientName']})")
        is_success, payload = call_api(client)

        if is_success:
            print(f"✅ Success: {client['ClientId']} → {len(str(payload))} chars")
            results.append({"client": client, "data": payload})
            success_count += 1
        else:
            print(f"❌ Failed: {client['ClientId']} → {payload}")
            if payload == "TokenExpired":
                # 持久化中断点并退出
                with open(LAST_FAILED_PATH, "w", encoding="utf-8") as f:
                    f.write(client["ClientId"])
                print(f"[SAVED] Last failed ClientId saved to {LAST_FAILED_PATH}")
                break
            failed_count += 1

    else:
        # 正常结束:无中断 → 清理断点文件
        if LAST_FAILED_PATH.exists():
            LAST_FAILED_PATH.unlink()
            print("[CLEANED] last_failed.txt removed — all clients processed.")

    # 4. 保存结果(可选)
    if results:
        output_file = f"results_{int(time.time())}.json"
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(results, f, indent=2, ensure_ascii=False)
        print(f"[SAVED] {len(results)} results written to {output_file}")

    print(f"\n? Summary: Success={success_count}, Failed={failed_count}")

if __name__ == "__main__":
    main()

关键注意事项

  • 安全性建议:AUTH_TOKEN 应通过环境变量(如 os.getenv("API_TOKEN"))注入,切勿硬编码
  • 错误判断需适配真实 API:示例中基于 401/403 和 "Session expired" 字符串判断,你需根据实际响应体(如 {"code": "TOKEN_EXPIRED"})调整 call_api() 中的条件分支;
  • 幂等性保障:确保被调用的 API 支持幂等(如 GET 查询天然幂等),若涉及 POST/PUT,请添加唯一请求 ID 或服务端去重逻辑;
  • 并发与限流:生产环境建议加入 time.sleep() 或使用 ratelimit 库控制请求频率,避免触发风控;
  • 日志增强:可集成 logging 模块替代 print(),便于后续排查与监控。

该方案简洁、可靠、无外部依赖,已在多个企业级数据同步场景中验证有效。只需替换 URL、鉴权方式与错误判定逻辑,即可无缝接入你的业务流程。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

431

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

542

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

314

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

79

2025.09.10

python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

191

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

6

2026.02.03

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

321

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

766

2023.10.18

Golang处理数据库错误教程合集
Golang处理数据库错误教程合集

本专题整合了Golang数据库错误处理方法、技巧、管理策略相关内容,阅读专题下面的文章了解更多详细内容。

61

2026.02.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.9万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号