O intuito deste projeto é familiarizar os alunos à linguagem de programação, à sintaxe da linguagem utilizada, e estimular a descoberta e pesquisa de novas funcionalidades. A escolha foi feita baseada na pergunta “Como posso usar Python no dia-a-dia?”.
Criado em 2006, o Twitter é uma rede social de microblogging, que permite atualizações de status de até 140 caracteres. Essas atualizações de status são mais conhecidas como “tweets”. Um usuário pode seguir outro usuário, o que significa que ele está disposto a acompanhar os tweets e a mídia compartilhada pelo colega. Cada usuário tem a sua linha do tempo, onde ele visualiza os tweets dos usuários que ele segue.
O Twitter disponibiliza uma API REST, isso significa que conseguimos recuperar ou informações vindas do Twitter para a nossa aplicação, além de conseguimos enviar informações da nossa aplicação ao Twitter.
Leia a especificação deste projeto com atenção, ela lhe guiará a estabelecer a conexão e a autenticação do seu código ao Twitter. O seu trabalho será criar as funções necessárias para facilitar o uso da API REST do Twitter, além de poder integrá-las às funcionalidades de Python.
Ao final deste projeto, sinta-se livre para continuar estudando, pesquisando e melhorando seu código depois da entrega. Se quiser, você também pode usar outras bibliotecas para adicionar mais funcionalidades!
- Ter o Python 3.5 instalado
- Ter o pip funcionando
- Ter uma conta no twitter, com um número de telefone associado.
- Ter paciência para ler a documentação da REST API do Twitter quando necessário
Abra o prompt de comando, digite
pip install requests requests_oauthlib
e tecle enter.
A instalação deverá seguir com sucesso.
Crie uma nova aplicação no Twitter Apps. Escolha o nome e a descrição do seu app. Na opção de website, adicione um placeholder (exemplo: https://www.meuprojetopython.com), pois não usaremos o nosso app em um site, e sim, no interpretador de Python. Aceite os termos e crie o app.
Na aba “Keys and Access Tokens”, no painel “Your Access Token”, clique em “Create my access token”. Agora você tem em mãos as 4 cadeias de caracteres necessárias para se autenticar no seu app.
Inicie o seu programa Python com a seguinte linha:
from requests_oauthlib import OAuth1Session
Isso importará a biblioteca que possibilita a autenticação ao Twitter. Armazene em variáveis cada uma das chaves conseguidas no passo anterior.
API_KEY = 'sua api key'
API_SECRET = 'sua api secret'
ACCESS_TOKEN = 'sua access token'
ACCESS_TOKEN_SECRET = 'sua access token secret'
Agora, vamos armazenar uma sessão em uma variável. É através da sessão que conseguimos usar o resto da API.
session = OAuth1Session(API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
Na página da API de busca é possível obter a url acessada para construir uma query de busca.
https://api.twitter.com/1.1/search/tweets.json?
Se quisermos fazer uma consulta para retornar os últimos tweets contendo a palavra “projeto”, podemos adicionar o parâmetro q ao final da url, com o valor do que queremos procurar.
https://api.twitter.com/1.1/search/tweets.json?q=projeto
Então, agora guardaremos essa url em uma variável
url = "https://api.twitter.com/1.1/search/tweets.json?q=projeto"
Uma dica: você ainda pode armazenar o termo da busca em outra variável, e usar a interpolação!
url = "https://api.twitter.com/1.1/search/tweets.json?q="
termo = 'projeto'
url = url % termo
Se você quiser saber todos os possíveis parâmetros em uma consulta na API de busca, acesse a documentação referente a busca de tweets.
Agora criaremos uma variável response que irá armazenar o acesso à essa url com a nossa autenticação definida anteriormente.
response = session.get(url)
Pronto! Conexão feita. Se imprimirmos ela, veremos o código 200, isto significa que está tudo ok.
Para conseguirmos ler os dados armazenados no response, podemos usar o método .text, que nos retorna uma string grandona com várias informações sobre todos os tweets. CUIDADO! Muito provavelmente isto irá travar o seu IDLE, pois a string é realmente muito grande. Para poder transformar essa string em algo que o Python consiga trabalhar melhor, podemos usar a biblioteca json que já vem instalada, e seu método loads.
import json # Adicionar esta linha no início do código
# bla bla bla some code
tweets = json.loads(response.text)
O método loads vai retornar um dicionário baseado na string gigante. Agora, será que a variável tweets já está armazenando diretamente os tweets?
Na verdade a variável tweets até então está armazenando um dicionário de apenas duas chaves: “search_metadata” e “statuses” (Com o método de dicionários .keys() você pode ver isso). Podemos observar a versão “bonita” desse dicionário aqui:
{
'search_metadata': {
'refresh_url': '?since_id=890775573047455745&q=python&include_entities=1',
'since_id_str': '0',
'since_id': 0,
'count': 1,
'completed_in': 0.02,
'max_id': 890775573047455745,
'max_id_str': '890775573047455745',
'next_results': '?max_id=890775573047455744&q=python&count=1&include_entities=1',
'query': 'python'
},
'statuses': [{
'in_reply_to_user_id_str': None,
'id': 890775573047455745,
'is_quote_status': False,
'retweeted': False,
'in_reply_to_user_id': None,
'contributors': None,
'metadata': {
'result_type': 'recent',
'iso_language_code': 'en'
},
'place': None,
'coordinates': None,
'created_at': 'Fri Jul 28 03:27:01 +0000 2017',
'retweet_count': 0,
'favorited': False,
'entities': {
'user_mentions': [],
'hashtags': [{
'indices': [60, 67],
'text': 'python'
}, {
'indices': [68, 80],
'text': 'filesystems'
}],
'urls': [{
'indices': [81, 104],
'display_url': 'goo.gl/C5GYHl',
'url': 'https://t.co/0qYkmFiACm',
'expanded_url': 'https://goo.gl/C5GYHl'
}],
'symbols': []
},
'possibly_sensitive': False,
'in_reply_to_status_id': None,
'in_reply_to_screen_name': None,
'truncated': False,
'text': "How to get full path of current file's directory in Python? #python #filesystems https://t.co/0qYkmFiACm",
'favorite_count': 0,
'user': {
'id': 747460774998605825,
'name': 'PythonQnA',
'profile_image_url_https': 'https://pbs.twimg.com/profile_images/747461193653092352/Mz9NjeE__normal.jpg',
'notifications': False,
'profile_sidebar_border_color': 'C0DEED',
'profile_link_color': '1DA1F2',
'url': None,
'profile_text_color': '333333',
'profile_sidebar_fill_color': 'DDEEF6',
'profile_use_background_image': True,
'protected': False,
'location': 'Bengaluru, India',
'entities': {
'description': {
'urls': []
}
},
'time_zone': None,
'profile_background_image_url': None,
'created_at': 'Mon Jun 27 16:05:10 +0000 2016',
'favourites_count': 0,
'profile_background_image_url_https': None,
'is_translator': False,
'followers_count': 697,
'lang': 'en',
'following': False,
'profile_background_tile': False,
'default_profile_image': False,
'follow_request_sent': False,
'screen_name': 'PythonQnA',
'geo_enabled': False,
'profile_background_color': 'F5F8FA',
'listed_count': 274,
'statuses_count': 93653,
'profile_banner_url': 'https://pbs.twimg.com/profile_banners/747460774998605825/1467044067',
'default_profile': True,
'friends_count': 64,
'is_translation_enabled': False,
'translator_type': 'none',
'has_extended_profile': True,
'profile_image_url': 'http://pbs.twimg.com/profile_images/747461193653092352/Mz9NjeE__normal.jpg',
'id_str': '747460774998605825',
'utc_offset': None,
'verified': False,
'description': 'I tweet Python questions from stackoverflow.',
'contributors_enabled': False
},
'id_str': '890775573047455745',
'geo': None,
'source': '<a href="http://jarvis.ratankumar.org/" rel="nofollow">PythonQnA</a>',
'lang': 'en',
'in_reply_to_status_id_str': None
}]
}
Este dicionário foi “embelezado” pelo Python Beautifier
A chave “search_metadata” tem como valor os metadados da busca, já a chave “statuses” tem como valor uma lista de tweets, que é o que queremos agora. Então podemos trocar a linha que atribuía todo o dicionário a variável tweets, por esta linha:
tweets = json.loads(response.text)['statuses']
Agora a variável tweets contém uma lista de tweets!
Um fato interessante é que cada tweet nessa lista, é um dicionário. Se necessário, volte ao dicionário embelezado das páginas anteriores. A chave “text” do dicionário, tem o texto do tweet como valor. Então, se quisermos imprimir o conteúdo de todos os tweets recuperados pela nossa busca, podemos rodar um laço pela lista e printar o valor de chave ‘text’.
for tweet in tweets:
print(tweet['text'])
E se para cada tweet retornado pela consulta, quisermos imprimir o nome do usuário que tweetou? Podemos ver no dicionário embelezado que o dicionário do tweet tem uma chave “user”. O valor que a chave “user” referencia, por sua vez, também é um dicionário, que tem uma chave “name” e outra chave “screen_name”. Essas chaves referenciam respectivamente os valores de nome do usuário, e login do usuário que criou aquele tweet. Confuso? Volte alguns passos. Ver o dicionário embelezado ajuda bastante a entender.
for tweet in tweets:
print("%s (%s)" % (tweet['user']['name'], tweet['user']['screen_name']))
E se quisermos postar no nosso Twitter, como fazer? Na documentação da atualização de status, podemos ver que a URL base muda para
https://api.twitter.com/1.1/statuses/update.json
e o parâmetro para passar o texto é o ‘status’. Se vamos postar a palavra “projeto”, teremos a url
https://api.twitter.com/1.1/statuses/update.json?status=projeto
Vamos armazenar a url base em uma variável e o texto do tweet em outra
url = "https://api.twitter.com/1.1/statuses/update.json?status=%s"
texto = "projeto"
url = url % projeto
Anteriormente, nossa session foi feita usando o método .get(), mas se agora queremos enviar informações do nosso programa para o Twitter, teremos que usar o método .post().
response = session.post(url)
Verifique se a atualização de status apareceu no seu Twitter!
Uma url não pode conter espaços e alguns caracteres especiais, certo? Para conseguir usar uma hashtag ou um @, é necessário formatar o texto antes. O método quote pode fazer isso por você!
import requests
#some code
texto = 'Olá, mundo!'
texto = requests.utils.quote(texto)
Com o twitter hoje, é possível usar emojis em algumas partes do site. 😱 Aqui tem uma solução em Python que consegue converter os emojis para que não gere nenhum erro no IDLE. 😊 Assumindo que uma variável texto contenha um emoji:
non_bmp_map = dict.fromkeys(range(0x10000, sys.maxunicode + 1), 0xfffd)
texto.translate(non_bmp_map)
Por segurança, faça isso com todos os textos que podem conter emojis, como nomes de usuário e texto dos tweets. 😉
Para outras funcionalidades, acesse a documentação de referência. Todos os endpoints que estão na sessão GET, irão usar o método .get(), todos os que estão na sessão POST, irão usar o método POST.
Atenção: Não confunda POST / .post() com o ato “twittar” (atualização de status). Diariamente, utilizamos o verbo “postar” querendo falar da nossa atualização de status, porém, nesse contexto, POST significa qualquer operação que irá ENVIAR informações ao twitter, e nem sempre essa operação é uma atualização de status.
Quando você quiser recuperar informações vindas do Twitter, utilize o método .get(). Quando você quiser enviar informações ao Twitter, utilize o método .post().
Exemplo:
Operação para conseguir o nome de um usuário: GET,
Operação para seguir um usuário: POST
Agora que aprendemos a utilizar a API REST do Twitter, o seu trabalho é criar funções para facilitar essa conexão.
Dica: os parâmetros da função estão em negrito
- Faça uma função que crie e retorne uma sessão através das chaves API_KEY, API_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET.
- Faça uma função que retorne o url base de busca de tweets (com o parâmetro q na url).
- Faça uma função que faça uma requisição GET ao Twitter, de uma sessão s com uma url url. (utilize o método .get() e retorne o response)
- Faça uma função que faça uma requisição POST ao Twitter, de uma sessão s com uma url url. (utilize o método .post() e retorne o response)
- Faça uma função que receba um response r e retorne a lista de tweets dele.
- Faça uma função que retorne o nome do usuário criador de um tweet tw.
- Faça uma função que retorne o login do usuário criador de um tweet tw.
- Faça uma função que retorne as informações de data e hora de criação de um tweet tw.
- Faça uma função que imprima um tweet tw num formato que apareça o seu texto, data, nome do usuário e login.
- Faça uma função que receba uma lista de tweets ltw e para cada tweet, imprima ele no formato dito anteriormente.
- Faça uma função que formate um texto t. (‘Como vai?’ -> 'Como%20vai%3F')
- Faça uma função que com uma sessão s, retorne uma lista dos últimos n tweets contendo um texto t.
- Faça uma função que retorne o url base de timeline de usuário (com os parâmetros screen_name e count na url).
- Faça uma função que com uma sessão s, retorne uma lista dos últimos n tweets de um usuário de login un.
- Faça uma função que retorne o url base de atualização de status (com o parâmetro status na url).
- Faça uma função que com uma sessão s, atualize o status (poste um tweet) com um texto t.
- Faça uma função que com uma sessão s, responda um tweet tw com um texto t.
- Faça uma função que retorne o url base de criar amizade, ou seja, seguir alguém (com o parâmetro screen_name na url).
- Faça uma função que com uma sessão s, siga um usuário de login un.
- Faça uma função que com uma sessão s, siga a última pessoa que tweetou um texto t.
- Faça uma função que retorne o url base de favoritar um tweet (com o parâmetro id na url).
- Faça uma função que com uma sessão s, favorite um tweet tw.
- Faça uma função que com uma sessão s, favorite o último tweet de um usuário de login un.
- Faça uma função que retorne o url base de retweetar um tweet.
- Faça uma função que com uma sessão s, retweete um tweet tw.
- Faça uma função que com uma sessão s, retweete o último tweet contendo um texto t.
- Faça uma função que imprima um usuário u num formato que apareça o seu nome e o seu login com um login com @ na frente,
- Faça uma função que retorne o url base de lista de seguidores (com os parâmetros screen_name e count na url).
- Faça uma função que com uma sessão s, retorne uma lista dos últimos n seguidores de um usuário com login un.
- Faça uma função que com uma sessão s, para uma lista de usuários lu, envie um tweet para cada usuário saudando ele. (A saudação deve conter o nome dele)