O Twitter não é apenas uma fonte estendida de notícias, é de longe uma das melhores amostras dos pensamentos do mundo. Com mais de 330 milhões de usuários ativos, é uma das principais plataformas onde as pessoas gostam de compartilhar seus pensamentos. Os dados do Twitter podem ser usados para uma variedade de propósitos, tais como pesquisa, insights do consumidor, insights demográficos, e muitos outros.
Portanto, o objetivo principal deste tutorial é ensinar como obter uma amostra de dados do Twitter relevante para o seu projeto ou negócio.
Antes de prosseguir, certifique-se de ter todas estas variáveis em mãos:
- Consumer Key
- Consumer Secret
- Access Token
- Access Token Secret
Se você quiser saber como adquirir os detalhes mencionados acima, leia este post no blog escrito pelo meu colega Dattatray Upase.
Agora, vamos codificar!
Definindo as variáveis de entrada
Primeiro, você precisa definir algumas das variáveis globais que precisará para o programa:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import sys start_date = sys.argv[1] #"2018-01-09" end_date = sys.argv[2] #"2018-01-10" consumerKey="Enter_Your_Consumer_Key_Here" consumerSecret="Enter_Your_Consumer_Secret_Here" accessToken="Enter_Your_Access_Token_Here" accessTokenSecret="Enter_Your_Access_Token_Secret_Here" keyword= sys.argv[3] #"tcs" lang="en" #veja o que o twitter oferece para filtragem de idioma data={} |
Estou importando ‘sys’ para obter argumentos de linha de comando, porque posso querer alterar as palavras-chave, a data de início (start-date) ou a data de término (end-date). Para o idioma, escolhi o inglês, mas você pode querer verificar quais outros idiomas são suportados. Os resultados serão armazenados em ‘data’ no final.
Como resultado, um uso típico do script seria assim:
python script.py start_date end_date keyword
Acessando a API do Twitter
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import oauth2 req_count = 0 def oauth_req(url, http_method="GET", post_body=b"", http_headers=None): global req_count,consumerKey,consumerSecret,accessToken,accessTokenSecret req_count += 1 consumer = oauth2.Consumer(key=consumerKey, secret=consumerSecret) token = oauth2.Token(key=accessToken, secret=accessTokenSecret) client = oauth2.Client(consumer, token) resp, content = client.request( url, method=http_method, body=post_body , headers=http_headers ) return content |
A req_count variável é o número de vezes que usei a API na execução do meu programa. Estou enfrentando o seguinte erro com o código fornecido:
TypeError: Unicode-objects must be encoded before hashing
Para evitar isso, estou alterando post_body=”” para post_body=b”” e isso resolve o problema.
Uso e Referência da API do Twitter
É hora de definir a URL da API para obter os dados do Twitter. Estou usando o parâmetro min_faves. Aqui está a explicação da URL e alguns truques de otimização:
‘min_faves’ é usado para definir o número mínimo de favoritos que um tweet deve ter nos dados. É um recurso muito útil, mas não é mencionado na documentação da API do Twitter.
‘q’ representa a consulta ou as palavras-chave que você deseja inserir. Aqui é importante garantir que você forneça o menor número possível de palavras-chave. Por exemplo, vamos imaginar que eu queira tweets sobre o Facebook e o Google. Se eu fornecer ambos como palavras-chave, digamos, FACEBOOK e GOOGLE, isso só me retornará no máximo 100 tweets, já que essa é uma restrição. Mas se eu executar a consulta duas vezes – uma com o Facebook e outra com o Google, posso obter um total de 200 tweets. Resumindo a história, é melhor usar uma palavra-chave por consulta.
‘lang’ representa o idioma dos tweets filtrados. Como quero obter tweets em inglês, estou definindo-o como ‘en’.
‘since’ é a data de início do período a partir do qual você deseja procurar tweets. Esta data de início deve ser dos últimos 7 dias. Este é outro recurso que não está documentado na Documentação da API do Twitter.
‘until’ representa a data de término do período desejado. Logicamente, também deve ser dos últimos 7 dias. Também não está documentado na Documentação da API do Twitter.
‘result_type’ representa o tipo de tweets que você deseja. Tem 3 valores:
‘recent’ fornece os tweets mais recentes, ou seja, os tweets no final do período selecionado.
‘popular’ fornece os tweets mais populares e, portanto, perde muitos tweets. Você sempre obteria os tweets com os principais favoritos e retweets. O min_faves recurso não teria utilidade aqui.
‘mixed’ fornece uma mistura de tweets recentes e populares.
‘count’ representa o número máximo de tweets no resultado. O padrão é definido como 15 e o máximo é 100.
Com o misto result_type e o uso de min_faves, podemos obter o máximo de tweets executando a consulta várias vezes.
|
1 2 3 |
def get_tweets(min_faves): global keyword, start_date, end_date, lang return oauth_req( 'https://api.twitter.com/1.1/search/tweets.json?' + '&q=' + keyword + '&lang=' + lang + '%20since%3A' + start_date + '%20until%3A' + end_date + '%20min_faves%3A' + str(min_faves) +'&result_type=mixed&count=100') |
Para mais recursos documentados, você também pode conferir a Documentação da API do Twitter.
Salvando/Salvamento automático dos dados de tweets recuperados
Como próximo passo, você precisa definir um método de salvamento automático/salvamento que tenha um parâmetro ‘saveOverride’. Esta etapa é simplesmente necessária para remover a restrição de tempo de salvamento automático e salvar o arquivo. Para fazer isso, eu crio um t_last para salvar o tempo de início do programa. Depois, eu o acesso no programa e verifico se já se passaram 5 minutos desde o t_last (último tempo de salvamento). Se já se passaram mais de 5 minutos, eu marco o ‘saveStatus’ como True.
Em seguida, eu verifico o ‘saveOverride’, o que simplesmente significa que preciso dar instruções ao meu programa para que, não importa o que aconteça, o arquivo seja salvo agora. Para isso, defino o saveStatus como True.
Então, se ‘saveStatus’ for True, o script alterará o t_last para o tempo atual. Depois disso, o código cria um objeto de dicionário e imprime “Salvamento automático em [time]” para que você saiba que os dados estão sendo salvos automaticamente.
Em seguida, estou verificando se o arquivo de saída já existe. Se existir, estou combinando os dados e os dados de um arquivo já salvo. Depois de combinar, estou gravando-os no mesmo arquivo. Se não existir, estou criando um novo arquivo e gravando os dados nesse arquivo.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import os import json import time import datetime t_last = time.time() def autosave(saveOverride = False): global t_last saveStatus = (time.time() > t_last + 300) if(saveOverride == True):en" saveStatus = True if(saveStatus): t_last=time.time() tmp = {} print("Autosave em " + str(datetime.datetime.now().strftime("%Y-%m-%d_%H:%M:%S"))) fnamea = keyword + "-st-" + start_date + "-ed-"+ end_date + '.json' if os.path.exists(fnamea) == True: with open(fnamea,'r+') as f: tmp = json.load(f) for i in data.keys(): tmp[i] = data[i] with open(fnamea,'w+') as f: json.dump(tmp,f) |
Como resultado, programei quase toda a funcionalidade que queria.
Otimizando ainda mais
Finalmente, é hora de fazer uso dessas funções. Estou escrevendo um loop while(1), o que significa while(True). Isso basicamente faz com que a instrução seja executada para sempre até que alguma instrução ‘break’ seja chamada ou alguma exceção seja gerada.
Primeiro, coleto os dados dos tweets no dicionário ‘d’ usando json.loads que converte os dados em um formato de dicionário. Em seguida, executo um try-catch/except no bloco de código que extrai os status dos dados. Uso try-catch porque às vezes a API do Twitter não retorna dados, mas sim um JSON mencionando o erro. Não quero que meu programa pare nesses casos. Além disso, quero que ele recupere em qual número de requisição isso está acontecendo e salve meus dados do Twitter usando o comando autosave. O Twitter nos permite fazer 180 requisições a cada 15 minutos. Isso é como 12 requisições por minuto ou uma requisição a cada cinco segundos. Só para garantir, adiciono um comando sleep para fazer meu programa dormir por 5 segundos após executar uma iteração.
Depois disso, o código exibirá o número de tweets que o script coletou até agora.
Finalmente, é hora do principal truque de otimização. Testei este script por quase uma semana e obtive o seguinte número de tweets para cada min_faves valor. Posso obter no máximo 100 tweets por requisição e quero obter o máximo possível. Atualmente, não há muitos tweets com valores mais altos de min_faves mas queremos levar em conta os momentos em que, talvez, a empresa ou a palavra-chave esteja em alta. O valor máximo de min_faves pode ser 999999.
| Valor de min_faves | Número de Tweets |
| 100,000 | 1 |
| 90,000 | 1 |
| 80,000 | 1 |
| 70,000 | 2 |
| 60,000 | 3 |
| 50,000 | 6 |
| 40,000 | 6 |
| 30,000 | 12 |
| 25,000 | 12 |
Portanto, estou usando uma lógica que obteria tweets do min_faves valor de 60000 e depois o diminui em 10000 a cada vez até atingir 10000. Mas se, por exemplo, a palavra-chave estiver em alta e eu obtiver 100 tweets quando estiver trabalhando com o valor de min_faves para ser 30000, isso vai aumentar o min_faves para 35000 e depois obter os resultados novamente. Então agora a nova lógica é 5000 em vez de 10000. No entanto, se a alteração diminuir para menos de 1000, peço para ignorar e prosseguir com a subtração de 1000.
Estou especificando um intervalo fixo de 1000 que min_faves deve diminuir se min_faves for menor ou igual a 10000.
No final do programa, o programa informará que o trabalho está concluído exibindo ‘End’.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
min_faves=60000 change=10000 #alta redução em min_faves para extrair dados interval = 500 #redução normal em min_faves para extrair dados while(1): d = json.loads(get_tweets(min_faves)) try: for i in d['statuses']: data[i['id']] = i c = len(d['statuses']) except Exception as e: print("Erro na requisição : " + str(req_count)) autosave(True) print("Na requisição: " + str(req_count) + " Total de Tweets Coletados: " + str(len(data)) + " com Min Faves: " + str(min_faves) ) if c==100 and min_faves>10000: if (change>1000): change /= 2 min_faves += change else: min_faves -= change elif min_faves>10000: min_faves -= change else: min_faves -= interval if(min_faves < 0): fnamea = keyword + '.json' autosave(True) break autosave() time.sleep(5) print("End") |
Você pode encontrar o código completo no GitHub.
Isso é tudo. No próximo tutorial de dados do Twitter, vou ensinar como recuperar tweets em tempo real usando a ferramenta de big data ‘Flume’. Fique ligado!
Comentários
Nenhum comentário ainda. Seja o primeiro.