如何通过Python将双API学生数据映射合并为含姓名学号的DataFrame并导出CSV
解决方案
可以直接在API调用过程中完成Sid和StudentName的映射,无需先保存本地文件再合并。以下是修改后的完整代码,核心思路是遍历学生数据时同步携带对应身份信息,获取成绩后直接关联:
import requests import pandas as pd def getdata(link): try: response = s.get(link) response.raise_for_status() # 主动触发HTTP状态码错误 return response.json() except requests.exceptions.RequestException as e: print(f'请求异常: {e}') return None s = requests.session() # 获取学生基础数据 student_json = getdata('https://api.school.com/2020/students.json') if not student_json: exit("无法获取学生基础数据,程序终止") def normalize(json_data, record_path): if not json_data or record_path not in json_data: return pd.DataFrame() return pd.json_normalize(json_data[record_path]) student_df = normalize(student_json, 'Students') # 存储所有学生的成绩数据 all_marks_df = pd.DataFrame() # 遍历每个学生,获取成绩并关联身份信息 for _, row in student_df.iterrows(): sid = row['Sid'] student_name = row['StudentName'] # 构造成绩API链接 mark_link = f"https://api.school.com/2020/mark.json?sid={sid}" mark_json = getdata(mark_link) if not mark_json: print(f"无法获取Sid={sid}的成绩数据,跳过") continue # 解析成绩数据 mark_df = normalize(mark_json, 'marks') if mark_df.empty: print(f"Sid={sid}的成绩数据为空,跳过") continue # 添加Sid和StudentName关联字段 mark_df['Sid'] = sid mark_df['StudentName'] = student_name # 合并到总成绩DataFrame all_marks_df = pd.concat([all_marks_df, mark_df], ignore_index=True) # 合并学生基础信息与成绩数据(保留所有学生,包括成绩获取失败的) final_df = pd.merge(student_df[['Sid', 'StudentName']], all_marks_df, on=['Sid', 'StudentName'], how='left') # 保存为CSV文件 final_df.to_csv('学生成绩汇总.csv', index=False, encoding='utf-8-sig') print("CSV文件已生成")
关键改动说明
- 同步关联身份信息:不再单独生成成绩API链接列表,而是直接遍历学生数据行,实时获取当前学生的Sid和姓名,避免后续匹配误差。
- 成绩数据追加关联字段:拿到单个学生的成绩数据后,直接添加Sid和StudentName列,确保成绩与学生一一绑定。
- 增强异常处理:在请求函数中添加HTTP错误捕获,同时判断返回数据有效性,避免空数据导致程序崩溃。
- 完整数据合并:通过
pd.merge的左连接方式,确保所有学生都能出现在最终结果中,成绩缺失的学生对应字段会显示为空。
内容的提问来源于stack exchange,提问作者Aks3
相关产品推荐
相关产品推荐

