Как исправить «статусы» KeyError при сборе твитов? - PullRequest
1 голос
/ 29 апреля 2019

Я собирал твиты пользователей, используя TwitterAPI, когда наткнулся на эту ошибку.

Поскольку я планирую сканировать не менее 500 твитов с разными атрибутами, и каждый запрос возвращает только максимум 100 твитов, я сделал функцию.

!pip install TwitterAPI
from TwitterAPI import TwitterAPI
import json

CONSUMER_KEY = #ENTER YOUR CONSUMER_KEY
CONSUMER_SECRET = #ENTER YOUR CONSUMER_SECRET
OAUTH_TOKEN = #ENTER YOUR OAUTH_TOKEN
OAUTH_TOKEN_SECRET =  #ENTER YOUR OAUTH_TOKEN_SECRET

api = TwitterAPI(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)

Вот как работает моя функция:

def retrieve_tweets(api, keyword, batch_count, total_count):
    tweets = []
    batch_count = str(batch_count)
    resp = api.request('search/tweets', {'q': 'keyword',
                                         'count':'batch_count', 
                                         'lang':'en',
                                         'result_type':'recent',
                                        }
                      )

    # store the tweets in the list
    tweets += resp.json()['statuses']

    # find the max_id_str for the next batch
    ids = [tweet['id'] for tweet in tweets]
    max_id_str = str(min(ids))

    # loop until as many tweets as total_count is collected
    number_of_tweets = len(tweets)
    while number_of_tweets < total_count:
        print("{} tweets are collected for keyword {}. Last tweet created at {}".format(number_of_tweets, keyword, tweets[number_of_tweets-1]['created_at']))
        resp = api.request('search/tweets', {'q': 'keyword',#INSERT YOUR CODE
                                             'count':'batch_count',
                                             'lang':'en',
                                             'result_type': 'recent',
                                             'max_id': 'max_id_str'
                                            }
                          )

        tweets += resp.json()['statuses']
        ids = [tweet['id'] for tweet in tweets]
        max_id_str = str(min(ids))
        number_of_tweets = len(tweets)

    print("{} tweets are collected for keyword {}. Last tweet created at {}".format(number_of_tweets, keyword, tweets[number_of_tweets-1]['created_at']))
    return tweets

После этого я запустил функцию следующим образом:

first_group = retrieve_tweets(api, 'Rock', 100, 500)

Она продолжала нормально работать до тех пор, пока180-й твит, затем выскочил:

179 tweets are collected for keyword Rock. Last tweet created at Mon Apr 29 02:04:05 +0000 2019
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-9-cbeb6ede7a5a> in <module>
      8 # Your function call should look like this:  retrieve_tweets(api,'keyword',single_count,total_count)
      9 
---> 10 k1_tweets = retrieve_tweets(api, 'Restaurant', 100, 500) #INSERT YOUR CODE HERE
     11 
     12 

<ipython-input-7-0d0c87e7c3e9> in retrieve_tweets(api, keyword, batch_count, total_count)
     55                           )
     56 
---> 57         tweets += resp.json()['statuses']
     58         ids = [tweet['id'] for tweet in tweets]
     59         max_id_str = str(min(ids))

KeyError: 'statuses' 

Это должно было быть гладко сделано до 500, и я уже несколько раз тестировал ключевое слово «состояния».

Кроме того, это происходило случайно в разные моменты фазы сбора твитов, было время, когда мне удавалось завершить свою первую группу из 500 твитов.Но затем, эта ошибка будет появляться во время сбора второй группы. Также, когда эта ошибка появляется, я больше не могу использовать ключевые «состояния», пока я не выключу свой редактор и не запущу все заново.

Вот простой тест, который я всегда выполняю до и после возникновения ошибки.

a = api.request('search/tweets', {'q': 'Fun', 'count':'10'})
a1 = a.json()
a1['statuses']

Ответы [ 2 ]

0 голосов
/ 29 апреля 2019

Ответ JSON от Twitter не всегда будет содержать statuses.Вам также нужно обработать ответ, содержащий ключ errors.Ответы об ошибках описаны здесь https://developer.twitter.com/en/docs/ads/general/guides/response-codes.html

Кроме того, ваш код использует resp.json() для получения этой структуры JSON.Это нормально, но вы также можете использовать итератор, который поставляется с TwitterAPI.Итератор будет повторять элементы, содержащиеся в statuses или errors.Вот пример использования:

resp = api.request('search/tweets', {'q':'pizza'})
for item in resp.get_iterator():
    if 'text' in item:
        print item['text']
    elif 'message' in item:
        print '%s (%d)' % (item['message'], item['code'])

Еще одна вещь, о которой вы можете не знать, это то, что TwitterAPI поставляется с служебным классом, который будет выполнять последовательные запросы и отслеживать для вас max_id.Вот краткий пример https://github.com/geduldig/TwitterAPI/blob/master/examples/page_tweets.py

0 голосов
/ 29 апреля 2019

Вы используете dict.get, чтобы получить значение для ключа statuses, которое возвращает None, если ключ отсутствует, другие дают значение для ключа statuses

tweets += resp.json().get('statuses')
if tweets:
    ids = [tweet['id'] for tweet in tweets]
    max_id_str = str(min(ids))
    number_of_tweets = len(tweets)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...