首页 > 解决方案 > Python ijson - 解析错误:尾随垃圾 // bz2.decompress()

问题描述

使用 ijson 解析 json 时遇到错误。

背景:我有一系列(大约 1000 个)推特数据的大文件,这些文件以“.bz2”格式压缩。我需要将文件中的元素放入 apd.DataFrame中以进行进一步分析。我已经确定了我需要获取的密钥。我很谨慎地发布推特数据。

尝试:我已经设法使用bz2.decompress以下代码解压缩文件:

## Code in loop specific for decompressing and parsing - 

with open(file, 'rb') as source:
                # Decompress the file
                json_r = bz2.decompress(source.read())
                json_decom =  json_r.decode('utf-8') # decompresses one file at a time rather than a stream
                
                # Parse the JSON with ijson 
                parser = ijson.parse(json_decom)
                for prefix, event, value in parser:
                    # Print selected items as part of testing
                    if prefix=="created_at":
                        print(value)
                    if prefix=="text":
                        print(value)
                    if prefix=="user.id_str":
                        print(value)

这给出了以下错误:

IncompleteJSONError: parse error: trailing garbage
          estamp_ms":"1609466366680"}  {"created_at":"Fri Jan 01 01:59
                     (right here) ------^

两件事情:

任何帮助将不胜感激。

谢谢你,詹姆斯

标签: pythontwittererror-handlingbz2ijson

解决方案


直接回答你的两个问题:

  • 解压缩方法是正确的,因为它会生成 JSON 数据,然后将其提供给ijson. 正如您所指出的,ijson同时使用strbytes输入(尽管后者是首选);如果您提供ijson一些非 JSON 输入,您将不会看到在其中显示 JSON 数据的错误。

  • 这是ijson 的 FAQ 中描述的一个非常常见的错误。这基本上意味着您的 JSON 文档具有多个顶级值,这不是标准 JSON,但 ijson 通过使用该multiple_values选项支持(有关详细信息,请参阅文档)。

关于整个代码:虽然它工作正常,但可以改进:使用的重点ijson是您可以避免将完整的 JSON 内容加载到内存中。您发布的代码并没有利用它的优势:它首先打开 bz 压缩文件,将其作为一个整体读取,将其作为一个整体解压缩(不必要地)将其作为一个整体解码然后提供解码后的数据作为 的输入ijson。如果您的输入文件很小,并且解压缩的数据也很小,您不会看到任何影响,但是如果您的文件很大,那么您肯定会开始注意到它。

更好的方法是通过所有操作流式传输数据,以便一切都以增量方式发生:解压缩、不解码和 JSON 解析。类似于以下内容:

with bz2.BZ2File(filename, mode='r') as f:
    for prefix, event, value in ijson.parse(f):
        # ...

作为蛋糕上的樱桃,如果您想从中构建一个 DataFrame,您可以使用 DataFrame 的data 参数直接使用上述结果构建 DataFrame。data可以是可迭代的,例如,您可以在生成器上方制作代码并将其用作data. 再次,类似于以下内容:

def json_input():
   with bz2.BZ2File(filename, mode='r') as f:
       for prefix, event, value in ijson.parse(f):
           # yield your results

df = pandas.DataFrame(data=json_input())

推荐阅读