将大型Twitter JSON数据(7GB以上)加载到Python中



我已经通过AWS建立了一个公共流来收集tweet,现在想做一些初步分析。我所有的数据都存储在S3存储桶中(5mb的文件)。

我下载了所有的文件,并将所有的文件合并为一个。每条tweet都按照Twitter规范作为标准JSON对象存储。

基本上,合并文件包含多个JSON对象。我添加了开始和结束方括号([]),使它在被读入Python时看起来像一个字典列表。所以结构是这样的(我不确定我是否可以在这里发布twitter数据):
[{"created_at":"Mon Sep 19 23:58:50 +000 2016", "id":<num>, "id_str":"<num>","text":"<tweet message>", etc.}, 
{same as above},
{same as above}]

删除第一条tweet后,我将所有内容放入www.jsonlint.com并确认它是一个有效的JSON数据结构。

现在,我试图将这些数据加载到Python中,并希望对tweet中的不同术语进行一些基本计数(例如@HillaryClinton在tweet文本中被提及多少次等)。

以前使用较小的数据集,我可以使用这样的代码:

import json
import csv
import io
data_json = open('fulldata.txt', 'r', encoding='utf-8')
data_python = json.load(data.json)

然后,我将各个字段的数据写入CSV文件,并以这种方式执行分析。

现在我有一个7GB的文件,我注意到如果我使用这个方法,Python会在"json.load(data.json)"行抛出一个错误,说"OSError: [Errno 22] Invalid Argument "。

我不确定为什么会发生这种情况,但我预计这可能是因为它试图一次将整个文件加载到内存中。这是正确的吗?

所以我试图使用ijson,这显然可以让你解析json文件。我试着写了下面的代码:

import ijson
f = open('fulldata.txt', 'r', encoding='utf-8')
content = ijson.items(f, 'item')
for item in content:
    <do stuff here>

通过这个实现,我在"for item in content"这行得到一个错误,说"json.backend .python"。

我还尝试遍历数据文件的每一行,并将其作为JSON行格式进行遍历。因此,假设每行都是一个JSON对象,我写:

raw_tweets = []
with open('full_data.txt', 'r', encoding='utf-8') as full_file:
     for line in full_file:
         raw_tweets.append(json.dumps(line))
print(len(raw_tweets)) #this worked. got like 2 million something as expected!
enter code here

但是这里,列表中的每个条目都是字符串而不是字典,这使得解析我需要的数据变得非常困难。是否有一种方法来修改这最后的代码,使其工作,因为我需要?但即便如此,考虑到内存限制,将整个数据集加载到列表中不会使将来的分析变得困难吗?

我不知道该怎么做才好。我真的很想在Python中做这些,因为我正在尝试学习如何使用Python工具进行这些分析。

有人有这方面的经验吗?是我太蠢了还是误解了一些基本的东西?

编辑:

所以,我首先去www.jsonlint.com粘贴我的整个数据集,发现删除第一条tweet后,它是有效的JSON格式。所以现在我只排除了一个文件

我基本上有一个上面提到的格式的数据集([{json1}, {json2}],其中{}中的每个实体代表一条tweet。

现在我确认了它是一个有效的JSON,我的目标是将其转换为python,每个JSON都表示为一个字典(这样我就可以轻松地操作这些文件)。如果低效,有人能纠正我的思考过程吗?

为此,我做了:

raw_tweets=[]
with open('fulldata.txt', 'r', encoding='ISO-8859-1') as full_file:
     for line in full_file:
         raw_tweets.append(json.dumps(line))
#This successfully wrote each line of my file into a list. Confirmed by checking length, as described previously.
#Now I want to write this out to a csv file. 
csv_out = io.open("parsed_data.csv", mode = 'w', encoding='ISO-8859-1')
fields = u'created_at,text,screen_name,followers<friends,rt,fav'
csv_out.write(fields) #Write the column headers out. 
csv_out.write(u'n')
#Now, iterate through the list. Get each JSON object as a dictionary and pull out the relevant information.
for tweet in raw_tweets:
#Each "tweet" is {json#},n'
    current_tweet = json.loads(tweet) #right now everything is a list of strings in the {} format but it's just a string and not a dictionary. If I convert it to a JSON object, I should be able to make a dictionary form of the data right?
row = [current_tweet.get('created_at'), '"' + line.get('text').replace('"','""') + '"', line.get('user).get('screen_name')] #and I continue this for all relevant headers

问题是,我说current_tweet的最后一行。get不工作,因为它一直说'str'没有属性'get'所以我不知道为什么json.loads()不给我一个字典…

编辑# 2

一位用户建议我删除[和]以及后面的逗号,以便每行都有有效的JSON。这样我就可以每行只使用json.loads()。我按照建议去掉了括号。对于逗号,我这样做:

raw_tweets=[]
with open('fulldata.txt', 'r', encoding='ISO-8859-1') as full_file:
     for line in full_file:
         no_comma = line[:-2] #Printed this to confirm that final comma was removed
         raw_tweets.append(json.dumps(line))

这是给出一个错误说ValueError: expected ':' Delimiter: Line 1 Column 2305 (char 2304)

为了调试这个,我打印了第一行(即我刚刚说了print(no_comma)),我注意到Python打印的实际上有多个tweet…当我在像"UltraEdit"这样的编辑器中打开它时,我注意到每个tweet都是一个不同的行,所以我假设每个JSON对象由换行字符分隔。但是在这里,当我逐行迭代后打印结果时,我看到它一次拉入多个tweet。

我应该用不同的方式迭代吗?我删除逗号的方法是否合适,或者我是否应该单独预处理文件?

我很确定我的JSON格式很差,但我不确定为什么以及如何去修复它。下面是我的JSON数据的一个示例。如果这是不允许的,我将删除它…

https://ufile.io/47b1

我是一个非常新的用户,但我可能能够提供部分解决方案。我认为你的格式是错误的。如果没有JSON格式,就不能导入JSON。如果您可以将tweet放入数据帧(或单独的数据帧),然后使用"DataFrame",则应该能够解决此问题。to_json"命令。如果没有安装,您将需要Pandas。

Pandas - http://pandas.pydata.org/pandas-docs/stable/10min.html

Dataframe - http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_json.html

不将整个文件作为JSON对象,而是将每行一个JSON对象用于大型数据集!

要修复格式,您应该

  1. 删除文件开头的[
  2. 删除文件末尾的]
  3. 删除每行末尾的逗号

那么你可以这样读文件:

with open('one_json_per_line.txt', 'r') as infile:
    for line in infile:
        data_row = json.loads(line)
如果可能的话,我建议使用不同的存储。我想到了SQLite

最新更新