Проверьте, имеет ли JSON var ключ обнуляемый (Twitter Streaming API) - PullRequest
0 голосов
/ 22 марта 2019

Я загружаю твиты из Twitter Streaming API, используя Tweepy. Мне удается проверить, есть ли у загруженных данных ключи как «extended_tweet», но я борюсь с определенным ключом внутри другого ключа.

def on_data(self, data):
    savingTweet = {}
        if not "retweeted_status" in data: 
            dataJson = json.loads(data)
            if 'extended_tweet' in dataJson:
                savingTweet['text'] = dataJson['extended_tweet']['full_text']
            else:
                savingTweet['text'] = dataJson['text']
            if 'coordinates' in dataJson:
                if 'coordinates' in dataJson['coordinates']:
                    savingTweet['coordinates'] = dataJson['coordinates']['coordinates']
            else:
                savingTweet['coordinates'] = 'null'

Я правильно проверяю 'extended_key', но когда я пытаюсь сделать то же самое с ['координаты] [' координаты], я получаю следующую ошибку:

TypeError: argument of type 'NoneType' is not iterable

В документации Twitter сказано, что ключевые «координаты» имеют следующую структуру:

"coordinates":
{
    "coordinates":
    [
        -75.14310264,
        40.05701649
    ],
    "type":"Point"
}

Мне удалось решить эту проблему, просто попробовав конфликтную проверку, но я думаю, что это не самый подходящий подход к проблеме. Любая другая идея?

1 Ответ

1 голос
/ 22 марта 2019

Так что документы Twitter API, вероятно, немного лгут о том, что они возвращают (шок ужас!), И похоже, что вы получаете None вместо ожидаемой структуры данных.Вы уже отказались от использования try, catch, поэтому я не буду об этом говорить, но вот несколько других предложений.

Использование dict get () default

Мне приходит в голову пара опций, во-первых, использовать возможность по умолчанию команды dict get.Вы можете обеспечить откат, если ожидаемый ключ не существует, что позволяет объединить несколько вызовов в цепочку.

Например, вы можете достичь большей части того, что вы пытаетесь сделать, с помощью следующего:

return {
    'text': data.get('extended_tweet', {}).get('full_text', data['text']),
    'coordinates': data.get('coordinates', {}).get('coordinates', 'null')
}

Это не супер красиво, но работает.Вероятно, это будет немного медленнее, чем то, что вы делаете.

Использование JSONPath

Другой вариант, который, вероятно, излишний для этой ситуации, заключается в использовании JSONPath библиотека, которая позволит вам искать в структурах данных элементы, соответствующие запросу.Что-то вроде:

from jsonpath_rw import parse

matches = parse('extended_tweet.full_text').find(data)
if matches:
    print(matches[0].value)

Это будет намного медленнее, чем то, что вы делаете, и только для нескольких полей это излишне, но если вы выполняете много такого рода работы, это может бытьудобный инструмент в коробке.JSONPath также может выражать гораздо более сложные пути или очень глубоко вложенные пути, где метод get может не работать или будет неудобен.

Сначала проанализируйте JSON!

Последнее, что я хотел бы упомянуть, это убедиться, что вы анализируете свой JSON, прежде чем выполнять тест для "retweeted_status".Если текст появляется где-либо (скажем, внутри текста твита), этот тест будет запущен.

Разбор JSON с компетентной библиотекой также обычно очень быстрый, поэтому, если у вас нет реальных проблем со скоростью, не обязательно беспокоитьсяо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...