You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python标准化嵌套JSON 实现评论与回复同属一行

解决方案

错误原因

你之前的写法报错是因为pd.json_normalize处理的输入应该是原始的JSON嵌套结构,你先把第一层展开成DataFrame之后再传入作为normalize的输入,此时replies列已经是序列化后的结构,不再是原始的嵌套数组,因此无法解析。

方案1:仅保留有回复的主评论+对应回复(每条回复对应一行,和所属主评论在同一行)

import pandas as pd
import json

with open('f1.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

df = pd.json_normalize(
    data,
    # 直接指定到最内层的回复数组路径
    record_path=['comments_full', 'replies'],
    # 指定需要保留的上层主评论字段,可按需增减
    meta=[
        ['comments_full', 'comment_id'],
        ['comments_full', 'comment_url'],
        ['comments_full', 'commenter_id'],
        ['comments_full', 'commenter_url'],
        ['comments_full', 'commenter_name'],
        ['comments_full', 'comment_text'],
        ['comments_full', 'comment_time']
    ],
    # 给字段加前缀避免重名冲突
    meta_prefix='main_',
    record_prefix='reply_'
)

# 导出CSV,用utf-8-sig避免乱码
df.to_csv('comments_with_replies.csv', index=False, encoding='utf-8-sig')

执行后你会得到的CSV字段格式为main_comment_id、main_commenter_name、main_comment_text、reply_comment_id、reply_commenter_name、reply_comment_text等,主评论和对应回复在同一行展示。

方案2:保留所有主评论(包括没有回复的主评论)

如果需要保留没有回复的主评论,可通过左连接实现:

import pandas as pd
import json

with open('f1.json', 'r', encoding='utf-8') as f:
    data = json.load(f)

# 第一步:展开所有主评论,加前缀区分
main_comment_df = pd.json_normalize(
    data,
    record_path=['comments_full']
).add_prefix('main_')

# 第二步:展开所有回复,关联主评论ID
reply_df = pd.json_normalize(
    data,
    record_path=['comments_full', 'replies'],
    meta=[['comments_full', 'comment_id']],
    record_prefix='reply_'
)

# 第三步:左连接,无回复的主评论对应回复字段为空
final_df = pd.merge(
    main_comment_df,
    reply_df,
    left_on='main_comment_id',
    right_on='main_comment_id',
    how='left'
)

final_df.to_csv('all_comments.csv', index=False, encoding='utf-8-sig')

内容的提问来源于stack exchange,提问作者ossama assaghir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 06:06:01