【问题标题】:Yajl parse error with githubarchive.org JSON stream in PythonYajl 在 Python 中使用 githubarchive.org JSON 流解析错误
【发布时间】:2012-05-03 13:28:18
【问题描述】:

我正在尝试使用 yajl-py 解析 GitHub 存档文件。我相信文件的基本格式是 JSON 对象流,所以文件本身不是有效的 JSON,但它包含的对象是。

为了测试这一点,我安装了yajl-py,然后使用他们的示例解析器(来自https://github.com/pykler/yajl-py/blob/master/examples/yajl_py_example.py)尝试解析文件:

python yajl_py_example.py < 2012-03-12-0.json

其中2012-03-12-0.json 是已解压缩的 GitHub 存档文件之一。

看来这类事情应该从他们在 Ruby 中的参考实现中起作用。 Python 包不处理 JSON 流吗?

顺便说一下,这是我得到的错误:

yajl.yajl_common.YajlError: parse error: trailing garbage
          9478bbc3","type":"PushEvent"}{"repository":{"url":"https://g
                     (right here) ------^

【问题讨论】:

  • "我相信文件的基本格式是 JSON 对象流" 你是怎么得出这个结论的?我们可以检查文件吗?
  • 当然,您可以看到带有wget http://data.githubarchive.org/2012-03-12-0.json.gz | gzip -d &gt; 2012-03-12-0.json 的文件。它有几兆字节,有点大。
  • 你知道了吗?您是否尝试过 allow_multiple_values 选项?
  • 请参阅下面的答案以正确使用 Yajl-Py 解析您的文件。

标签: python json yajl


【解决方案1】:

您需要使用流解析器来读取数据。 Yajl 支持流解析,它允许您一次从文件/流中读取一个对象。话虽如此,看起来 Python 并没有为 Yajl 提供有效的绑定..

py-yajl 已将 iterload 注释掉,不知道为什么:https://github.com/rtyler/py-yajl/commit/a618f66005e9798af848c15d9aa35c60331e6687#L1R264

不是 Python 解决方案,但您可以使用 Ruby 绑定来读取数据并以您需要的格式发出:

# gem 安装 yajl-ruby 需要'open-uri' 需要'zlib' 需要'yajl' gz = open('http://data.githubarchive.org/2012-03-11-12.json.gz') js = Zlib::GzipReader.new(gz).read Yajl::Parser.parse(js) 做 |事件| 打印事件 结尾

【讨论】:

    【解决方案2】:

    该示例未启用任何 Yajl 额外功能,对于您要查找的内容,您需要在解析器上启用 allow_multiple_values 标志。这是您需要修改基本示例以使其解析您的文件的内容。

    --- a/examples/yajl_py_example.py
    +++ b/examples/yajl_py_example.py
    @@ -37,6 +37,7 @@ class ContentHandler(YajlContentHandler):
    
     def main(args):
         parser = YajlParser(ContentHandler())
    +    parser.allow_multiple_values = True
         if args:
             for fn in args:
                 f = open(fn)
    

    Yajl-Py 是 yajl 的一个薄包装器,因此您可以使用 Yajl 提供的所有功能。这里是所有flags that yajl provides that you can enable

    yajl_allow_comments
    yajl_dont_validate_strings
    yajl_allow_trailing_garbage
    yajl_allow_multiple_values
    yajl_allow_partial_values
    

    要在 yajl-py 中打开这些,请执行以下操作:

    parser = YajlParser(ContentHandler())
    # enabling these features, note that to make it more pythonic, the prefix `yajl_` was removed
    parser.allow_comments = True
    parser.dont_validate_strings = True
    parser.allow_trailing_garbage = True
    parser.allow_multiple_values = True
    parser.allow_partial_values = True
    # then go ahead and parse
    parser.parse()
    

    【讨论】:

    • 可以不打印结果吗?文件太大。我只是想做一个新对象,比如:data = parser.parse(f)
    【解决方案3】:

    我知道这已得到解答,但我更喜欢以下方法,它不使用任何包。由于某种原因,github 字典位于一行,因此您不能假设每行只有一个字典。这看起来像:

    {"json-key":"json-val", "sub-dict":{"sub-key":"sub-val"}}{"json-key2":"json-val2", "sub-dict2":{"sub-key2":"sub-val2"}}
    

    我决定创建一个函数,一次获取一个字典。它以字符串形式返回 json。

    def read_next_dictionary(f):
        depth = 0
        json_str = ""
        while True:
            c = f.read(1)
            if not c:
                break #EOF
            json_str += str(c)
            if c == '{':
                depth += 1
            elif c == '}':
                depth -= 1
    
            if depth == 0:
                break
    
        return json_str
    

    我使用这个函数通过 while 循环遍历 Github 存档:

    arr_of_dicts = []
    f = open(file_path)
    while True:
        json_as_str = read_next_dictionary(f)
        try:
            json_dict = json.loads(json_as_str)
            arr_of_dicts.append(json_dict)
        except: 
            break # exception on loading json to end loop
    
    pprint.pprint(arr_of_dicts)
    

    这适用于此处的数据集帖子:http://www.githubarchive.org/(在 gunzip 之后)

    【讨论】:

    【解决方案4】:

    作为一种解决方法,您可以将 GitHub 存档文件分成几行,然后将每一行解析为 json:

    import json
    with open('2013-05-31-10.json') as f:
        lines = f.read().splitlines()
        for line in lines:
            rec = json.loads(line)
            ...
    

    【讨论】:

    • 2012年数据文件只有一行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多