2016-08-16 65 views
0

我想制作一个程序,让可汗学院的数学问题离线复制。我有一个巨大的21.6MB文本文件,其中包含所有练习的数据,但我不知道如何开始分析它,更不用说开始从中提取问题。如何开始拉开JSON数据块?

Here是一个包含JSON数据样本的pastebin。如果你想看到它,你可以找到它here。长时间加载的警告。

我从来没有使用JSON,但我写了一个快速的Python脚本来尝试加载单个“子块”(或等效的正确术语)的数据。

import sys 
import json 

exercises = open("exercises.txt", "r+b") 
byte = 0 
frontbracket = 0 
backbracket = 0 
while byte < 1000: #while byte < character we want to read up to 
        #keep at 1000 for testing purposes 
    char = exercises.read(1) 
    sys.stdout.write(char) 
    #Here we decide what to do based on what char we have 
    if str(char) == "{": 
     frontbracket = byte 
     while True: 
      char = exercises.read(1) 
      if str(char)=="}": 
       backbracket=byte 
       break 
     exercises.seek(frontbracket) 
     block = exercises.read(backbracket-frontbracket) 
     print "Block is " + str(backbracket-frontbracket) + " bytes long" 
     jsonblock = json.loads(block) 
     sys.stdout.write(block) 
     print jsonblock["translated_display_name"] 
     print "\nENDBLOCK\n" 


    byte = byte + 1 
+1

您没有考虑嵌套括号......您可以使用堆栈来跟踪它。 – danielfranca

+1

您可以使用[jsonlint](http://jsonlint.com/)之类的内容来复制/粘贴部分JSON,以便至少以可读格式获取它。我想我已经在那里找到了重复的模式,但是你知道你实际需要的数据吗?一旦你把它加载到'json'中,那么你就可以开始将它作为嵌套列表和字典来处理。 – roganjosh

+1

这似乎是你的重复模式:http://pastebin.com/4nSnLEFZ – roganjosh

回答

1

确定,重复模式似乎是这样的:http://pastebin.com/4nSnLEFZ

获得响应的结构的想法,你可以使用JSONlint复制你的字符串/粘贴部分和“验证”。即使您复制的部分无效,仍会将其格式化为您实际可以读取的内容。

首先,我使用requests库来为您拉动JSON。当你处理这样的事情时,这是一个超级简单的图书馆。该API响应缓慢,因为它似乎你拉动一切,但它应该工作正常。

从API获取响应后,可以使用.json()直接将其转换为python对象。你所拥有的基本上是嵌套列表和词典的混合体,你可以遍历并获取特定的细节。在下面的示例中,my_list2必须使用try/except结构,因为看起来某些条目在translated_problem_types下的列表中没有两个项目。在这种情况下,它只会放置'无'。您可能不得不为此类事情使用试验和错误。

最后,由于您之前没有使用过JSON,所以也值得注意的是,它可以像字典本身一样行为;您无法保证您获得详细信息的顺序。然而,在这种情况下,似乎最外层的结构是一个列表,所以理论上可能存在一致的顺序但不依赖于它 - 我们不知道列表是如何构建的。

import requests 

api_call = requests.get('https://www.khanacademy.org/api/v1/exercises') 
json_response = api_call.json() 

# Assume we first want to list "author name" with "author key" 
# This should loop through the repeated pattern in the pastebin 
# access items as a dictionary 
my_list1 = [] 

for item in json_response: 
    my_list1.append([item['author_name'], item['author_key']]) 

print my_list1[0:5] 

# Now let's assume we want the 'sha' of the SECOND entry in translated_problem_types 
# to also be listed with author name 

my_list2 = [] 

for item in json_response: 
    try: 
     the_second_entry = item['translated_problem_types'][0]['items'][1]['sha'] 
    except IndexError: 
     the_second_entry = 'None' 

    my_list2.append([item['author_name'], item['author_key'], the_second_entry]) 
print my_list2[0:5] 
+0

非常感谢!现在我要弄清楚如何使用这个表格作为问题文本。我正在考虑将网页抓取工具定向到“相对网址”项目。再次感谢你! – Xeneficus

+0

@Xeneficus非常欢迎:) API响应很麻烦,以我的方式挖掘。您应该尝试更多地了解API本身以针对您的请求,并且只获取您感兴趣的信息。这将a)提高响应时间并且b)停止像'item ['translated_problem_types'] [0 ] ['items'] [1] ['sha']'为单个值。祝你好运:) – roganjosh