terça-feira, 20 de setembro de 2016

Como ler feed de redes sociais: Facebook, Twitter, Instagram



A ideia é simples: gostaria de postar algo nas redes sociais e seria fantástico se esses posts fossem incorporados no site.

Bom, tem como.

Primeiro vamos a estrutura:


  1. Crie uma app para armazenar esse conteúdo:
    python manage.py startapp redes_sociais
  2. models.py:
    from django.db import models
    
    # Create your models here.
    
    REDES_SOCIAIS_C = (
    	('FACEBOOK', 'Facebook'),
    	('TWITTER', 'Twitter'),
    	('INSTAGRAM', 'Instagram'),
    )
    
    class Post(models.Model):
    	"""(Post description)"""
    	texto = models.TextField()
    	imagem = models.ImageField(upload_to=U.retira_acento,null=True,blank=True,)
    	imagem_src = models.TextField(null=True,blank=True)
    	redesocial = models.CharField(max_length=255, choices=REDES_SOCIAIS_C)
    	pid = models.CharField(max_length=255)
    	data = models.DateTimeField(null=True, blank=True)
    	link = models.CharField(max_length=255, null=True, blank=True)
    	ativo = models.BooleanField(default=True)
    
    	class Meta:
    		verbose_name, verbose_name_plural = u"Post" , u"Posts"
    		ordering = ('-data',)
    
    	def __unicode__(self):
    		return u"%s" % self.texto
    
    
    	def get_imagem(self):
    		if self.imagem:
    			return self.imagem
    		elif self.imagem_src:
    			return self.imagem_src
    		return None
  3. admin.py:
    # coding: utf-8
    from django.contrib import admin
    from .models import *
    
    class PostAdmin(admin.ModelAdmin):
    	search_fields = ('texto',)
    	list_display = ('texto', 'redesocial', 'pid','link' ,'data','ativo')
    	list_filter = ['redesocial','data','ativo']
    	list_editable = ['ativo',]
    	readonly_fields = ['texto', 'redesocial', 'pid','link' ,'data','imagem','imagem_src']
    	save_on_top = True
    
    	fieldsets = (
    	    (u'Ativo', {'fields': ('ativo',)}),
    	    (u'Infos', {'fields': ('redesocial', 'texto', 'pid', 'link')}),
    	    (u'Data', {'fields': ('data',)}),
    	    (u'Imagem', {'fields': ('imagem','imagem_src')}),
    	)
    
    admin.site.register(Post, PostAdmin)
    
  4. Fiz dois campos para imagens para dar prioridade de edição sobre o campo do tipo file, uma vez que o facebook retorna o caminho da imagem com mais de 255 chars para um varchar normal. O método get_imagem é o responsável por definir qual imagem exibir.

Instagram:

  1. Instale o app em seu celular e crie uma conta.
  2. Acesse: https://www.instagram.com/developer/ e registre uma aplicação
    1. Na aba Details preencha as informações obrigagtórias
    2. Na aba Security coloque uma url válida em Valid redirect URIs. Esta urla lhe dará o access token depois da autorização
    3. Desabilite a opção: Disable implicit OAuth
    4. Acesse https://www.instagram.com/oauth/authorize/?client_id=[CLIENT_ID]&redirect_uri=[URI_DO_PASSO 2.2]&response_type=code
    5. Você será redirecionado para a URI informada com o seu access token no get:
      1. EX: [URI_DO_PASSO 2.2]/?code=rx1p450j0gz2ahgq8ufn0mvw50mvv47e
  3. Configure seu settings.py com as informações abaixo:
    # INSTAGRAM
    INSTAGRAM_USER_ID = '[USER_ID DO FEED]'
    INSTAGRAM_CLIENT_ID = '[CLIENT_ID DO PASSO 2]'
    INSTAGRAM_CLIENT_SECRET = '[CLIENT_SECRET DO PASSO 2]'
    INSTAGRAM_ACCESS_TOKEN = '[TOKEN OBTIDO NO PASSO 5.1]'
    
    
  4. Para o [USER_ID DO FEED] utilizei um site que fornece de maneira fácil: https://smashballoon.com/instagram-feed/find-instagram-user-id/
  5. Instale o python-instagrampy no seu ENV:
    pip install python-instagram==1.3.2
  6. Crie um arquivo chamado feed_instagram.py na mesma pasta do settings.py com o seguinte conteúdo:
    #!/usr/bin/env python
    # coding: utf-8
    
    from os.path import abspath, dirname
    from datetime import datetime, date, timedelta
    import sys, os, commands, time
    
    SETTINGS_DIRECTORY = dirname(dirname(abspath(__file__)))
    
    sys.path.insert(0, SETTINGS_DIRECTORY)
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    
    from django.conf import settings
    from django.db.models import Count, Min, Sum, Avg
    
    from django.template.defaultfilters import slugify
    
    import re, json
    
    def log(texto):
    	print "===================================="
    	print texto
    	print "===================================="
    
    
    def carga():
    	log("INICIO DA ROTINA")
    	from redes_sociais.models import Post
    	from instagram.client import InstagramAPI
    
    	# AUTH REQUIRED
    	access_token = settings.INSTAGRAM_ACCESS_TOKEN
    	client_secret = settings.INSTAGRAM_CLIENT_SECRET
    	api = InstagramAPI(access_token=access_token, client_secret=client_secret)
    	recent_media, next_ = api.user_recent_media(user_id=settings.INSTAGRAM_USER_ID, count=10)
    	for media in recent_media:
    		#print dir(media)
    		#print media.caption.text
    		post = Post.objects.filter(pid=media.id)
    
    		texto = media.caption.text if media.caption else None
    
    		try:
    			if post:
    				post = post[0]
    				post.texto = u'{0}'.format(texto)
    				post.data = media.created_time
    				post.imagem = media.get_standard_resolution_url()
    			else:
    				post = Post(
    					redesocial = 'INSTAGRAM',
    					pid = media.id,
    					texto = u'{0}'.format(texto),
    					data = media.created_time,
    					link = media.link,
    					imagem = media.get_standard_resolution_url(),
    				)
    			post.save()
    		except Exception, e:
    			log(u"Erro ao inserir [{0}]: {1}".format(media.id, media.get_standard_resolution_url()))
    			log(e)
    
    	# AUTH NON REQUIRED
    	# api = InstagramAPI(client_id=settings.INSTAGRAM_CLIENT_ID, client_secret=settings.INSTAGRAM_CLIENT_SECRET)
    	# popular_media = api.media_popular(count=20)
    	# for media in popular_media:
    	# 	print media.images['standard_resolution'].url
    
    	log("FIM DA ROTINA")
    
    if __name__ == '__main__':
    	os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
    	from django.core.wsgi import get_wsgi_application
    	application = get_wsgi_application()
    
    	carga()
    
    
    

Twitter

  1. Crie um aplicativo em: https://apps.twitter.com/
  2. Após criado, na aba settings tem as informações necessárias para configuração:
    1. Access Token [TOKEN]
    2. Access Token Secret [TOKEN_SECRET]
    3. Access Level Read and write
    4. Owner [SEU USUARIO]
    5. Owner ID [SEU ID]
  3. Configure seu settings.py com as informações abaixo:
    1. # TWITTER
      TWITTER_USERNAME = 'zejuniortdr'
      TWITTER_CONSUMER_KEY = '0aYPbXNNNYvhGyPg9CYufUncN'
      TWITTER_CONSUMER_SECRET = 'Lf6MfaSRp3qQaAGlbrVyt0hyo3659obj5bL2W6tiO8PWEAE0vU'
      TWITTER_ACCESS_TOKEN = '30026596-WKqQtcC3AmboRBOqp9uE1cEPfJkZIfeNB8mdR1nVK'
      TWITTER_ACCESS_SECRET = '9j7D0yzgvIybg6vnB9iqac1354Shv21YE2OwSO1oUarTw'
      
  4. Instale o python-instagrampy no seu ENV:
    pip install tweepy==3.3.0
  5. Crie um arquivo chamado feed_twitter.py na mesma pasta do settings.py com o seguinte conteúdo:
    #!/usr/bin/env python
    # coding: utf-8
    
    from os.path import abspath, dirname
    from datetime import datetime, date, timedelta
    import sys, os, commands, time
    
    SETTINGS_DIRECTORY = dirname(dirname(abspath(__file__)))
    
    sys.path.insert(0, SETTINGS_DIRECTORY)
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    
    from django.conf import settings
    
    import re
    
    def log(texto):
    	print "===================================="
    	print texto
    	print "===================================="
    
    
    def carga():
    	log("INICIO DA ROTINA")
    	from redes_sociais.models import Post
    	import tweepy
    	from tweepy import OAuthHandler
    
    	consumer_key = settings.TWITTER_CONSUMER_KEY
    	consumer_secret = settings.TWITTER_CONSUMER_SECRET
    	access_token = settings.TWITTER_ACCESS_TOKEN
    	access_secret = settings.TWITTER_ACCESS_SECRET
    
    	auth = OAuthHandler(consumer_key, consumer_secret)
    	auth.set_access_token(access_token, access_secret)
    
    	api = tweepy.API(auth)
    
    	username = settings.TWITTER_USERNAME
    	user = tweepy.API(auth).get_user(username)
    	# log(dir(user))
    
    
    	status = api.user_timeline(screen_name=username, count=200, include_entities=True)
    
    
    	for s in status:
    		imagem = None
    		if 'media' in s.entities.keys():
    			imagem = s.entities['media'][0]['media_url']
    
    		post = Post.objects.filter(pid=s.id)
    		try:
    			if post:
    				post = post[0]
    				post.texto = u'{0}'.format(s.text)
    				post.data = s.created_at
    				post.imagem = imagem
    			else:
    				post = Post(
    					redesocial = 'TWITTER',
    					pid = s.id,
    					texto = u'{0}'.format(s.text),
    					data = s.created_at,
    					link = 'https://twitter.com/{0}/status/{1}'.format(username, s.id),
    					imagem = imagem,
    				)
    			post.save()
    		except Exception, e:
    			log(u"Erro ao inserir [{0}]: {1}".format(status.id, status.text))
    
    	log("FIM DA ROTINA")
    
    if __name__ == '__main__':
    	os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
    	from django.core.wsgi import get_wsgi_application
    	application = get_wsgi_application()
    
    	carga()
    
    

Facebook

  1. Crie um app com uma conta de desenvolvedor onde esta pessoa seja um dos administradores da Fan Page que quer extrair o feed: https://developers.facebook.com/apps
  2. Configure seu settings.py com as informações abaixo:
    # FACEBOOK
    FACEBOOK_PAGE_ID = [ID DA PAGINA QUE QUER O FEED DE POSTAGENS] # must be integer
    FACEBOOK_APP_ID = [ID DA APLICACAO CRIADA] # must be integer
    FACEBOOK_APP_SECRET = "[APP SECRET DA APLICACAO CRIADA]"
    
  3. Instale as dependencias do Facebook no seu ENV:
    facebook-sdk==2.0.0
    facepy==1.0.8
  4. Crie um arquivo chamado feed_facebook.py na mesma pasta do settings.py com o seguinte conteúdo:
    #!/usr/bin/env python
    # coding: utf-8
    
    from os.path import abspath, dirname
    from datetime import datetime, date, timedelta
    import sys, os, commands, time
    
    SETTINGS_DIRECTORY = dirname(dirname(abspath(__file__)))
    
    sys.path.insert(0, SETTINGS_DIRECTORY)
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    
    from django.conf import settings
    from django.db.models import Count, Min, Sum, Avg
    
    from django.template.defaultfilters import slugify
    
    import re, json
    
    def log(texto):
    	print "===================================="
    	print texto
    	print "===================================="
    
    
    def carga():
    	log("INICIO DA ROTINA")
    	from redes_sociais.models import Post
    	from facepy import utils, GraphAPI
    	import facebook
    
    	app_id = settings.FACEBOOK_APP_ID
    	page_id = settings.FACEBOOK_PAGE_ID
    	app_secret = settings.FACEBOOK_APP_SECRET
    	oath_access_token = utils.get_application_access_token(app_id, app_secret)
    
    
    	a = GraphAPI(oath_access_token)
    	response = a.get('{0}/posts?fields=id,picture,message,link,full_picture,created_time,object_id'.format(page_id))
    
    	for r in response['data']:
    		post_id = None
    		post_message = None
    		post_link = None
    		post_full_picture = None
    		post_created_time = None
    		for k, v in r.items():
    			if k == 'id':
    				post_id = v
    			elif k == 'message':
    				post_message = v
    			elif k == 'link':
    				post_link = v
    			elif k == 'full_picture':
    				post_full_picture = v
    			elif k == 'created_time':
    				post_created_time = v
    
    		post = Post.objects.filter(pid=post_id)
    
    
    		try:
    			if post:
    				post = post[0]
    				post.texto = u'{0}'.format(post_message)
    				post.pid = u'{0}'.format(post_id)
    				post.data = post_created_time
    				post.imagem_src = post_full_picture
    				post.link = u'{0}'.format(post_link)
    			else:
    				post = Post(
    					texto = u'{0}'.format(post_message),
    					redesocial = 'FACEBOOK',
    					pid = u'{0}'.format(post_id),
    					imagem_src = post_full_picture,
    					data = post_created_time,
    					link = u'{0}'.format(post_link),
    				)
    
    			post.save()
    		except Exception, e:
    			log(u"Erro ao inserir [{0}]: {1} - {2}".format(post_id, post_message, e))
    
    
    	log("FIM DA ROTINA")
    
    if __name__ == '__main__':
    	os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
    	from django.core.wsgi import get_wsgi_application
    	application = get_wsgi_application()
    
    	carga()
    
    
    

Agora para executar as rotinas, basta estar com seu ENV ativado e rodar os comandos:
python app/feed_instagram.py 
python app/feed_twitter.py 
python app/feed_facebook.py

Após rodar as rotinas vai ter em sua base de dados os post das três redes sociais. Na view que for fazer o render, basta utilizar o ORM  para obter os registros.

Espero ter ajudado mais gente.

Nota: do Google Plus está em desenvolvimento, mas é a documentação mais enjoada de conseguir informação. Se alguém tiver algum script pronto que faça o que estes acima se propõe a fazer seria de grande ajuda para complementar este post, com os devidos créditos, lógico.


hasta!


Nenhum comentário:

Postar um comentário