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

Posted

技术标签:

【中文标题】将大型 Twitter JSON 数据 (7GB+) 加载到 Python 中【英文标题】:Loading Large Twitter JSON Data (7GB+) into Python 【发布时间】:2017-02-08 10:52:39 【问题描述】:

我通过 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 会在 "json.load(data.json)" 行中抛出一个错误,提示“OSError: [Errno 22] Invalid论据。

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

所以我尝试使用 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”这一行得到一个错误,说“ijson.backends.python.unexpectedsymbol:unexpected symbol '/u201c' at 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 的最后一行不起作用,因为它一直说 '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: Expecting ':' Delimiter: Line 1 Column 2305 (char 2304)

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

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

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

https://ufile.io/47b1

【问题讨论】:

【参考方案1】:

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

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

数据框 - http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_json.html

【讨论】:

对不起,如果我很笨,但我的格式有什么问题?即我该如何修复它?我以为是 JSON 格式。 请发表您自己的答案,然后保留链接作为参考以获取更多详细信息。 我删除了我的集合中的第一条推文,并将所有其他推文复制到 www.jsonlint.com,它说这是有效的 JSON...所以我猜第一个有问题一个,但其余的工作。【参考方案2】:

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

要修复格式,您应该

    删除文件开头的[ 删除文件末尾的] 删除每行末尾的逗号

然后你可以这样读取文件:

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

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

【讨论】:

我用我尝试过的内容更新了我的帖子——我有点卡住了,因为我认为这是一个 JSON 问题。你说的我都做了。 好吧,经过一番折腾,我设法通过说 tweets = tweets.append(json.loads(json.dumps(line))) 将 JSON 对象附加到我的列表中。我认为 json.loads 应该给我一个对象,但我只得到一个字符串... 您似乎要从每一行中删除 2 个字符。那是完全不同的。

以上是关于将大型 Twitter JSON 数据 (7GB+) 加载到 Python 中的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Twitter API 用于超过 REST 速率限制的大型 Web 应用程序

使用 csv 或 json 处理 python twitter api 数据

json 手动将Twitter应用程序授权给Twitter帐户

将大型响应 Json 作为多部分数据或多个部分发送

将大型 JSON 文件数据加载到 Angular cli 表中

如何定期将大型 JSON 数据集导入 Cloud Firestore?