将大型Twitter JSON数据(7GB +)加载到Python

时间:2016-09-29 23:54:42

标签: json python-3.x pandas twitter ijson

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

我下载了所有内容并将所有文件合并为一个。根据Twitter规范,每条推文都作为标准JSON对象存储。

基本上,合并文件包含多个JSON对象。我添加了开始和结束方括号([]),使其看起来像是一个字典列表,当它被读入Python时。所以结构有点像这样(我不确定我是否可以在这里发布推特数据):

[{"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}]

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

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

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

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

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

现在我有一个7GB的文件,我注意到如果我使用这个方法,Python会在&#34; json.load(data.json)&#34;中引发错误。行说&#34; OSError:[Errno 22]参数无效。

我不确定为什么会这样,但我预计可能是因为它试图将整个文件一次性加载到内存中。它是否正确?

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

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

通过这种实现,我在第34行的内容中收到错误&#34;说&#34; ijson.backends.python.unexpectedsymbol:意外符号&#39; / u201c&#39;在1

我还尝试遍历数据文件的每一行,并以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并粘贴了我的整个数据集,发现删除第一条推文后,它是有效的JSON格式。所以现在我只是排除了那个文件。

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

现在我确认它是一个有效的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的最后一行是不行的,因为它一直说&#39; str&#39;没有属性&#39; get&#39; 所以我不确定为什么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:期待&#39;:&#39;分隔符:第1行第2305行(字符2304)

为了调试这个,我打印了第一行(即我刚才说print(no_comma)),我注意到Python打印的内容实际上有多条推文...当我在编辑器中打开它时,如#34; UltraEdit& #34;我注意到每条推文都是一条截然不同的行,所以我假设每个JSON对象都被换行符分隔。但是在这里,当我逐行迭代后打印结果时,我发现它同时引入了多条推文。

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

我非常确定我的JSON格式不佳,但我不确定为什么以及如何修复它。以下是我的JSON数据示例。如果不允许,我会删除它......

https://ufile.io/47b1

2 个答案:

答案 0 :(得分:1)

我是一个非常新的用户,但我可以提供部分解决方案。我相信你的格式是关闭的。您不能将其作为JSON导入,而不是JSON格式。如果您可以将推文放入数据框(或单独的数据框),然后使用&#34; DataFrame.to_json&#34;你应该能够解决这个问题。命令。如果尚未安装Pandas,你将需要它。

熊猫 - enter image description here

数据框 - http://pandas.pydata.org/pandas-docs/stable/10min.html

答案 1 :(得分:0)

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

要修复格式,您应该

  1. 删除文件开头的[
  2. 删除文件末尾的]
  3. 删除每行末尾的逗号
  4. 然后你可以这样读取文件:

    with open('one_json_per_line.txt', 'r') as infile:
        for line in infile:
            data_row = json.loads(line)
    

    如果可能的话,我建议使用不同的存储空间。想到了SQLite。