Python读取全量JSON生成DataFrame仅读取部分文件无报错问题咨询
问题原因及解决方案
可能的原因
- 未过滤JSON文件:
os.listdir()会返回目标路径下所有文件、子文件夹名称,当前代码未筛选.json后缀的文件,如果路径下存在其他符合JSON解析规则的非目标文件,不会触发报错但会生成结构不符合预期的空数据,导致最终拼接结果缺失部分文件内容。 - 文件名排序逻辑错误:
sorted()默认按字符串ASCII码排序,若文件名按数字区间命名(如slice_1.json、slice_10.json),会出现10排在2前面的乱序情况,若你依赖文件名顺序校验pid,会误判仅读取了部分文件;如果存在非目标前缀的文件,也可能打断预期的读取顺序。 - 路径拼接不规范:
os.sep.join()在Windows环境下易生成无效路径,导致部分文件读取失败且不会触发明显报错。 - 编码适配问题:Windows系统
open()默认编码为GBK,若JSON文件为UTF-8编码且包含特殊字符,会出现静默读取失败,解析出的JSON内容为空,对应的数据不会加入拼接列表。 - 重名列冲突:原代码中
reindex包含两个同名的duration_ms列(分别对应歌单时长、曲目时长),Pandas会自动重命名重名列,可能导致你误判数据范围。
修复后的代码
import json import pandas as pd import os path = 'C:\\Users\\sotir\\Desktop\\machinedataset' # 仅筛选JSON文件,排除子文件夹和其他格式文件 filenames = [f for f in os.listdir(path) if f.lower().endswith('.json')] # 针对Spotify百万歌单数据集的文件名规则排序,避免字符串排序乱序 filenames.sort(key=lambda x: int(x.split('.')[2].split('-')[0])) dfs = [] for filename in filenames: fullpath = os.path.join(path, filename) # 指定UTF-8编码读取,用with语句自动管理文件句柄 with open(fullpath, 'r', encoding='utf-8') as f: js = json.load(f) # 增加字段校验,跳过结构异常的文件 if 'playlists' not in js: print(f"跳过异常文件:{filename},缺失playlists字段") continue df = pd.json_normalize( js['playlists'], meta=['name', 'collaborative', 'pid', 'modified_at', 'num_tracks', 'num_albums', 'num_followers', 'num_edits', 'duration_ms', 'num_artists'], record_path=['tracks'], record_prefix='_' ) dfs.append(df) # 可选打印,确认每个文件处理后的pid范围 print(f"已处理:{filename},该文件pid最大值:{df['pid'].max()}") # 拼接时重置索引,避免索引重复 dfs_total = pd.concat(dfs, ignore_index=True) # 重命名重名列,避免冲突 dfs_total = dfs_total.rename(columns={'duration_ms': 'playlist_duration_ms', '_duration_ms': 'track_duration_ms'}) # 按需求重排列 dfs_total = dfs_total.reindex(columns=[ 'name', 'collaborative', 'pid', 'modified_at', 'num_tracks', 'num_albums', 'num_followers', 'num_edits', 'playlist_duration_ms', 'num_artists', '_pos', '_artist_name', '_track_uri', '_artist_uri', '_track_name', '_album_uri', 'track_duration_ms', '_album_name' ]) print(f"数据处理完成,总行数:{len(dfs_total)},全量pid最大值:{dfs_total['pid'].max()}")
额外排查建议
如果修改代码后pid最大值仍为9999,可先打印len(filenames)确认目标路径下的JSON文件总数是否为1000,大概率是数据集下载不完整,仅下载了前10个分片文件。
内容的提问来源于stack exchange,提问作者manduk
相关产品推荐
相关产品推荐

