递归采集多级菜单易死循环因环引用或无终止条件;应设max_depth、用visited_ids防重、校验children类型;推荐栈模拟递归以提升可控性。

为什么递归采集多级菜单容易陷入死循环
因为菜单接口常返回带 children 字段的嵌套结构,但实际数据里可能有环引用(比如某子项的 id 指向了祖先节点),或后端未严格控制层级深度,导致递归无终止条件。
实操建议:
立即学习“Python免费学习笔记(深入)”;
华为云 Python SDK 查询工具。自动发现已安装 SDK 的服务包、Client类、API 方法、入参详情、类信息(__init__ 参数、属性、类型、描述),支持关键字搜索,快速定位目标 API 使用方法。
- 必须传入
max_depth参数限制递归层数,默认设为5比较安全 - 用
visited_ids集合记录已处理过的id,每次进入前检查是否重复 - 不要直接对
response.json().get('children')无条件递归,先判断是否为list类型且非空
requests + 递归函数怎么安全提取每层菜单的 URL 和名称
多数菜单接口是 GET 请求,靠上层的 id 或 code 拼接下一层请求 URL。不能把所有字段都塞进递归参数,只传必要上下文。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 递归函数签名推荐:
def fetch_menu(url: str, parent_id: str = None, depth: int = 0) - 每层解析后立即提取关键字段:如
item['name']、item['url'](或拼接规则)、item['id'] - 若下一层需 POST 请求或带 token,把 session 对象作为参数传入,别在递归里反复新建
requests.Session() - 示例片段:
if 'children' in item and isinstance(item['children'], list): for child in item['children']: if child.get('id') not in visited_ids: fetch_menu(next_url_template.format(child['id']), child['id'], depth + 1)
遇到“最大递归深度 exceeded”错误怎么办
Python 默认递归限制约 1000 层,但真实菜单极少超 10 层;报这个错大概率是逻辑写错了,不是真需要调高限制。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先用
print(f"depth={depth}, id={item.get('id')}")打印路径,确认是否在两个 ID 之间来回跳转 - 检查接口返回的
children是否为null、None或字符串(如"null"),这些值没做类型判断就会触发无限递归 - 绝对不要用
sys.setrecursionlimit()临时加高——这只会掩盖环引用问题,且可能引发栈溢出崩溃
要不要改用栈模拟递归代替真实递归
要。尤其当菜单数据量大、层级不规则,或你需要控制请求并发、失败重试、中间状态保存时,显式栈更可控。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 用
stack = [(root_url, None, 0)]初始化,每个元组存 (当前URL, parent_id, depth) - 循环中
url, pid, d = stack.pop(),处理完再把子项 push 进栈 - 相比递归,栈方式天然支持暂停、断点续爬、按深度优先/广度优先切换(改
pop()为pop(0)) - 如果后端接口有频率限制,栈结构也更容易插入
time.sleep()或异步等待
id 根本不对应真实接口——这些得靠抓包比对响应体和网页 Network 面板里的实际请求。

















