我已经通过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对象用于大型数据集!
要修复格式,您应该
- 删除文件开头的
[
- 删除文件末尾的
]
- 删除每行末尾的逗号
那么你可以这样读文件:
with open('one_json_per_line.txt', 'r') as infile:
for line in infile:
data_row = json.loads(line)
如果可能的话,我建议使用不同的存储。我想到了SQLite