pandas json_normalize处理Facebook Graph API嵌套JSON为DataFrame问题
问题根因
直接对接口返回的完整JSON根对象调用json_normalize时,方法只会展开根节点下的一级字段,嵌套在data数组中的广告活动、insights.data下的指标数据、actions/action_values这类键值对结构的列表都不会被自动拆解,因此最终只会得到1行包含未展开嵌套结构的结果。
实现方案
分步拆解多层嵌套结构,先打平固定层级的字段,再转换行为类键值对列表为宽表,同时兼容接口分页逻辑,完整代码如下:
import requests import pandas as pd from pandas import json_normalize # 替换为你的有效访问凭证 my_access_token = "YOUR_ACCESS_TOKEN" api_url = 'https://graph.facebook.com/v14.0/act_1135563643203528/campaigns?fields=name,date_preset=last_7d,insights{actions,action_values,conversions,conversion_values,impressions}&access_token=' + my_access_token def get_campaign_report(start_url): all_page_data = [] current_url = start_url while current_url: resp = requests.get(current_url).json() campaign_list = resp.get("data", []) if not campaign_list: break # 第一层展开:把广告活动基础信息和insights下的基础指标打平 df_base = json_normalize( campaign_list, record_path=["insights", "data"], meta=["name", "id"], sep="_" ) # 工具函数:把actions/action_values这类列表转成action_type为列名的宽表 def expand_kv_action_col(target_df, col_name, col_prefix=""): expanded_rows = [] for row_idx, row in target_df.iterrows(): action_items = row.get(col_name, []) if not action_items: expanded_rows.append(pd.DataFrame(index=[row_idx])) continue row_data = {f"{col_prefix}{item['action_type']}": item["value"] for item in action_items} expanded_rows.append(pd.DataFrame(row_data, index=[row_idx])) return pd.concat(expanded_rows) # 分别展开行为次数、行为价值列,价值列加前缀避免列名冲突 df_actions = expand_kv_action_col(df_base, "actions") df_action_values = expand_kv_action_col(df_base, "action_values", col_prefix="conv_value_") # 合并所有字段,删除原始未展开的列表列 df_page = pd.concat( [ df_base.drop(columns=["actions", "action_values"], errors="ignore"), df_actions, df_action_values ], axis=1 ) all_page_data.append(df_page) # 读取下一页地址,无下一页时终止循环 current_url = resp.get("paging", {}).get("next") # 合并所有分页数据,统一转换数值字段类型 if not all_page_data: return pd.DataFrame() final_df = pd.concat(all_page_data, ignore_index=True) numeric_cols = [col for col in final_df.columns if col not in ["name", "id", "date_start", "date_stop"]] final_df[numeric_cols] = final_df[numeric_cols].apply(pd.to_numeric, errors="coerce") return final_df # 执行拉取 df = get_campaign_report(api_url)
输出说明
- 最终结果每行对应1个广告活动在所选时间周期的汇总数据
- 所有行为类型(
post_reaction、omni_purchase、link_click等)会自动展开为独立列,无对应行为的广告活动该列值为空 - 转化价值类字段统一加
conv_value_前缀,和行为次数字段明确区分 - 自动遍历分页拉取全量数据,所有数值类字段自动转为数值类型,可直接用于后续计算分析
内容的提问来源于stack exchange,提问作者ibimon
相关产品推荐
相关产品推荐

