2012-05-03 15 views
5

Tôi đang cố gắng phân tích tệp lưu trữ GitHub bằng yajl-py. Tôi tin rằng định dạng cơ bản của tệp là luồng của các đối tượng JSON, do đó, tệp đó không phải là JSON hợp lệ, nhưng nó chứa các đối tượng.Lỗi phân tích cú pháp Yajl với luồng githubarchive.org JSON trong Python

Để kiểm tra điều này ra, tôi cài đặt yajl-py và sau đó sử dụng ví dụ phân tích cú pháp của họ (từ https://github.com/pykler/yajl-py/blob/master/examples/yajl_py_example.py) để cố gắng phân tích một tập tin:

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

nơi 2012-03-12-0.json là một trong những tập tin lưu trữ GitHub đó là được giải nén.

Dường như loại điều này sẽ hoạt động từ việc triển khai tham chiếu của chúng trong Ruby. Các gói Python không xử lý luồng JSON?

Bằng cách này, đây là lỗi tôi nhận được:

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

"Tôi tin cơ bản định dạng của tệp là luồng của các đối tượng JSON "Bạn đã đi đến kết luận này như thế nào? Chúng tôi có thể kiểm tra các tập tin? –

+0

Chắc chắn, bạn có thể xem tệp bằng 'wget http://data.githubarchive.org/2012-03-12-0.json.gz | gzip -d> 2012-03-12-0.json'. Đó là một vài megabyte, rất lớn. – Bialecki

+0

Bạn đã tìm ra điều này chưa? Bạn có thử tùy chọn allow_multiple_values ​​không? – Pykler

Trả lời

4

Bạn cần phải sử dụng một cú pháp dòng để đọc dữ liệu. Yajl hỗ trợ phân tích cú pháp luồng, cho phép bạn đọc từng đối tượng từ một tệp/luồng. Có nói rằng, nó không giống như Python đã cam kết ràng buộc làm việc cho Yajl ..

py-yajl đã iterload nhận xét ra, không chắc chắn lý do tại sao: https://github.com/rtyler/py-yajl/commit/a618f66005e9798af848c15d9aa35c60331e6687#L1R264

Không phải là một giải pháp Python, nhưng bạn có thể sử dụng Ruby bindings để đọc trong các dữ liệu và phát ra nó trong một định dạng mà bạn cần:

 
# gem install yajl-ruby 

require 'open-uri' 
require 'zlib' 
require 'yajl' 

gz = open('http://data.githubarchive.org/2012-03-11-12.json.gz') 
js = Zlib::GzipReader.new(gz).read 

Yajl::Parser.parse(js) do |event| 
    print event 
end 
1

Ví dụ không cho phép bất kỳ tính năng bổ sung Yajl, cho những gì bạn đang tìm kiếm bạn cần phải kích hoạt allow_multiple_values cờ trên phân tích cú pháp. Đây là những gì bạn cần phải sửa đổi để các ví dụ cơ bản để có nó phân tích cú pháp tập tin của bạn.

--- 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 là một bao bọc mỏng xung quanh yajl, vì vậy bạn có thể sử dụng tất cả các tính năng mà Yajl cung cấp. Dưới đây là tất cả các 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 

Để bật các ngày trong yajl-py bạn thực hiện như sau:

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() 
+0

Có thể không in ra kết quả không? Tệp quá lớn. Tôi chỉ muốn tạo một đối tượng mới, chẳng hạn như: data = parser.parse (f) –

-1

Là một workaround bạn có thể chia nhỏ các tập tin GitHub Lưu Trữ vào dòng và sau đó phân tích mỗi dòng như json:

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

Chỉ có một dòng trong các tệp dữ liệu năm 2012. –

1

Tôi biết điều này đã được trả lời, nhưng tôi thích cách tiếp cận sau và không sử dụng bất kỳ gói nào. Từ điển github nằm trên một dòng vì một lý do nào đó, vì vậy bạn không thể giả định một từ điển duy nhất trên mỗi dòng. Điều này trông giống như:

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

Tôi quyết định tạo một hàm tìm nạp một từ điển tại một thời điểm. Nó trả về json như một chuỗi.

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 

tôi đã sử dụng chức năng này để lặp qua các kho lưu trữ với một vòng lặp 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) 

này hoạt động trên các bài tập dữ liệu ở đây: http://www.githubarchive.org/ (sau gunzip)

+0

Phương pháp của bạn sẽ phá vỡ ở một số kết thúc sai. Hãy thử đọc 2012-03-10-22.json.gzip, Comapre với phương pháp này: http://stackoverflow.com/questions/36967236/parse-multiple-json-objects-that-are-in-one-line –

Các vấn đề liên quan