Загрузка больших данных Twitter JSON (7 ГБ ) в Python

#json #python-3.x #pandas #twitter #ijson

#json #python-3.x #панды #Twitter #ijson

Вопрос:

Я настроил публичный поток через AWS для сбора твитов и теперь хочу провести предварительный анализ. Все мои данные были сохранены в корзине S3 (в файлах размером 5 МБ).

Я загрузил все и объединил все файлы в один. Каждый твит хранится как стандартный объект JSON в соответствии со спецификациями Twitter.

По сути, консолидированный файл содержит несколько объектов 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}]
  

После удаления самого первого твита я поместил все в 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 и таким образом выполнил свой анализ. Это сработало для файла объемом 2 ГБ.

Теперь, когда у меня есть файл объемом 7 ГБ, я замечаю, что если я использую этот метод, Python выдает ошибку в строке «json.load (data.json)», в которой говорится: «Ошибка: [Ошибка 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>
  

При этой реализации я получаю сообщение об ошибке в строке «для элемента в содержимом» со словами «ijson.backends.python.unexpectedsymbol: неожиданный символ ‘/ u201c’ в 1

Я также попытался просмотреть каждую строку файла данных и просмотреть ее в формате JSON lines. Итак, предполагая, что каждая строка является объектом 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
  

Но здесь каждая запись в списке представляла собой строку, а не словарь, что затрудняло анализ данных, которые мне были нужны. Есть ли способ изменить этот последний код, чтобы он работал так, как мне нужно? Но даже тогда, не приведет ли загрузка всего этого набора данных в список к тому, что он будет по-прежнему затруднен для будущих анализов, учитывая ограничения памяти?

I’m a little stuck about the best way to proceed with this. I really want to do this in Python because I’m trying to learn how to use Python tools for these kinds of analyses.

Does any have any experience with this? Am I being really stupid or misunderstanding something really basic?

EDIT:

So, I first went to www.jsonlint.com and pasted my entire dataset and found that after removing the first tweet, it was in valid JSON format. So for now I just excluded that one file.

I basically have a dataset in the format mentioned above ([{json1}, {json2}] where each entity in the {} represents a 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: Ожидание ‘:’ Разделитель: строка 1, столбец 2305 (символ 2304)

Чтобы отладить это, я напечатал первую строку (т. Е. Я просто сказал print(no_comma)), и я заметил, что то, что печатал Python, на самом деле содержало несколько твитов внутри… Когда я открываю его в редакторе, подобном «UltraEdit», я замечаю, что каждый твит представляет собой отдельную строку, поэтому я предположил, что каждый объект JSON был разделен символом новой строки. Но здесь, когда я печатаю результаты после итерации по строкам, я вижу, что он собирает сразу несколько твитов.

Должен ли я выполнять итерации по-другому? Подходит ли мой метод удаления запятых или я должен предварительно обрабатывать файл отдельно?

Я почти уверен, что мой JSON отформатирован плохо, но я не уверен, почему и как это исправить. Вот пример моих данных JSON. Если это не разрешено, я удалю его…

https://ufile.io/47b1

Ответ №1:

Я ОЧЕНЬ новый пользователь, но я мог бы предложить частичное решение. Я считаю, что ваше форматирование отключено. Вы не можете просто импортировать их как JSON, не имея формата JSON. Вы должны быть в состоянии исправить это, если сможете поместить твиты во фрейм данных (или отдельные фреймы данных), а затем использовать команду «DataFrame.to_json». Вам понадобятся Pandas, если они еще не установлены.

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

Фрейм данных — http://pandas.pydata.org/pandas-docs/stable/generated/pandas .DataFrame.to_json.html

Комментарии:

1. Извините, если я тупой, но что не так с моим форматированием? т.Е. Как мне это исправить? Я думал, что это в формате JSON.

2. пожалуйста, опубликуйте свой собственный ответ, а затем сохраните ссылки в качестве ссылки для получения более подробной информации.

3. Я удалил самый первый твит в своем наборе и скопировал все остальные твиты в www.jsonlint.com и там было сказано, что это Действительно Так JSON…so Я предполагаю, что с первым было что-то не так, но остальные сработали.

Ответ №2:

Вместо того, чтобы иметь весь файл в виде объекта 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.

Комментарии:

1. Я обновил свой пост тем, что я пробовал — я немного застрял из-за того, что я считаю проблемой JSON. Я сделал все, что вы сказали.

2. Хорошо, после некоторой возни мне удалось добавить объект JSON в свой список, сказав tweets = tweets.append(json.loads(json.dumps(строка))) . Я предполагаю, что json.loads должен дать мне объект, но я просто получаю строку…

3. Кажется, вы удаляете 2 символа из КАЖДОЙ строки. Это совершенно другое.