5

我正在尝试使用 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) ------^
4

4 回答 4

4

您需要使用流解析器来读取数据。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) 做 |事件|
  打印事件
结尾
于 2012-05-04T18:09:01.477 回答
1

我知道这已经得到解答,但我更喜欢以下方法,它不使用任何包。由于某种原因,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 之后)

于 2014-06-08T04:06:14.770 回答
1

该示例未启用任何 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 提供的所有功能。以下是yajl 提供的所有可以启用的标志

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()
于 2012-12-06T19:07:42.127 回答
-1

作为一种解决方法,您可以将 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)
        ...
于 2013-05-31T22:54:37.093 回答