如何将Canvas API返回的字典数据拆分为独立列及分页问题咨询
嵌套列拆分解决方案
你直接调用json_normalize失败的核心原因是目标列存储的是包含多个字典的列表结构,而非单个字典,需要先把列表展开再做规范化处理,操作步骤如下:
- 假设你将接口返回的JSON转为DataFrame后命名为
raw_df,嵌套列名为submission_comments,先将列表列炸开,让每条评论对应单独一行:
# 忽略索引重置行号,避免炸开后索引重复 df_exploded = raw_df.explode('submission_comments', ignore_index=True)
- 对炸开后的字典列做规范化,自动拆分一级、二级嵌套字段:
# 会自动将author下的字段生成author.id、author.display_name这类格式的列 comment_df = pd.json_normalize(df_exploded['submission_comments'])
- 把拆分后的评论列和原始提交数据拼接:
final_df = pd.concat([df_exploded.drop(columns=['submission_comments']), comment_df], axis=1)
如果需要保留同一条提交的多条评论在同一行,可以在上述步骤后按提交ID分组,给评论字段加序号后缀转宽表即可。submission_history列的拆分逻辑完全一致,替换列名即可。
仅返回10条数据的原因及解决方法
最常见的原因是Canvas API默认开启分页,单页默认返回10条数据,你只拿了第一页的结果,处理方案如下:
- 先在请求参数中加
per_page字段,设置单页最大返回条数100,减少请求次数 - 解析响应头的
Link字段,循环获取下一页数据直到没有下一页为止,完整代码示例:
import requests import pandas as pd base_url = 'https://canvas.gu.se/api/v1/courses/xxxxx/assignments/xxxxxx/submissions' params = { "include": ["submission_history", "submission_comments"], "per_page": 100 } headers = {'Authorization': 'Bearer ' + canvas_token} all_submissions = [] current_url = base_url while current_url: resp = requests.get(current_url, params=params, headers=headers) resp.raise_for_status() all_submissions.extend(resp.json()) # 解析下一页地址 next_url = None if 'Link' in resp.headers: for link_item in resp.headers['Link'].split(','): if 'rel="next"' in link_item: next_url = link_item.strip().split(';')[0].strip('<>') break current_url = next_url params = {} # 下一页地址已自带参数,无需重复传递 raw_df = pd.DataFrame(all_submissions)
如果按上述方法处理后返回条数还是不对,可排查两个问题:
- 你的账号没有该课程的全量提交查看权限,需要联系课程管理员开通权限
- 请求参数中的课程ID、作业ID填写错误,核对ID正确性即可
内容的提问来源于stack exchange,提问作者nicols
相关产品推荐
相关产品推荐

