26 sept. 2013

Mostrar tweets en tiempo real con twython y el API Stream de Twitter

En el artículo anterior se mostró como ver trendings topics por región, ahora se usará el API Stream de twitter para ver el flujo de tweets que recibe el usuario o lo que se publica en general en twitter.

La idea es usar twython con la clase TwythonStreamer para acceder a la API stream de twitter.

Del API de twitter se mostrará GET user el cual muestra los mensajes en flujo de un sólo usuario.

También se mostrará como usar POST status filter, el cual muestra todos los tweets públicos que contengan una palabra (track).

El primer ejemplo es con el GET user, el código a continuación:


#!/usr/bin/env python

# -*- coding: utf-8 -*-



#Se define el token de la aplicacion

CONSUMER_KEY = 'xxxxx'

CONSUMER_SECRET = 'xxxxx'

#Se define el acceso al usuario

ACCESS_KEY = 'xxxxx'

ACCESS_SECRET = 'xxxxx'



#Se importa TwythonStreamer

from twython import TwythonStreamer





#Se crea la clase MiStream que hereda de TwythonStreamer 

class MiStream(TwythonStreamer):

    #Se crea el metodo on_success que recibe data

    def on_success(self, data):

        #Si la palabra 'text' se encuentra en data se muestra en pantalla

        #su contenido

        if 'text' in data:

            print data['text'].encode('utf-8')

            #Si se desea desconectar luego del primer resultado?

            #self.disconnect()



    #Se crea el metodo on_error que recibe el codigo de estatus y data y se muestra en pantalla

    def on_error(self, status_code, data):

        print status_code, data

# Requires Authentication as of Twitter API v1.1
#Se crea la instancia de la clase MiStream con los parametros de autenticacion del API v1.1 de twittter.
stream = MiStreame(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET)
#Se recibe los tweets del usuario.
stream.user()



El resultado se muestra a continuación:


NASA puts papers from Curiosity rover behind paywall; @mbeisen points out this is illegal & shares them http://t.co/UB1jQfRpLR #openaccess

ICYMI: Boost Mobile now offering Boost Warp 4G http://t.co/qvZKtZXqOn

Empoderando a la ciudadanía para mejorar la educación en México http://t.co/GnTqhDWqzv

BREAKING: Dodgers say man killed in altercation with Giants fans in SF was son of team security guard: http://t.co/CkB75Nkt0V

RT @Anonymous_Prodi: Posible bomba nuclear de baja intensidad en Siria http://t.co/uSjjVI1T3A @Famelica_legion @AquiyAhora_2013 @wikinotici…

guía de gobierno electrónico local: http://t.co/X6i7f8NHFe  servicios electrónicos orientados al ciudadano #eGov

¡Felicidades también a @jenniferpsayago por ser la ganadora de estos increíbles productos #Samsung y @Oakley_VE! http://t.co/ZfZnNtZtCf

#linux #fedora  #art  Re: Request to join the Design Team http://t.co/CuAuncfFPU

Del Gobierno Abierto como Política y la Apertura de Datos como Programa Público http://t.co/4fmZAHA8x6  #OpenData #OGov

#linux #fedora  #art  Re: Request to join the Design Team http://t.co/RiHSMifvBQ

3D printer duplicates paintings down to the last brush stroke http://t.co/suC4T3P2Lr #3DPrinting #art

Maduro: Mi ausencia en la ONU se debió a provocaciones que habían en mi contra http://t.co/Ed1ufBiPCW

Venezuela: Turismo “raspatarjetas” mató al turismo http://t.co/Rd18XiZYZu @kaosenlarednet mm

Como las iniciativas de Datos Abiertos pueden mejorar la vida en las Ciudades? http://t.co/j8FJOUd5mk  #OpenData

RT @csoghoian: Want to read the details of some NSA #LOVEINT surveillance abuses? Now you can, thanks to Senator @ChuckGrassley http://t.co…

¿Me está diciendo usted q su teoría mágica es: no tener teoría? Creo que eso no es muy anarquista, ni lógico tampoco @fascaso @loadupyourgun

Venezuela: Turismo “raspatarjetas” mató al turismo http://t.co/Rd18XiZYZu @kaosenlarednetmmmmm

RT @C354R_B3RMUD3Z: Te interesa saber de #Soporte Tecnico en #Gnu/Linux? #inscribete, es totalmente #gratuito informate por 04243165766

RT @csoghoian: Are you an NSA analyst? Suspect that your husband is cheating on you? Tap his phone, don't get prosecuted. Page 3 of http://…

Saturday Night Live lanza canal oficial de YouTube disponible para todo el mundo http://t.co/LDFcwFxsx0

Microsoft donated $100k to IPython http://t.co/sU2UP07dJ8

Crece el huracán: exitosos Niños Cantores de diversas tendencias políticas nos dieron hoy públicamente su apoyo http://t.co/SGDvxPrczA

How is everyone? I feel like I've been away for years when it's only been a few days.

Ahora se quiere se muestra todos los tweets públicos que contengan la palabra python, esto se logra al  sustituir la última línea del código anterior por stream.statuses.filter pasando el argumento track con la palabra a buscar.:

stream.statuses.filter(track='python')


El resultado se muestra a continuación:

lunes que viene #PUG  con pizza, cerveza, #python en @Dlabs_co . Yo no me la perdería...
Monty Python - The man who is alternately rude and polite: :#NowPlaying.#ClassicComedies..#ComedyGreats ,,,#Comedy.  http://t.co/IO3juw6nfD
Like a Kungfu master, a Pythonista knows how to kill with a single finger, and never to actually do it. http://t.co/xx0Sb8SsWV
RT @jpcolino: Python + Hadoop: Real Python in Pig trunk http://t.co/i4NZXrofvq
Affiliate Freelancer, Freelancing September 26, 2013 at 04:51PM Python web front end development by vishalchavda... http://t.co/V45nPv3LVI
Compressed 4h of Python, Win32 dbg API and Intel PIN in 2h. Still people seemed to like it. I guess a lot of people are into BSDM at @brucon
Go vs. Python: 10% longer, 10 times faster. http://t.co/v640YolHW4 and concurrent, statically compiled, and the libraries are all modern.
Quantitative Economics | #python #ebook http://t.co/eVjlO9VBoE
@MikeKellyofEM Hopefully a Monty Python style parrot...
por um tutorial de como aprender python em um dia
@tommyd_95 this could descend into a scene from a Monty Python movie ))

De esta forma se puede mejorar la captura de tweets en tiempo real  del timeline de un usuario o de todos los tweets públicos. 


22 sept. 2013

Descrubiendo Trending Topics de Twitter con twython y python

El artículo anterior muestra como probar la librería twython, hace poco se mostró en un artículo como ver los Trending Topics usando la librería python-twitter, ahora se mostrará como desplegar los topics usando la librería twython.

El script mostrará la conexión a twitter, luego despliega los identificadores de las ciudades que tienen Trending Topics en Venezuela y por último se despliega los Trending Topics de Venezuela en este momento.

Para saber como obtener el valor del token de la aplicación o de acceso se recomienda revisar el artículo anterior.
El código se muestra a continuación:

#!/usr/bin/env python

# -*- coding: utf-8 -*-



#Se define el token de la aplicacion

CONSUMER_KEY = 'xxxxx'

CONSUMER_SECRET = 'xxxxx'

#Se define el acceso al usuario

ACCESS_KEY = 'xxxxx'

ACCESS_SECRET = 'xxxxx'



#Se importa twython y de time a  sleep

from twython import Twython

from time import sleep



#Se define los argumentos del cliente, la ip y puerto del proxy, el tiempo de intento de la conexion y el nombre de la

#aplicacion cliente

client_args = {'headers': {'User-Agent': 'cmdtweetpy'},'proxies': {'http': '127.0.0.1:xxx'},'timeout': 300}



#Conectar a twitter y enviar un tweet,

#Si no se logra la conexion se devuelve un mensaje.

try:

    api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET,client_args = client_args)

    print(u"Autenticación con exito")

except twython.exceptions.TwythonAuthError:

    print(u"Error de autenticación")

print ""

trending = api.get_available_trends()

print u"Identificación de woeid de Venezuela"

print "-------------------------------------"

c = 0   

pos = 0

woeid = 0
#Se despliega los woeid de las ciudades de Venezuela y de Venezuela en si
for i in trending:
    if i[u'countryCode'] == u'VE':
        print i[u'name'],i[u'woeid']
        #Se toma el woeid de Venezuela
        woeid = i[u'woeid']
        pos = c
    c += 1
print ""
#Se despliega los topics de Venezuela.
print "Lista de Trending Topics en Venezuela"
print "-------------------------------------"
for i in api.get_place_trends(id=woeid):
    for k in i[u'trends']:
        print k[u'name']


A continuación se muestra el resultado de la ejecución del script:
Identificación de woeid de Venezuela
-------------------------------------
Caracas 395269
Maracaibo 395270
Maracay 395271
Valencia 395272
Barcelona 395273
Ciudad Guayana 395275
Turmero 395277
Barquisimeto 468382
Maturín 468384
Venezuela 23424982
Lista de Trending Topics en Venezuela
-------------------------------------
#10CosasQueOdio
#AlfombraRojaE
#EmmysPorWarner
#ChavezElGranArquitecto
#ObamaNervioso
Angela Merkel
Titanic
Kenia
GNB
Sofia Vergara

Como se ve se puede obtener el topics de cada ciudad o País al obtener el woeid.

Probando la librería twython para twitter

Retomando los artículos sobre librerías de python para acceder a twitter, en el último artículo explique como descubrir trending topic con la librería python-twitter., ahora le toca el turno a twython.
La página del proyecto se encuentra en github.

Twython soporta lo siguiente:

  • Busqueda para:
    • Información de usuario.
    • Lista de twitter.
    • Líneas de tiempo (timeline).
    • Mensajes directos (DM).
    • Cualquier cosa que se encuentre en la documentación del API de twitter.
  • Actualización de imagen:
    • Actualización de un estatus de un usuario con una imagen.
    • Cambiar el avatar de un usuario.
    • Cambiar imagen de fondo.
    • Cambiar banner.
  • Soporte de sólo lectura para OAuth2
  • Soporte para el API de stream de twitter.
  • Soporte para Python 3.
Para más información sobre la documentación la pueden visitar en el siguiente enlace.
Para manejar la autenticación de la aplicación y del código pueden revisar el artículo de Efrain Valles, jugando con las APis de twitter y python.

Para instalar twython se usa pip o easy_install como root desde la línea de comandos:
root@grievous:~# pip install twython

Lo primero que se va a hacer es envíar un tweet con una imagen y luego sólo texto, la implementación usa un proxy para enviar los tweets, luego se muestra en pantalla el timeline del usuario y por último el resultado de la busqueda de la palabra python.

El código de la aplicación se muestra a continuación:

#!/usr/bin/env python

# -*- coding: utf-8 -*-



#Se define el token de la aplicacion

CONSUMER_KEY = 'xxxxx'

CONSUMER_SECRET = 'xxxxx'

#Se define el acceso al usuario

ACCESS_KEY = 'xxxxx'

ACCESS_SECRET = 'xxxxx'



#Se importa twython y de time a  sleep

from twython import Twython

from time import sleep



#Se define los argumentos del cliente, la ip y puerto del proxy, el tiempo de intento de la conexion y el nombre de la

#aplicacion cliente

client_args = {'headers': {'User-Agent': 'cmdtweetpy'},'proxies': {'http': '127.0.0.1:xxxx'},'timeout': 300}



#Conectar a twitter y enviar un tweet,

#Si no se logra la conexion se devuelve un mensaje.

try:

    api = Twython(CONSUMER_KEY,CONSUMER_SECRET,ACCESS_KEY,ACCESS_SECRET,client_args = client_args)

    photo = open('linux.jpg','rb')

    api.update_status_with_media(media=photo, status='May the source be with you=> ')

    api.update_status(status="Enviando tweets con twython por medio de un proxy")

    print("Tweet enviado con exito")

except twython.exceptions.TwythonAuthError:

    print(u"Error de autenticación, no se pudo envíar el tweet")



#Listar el timeline del usuario

listado = api.get_home_timeline()
print("Timeline del usuario _seraph1")
print("-----------------------------")
for i in listado:
    print i[u'text']
    sleep(1)
print("-----------------------------")
#Se realiza una busqueda de la palabra python con tipo de resultado popular
resultados = api.search(q='python',result_type='popular')
#resultados = api.search(q='python')
#
datos= resultados.keys()
print("Elementos del diccionario: %s" %datos)
print("Resultado de la busqueda: python")
print("--------------------------------")
for i in range(len(resultados[datos[1]])):
        print resultados[datos[1]][i][u'text']
        print "***********************************"
print("--------------------------------")



A continuación se muestra la salida de la aplicación:

Tweet enviado con exito
Timeline del usuario _seraph1
-----------------------------
Bo Xilai Gets Life Sentence http://t.co/oWBTgTBJKv
(Starting with "A") Armstrong, Aslan, Atran: Who will be the first to say this has nothing to do with religion?
http://t.co/8IacERuHN7
All About Team Building & #Leadership Exercises at Work! http://t.co/SEI89zGp8P #managers
#linux #netdev  Re: [Xen-devel] [PATCH net-next] xen-netfront: convert to GRO API and advertise this feature http://t.co/3nWDlbv7pT
#linux #netdev  [PATCH net 3/5] bnx2x: 57840 non-external loopback test fail on 1G http://t.co/tI6azgkcBZ
"Read the collective bargaining agreement, we can do that" RT @BradStone: ESPN reports #Browns now fielding offers for their fans' souls.
“@SoftwareHollis: @CloudExpo - can't wait for November.  Looking forward to presenting! http://t.co/b3dc2a08KU #Cloud #SocialMedia #SaaS”
.@jeancase - this is really about the democratization of ideas - the smartest people in the room probably don't work for you #2030NOW
Achieving Accountability With Talk of Infidelity - via @toddbnielsen http://t.co/hZktGZZ3EK #leadership
RT @les_leopold: Solution to the Student Debt Crisis: No More Debt
http://t.co/hsvdZj9uJQ
Recuerda cerrar sesión cuando entres a #Clavenet desde cualquier equipo. #TipdeSeguridad
-----------------------------
Elementos del diccionario: [u'search_metadata', u'statuses']
Resultado de la busqueda: python
--------------------------------
"Well, everday's a workout when you gotta carry around a 20 pound python in your jeans." -Will Forte 'MacGruber' 2010
***********************************
Aprende Python desde cero [Guía completa] http://t.co/ZZE2NXEOVG #YoComparto
***********************************
「d3はシングルスレッドなのでHadoopからデータ直接流し込んで大規模処理するわけにはいかないから、サーバ側でPythonとか走らせ、集計やサンプリング済みデータをJSに渡して可視化してる」的なこと言ったら「フリーソフトでは大規模なデータマイニングは難しい」っていう纏め方された
***********************************
Please RT! The most significant fact about today's Raspberry Jam for kids at PyconUK is the gender split: 50/50. #python #progress
***********************************
先方、データマイニングについての記事のインタビューなのにPythonとか全く知らない(名前すらしらない)ようで、RやPython、果てはd3.jsとか全部ひっくるめて「フリーソフトを利用して分析している」っていうすごいざっくりしたまとめられ方してて、前後の話に矛盾が出てる
***********************************
Obviously Monty Python was never shown on JA TV as the Reggae Charts out there have Silly Walks Record label listed as err..'Silky Walks".
***********************************
Air Jordan IV “Black Python” Customs. WIN or BIN? #CurtienFashion http://t.co/SHu9MKOOB5
***********************************
Defenders of Obamacare dismissing "glitches" increasingly sound like the Black Knight from Monty Python http://t.co/SGV8ys8hMF
***********************************
Without this Beatle, Monty Python's "Life of Brian" would never have been made http://t.co/85ys7bLo6S #5facts
***********************************
Indonesia adalah Tempat ditemukannya ular terpanjang di dunia yaitu, Python Reticulates sepanjang 10 meter di Sulawesi. #7d
***********************************
Recruiter: "I came across your resume in a Google search. You seem to have an awesome expertise on python" To Guido. https://t.co/lAbeQVgo1I
***********************************
Mozilla Webdev is looking for a Web Engineer - Python, Django, jQuery, OSS - http://t.co/9hg8GFOeSl
***********************************
Writing a High Performance Python book: I'm terribly excited to announce that I'm co-authoring an O'Reilly... http://t.co/ZctbSoZGqa
***********************************
If you can write PHP, you can write C/C++/Java/Python/Ruby/whatever.  These language aren't all that different.
***********************************
'El sentido de la vida' cumple 30 años: 12 cosas que probablemente no sabías de la peli de los Monty Python http://t.co/hBVKUCIMFJ
***********************************
--------------------------------



A continuación se muestra dos imagenes de los tweets enviados:


18 sept. 2013

Manejo de sesión en el ORM sqlalchemy

Hace tiempo explique como crear unas tablas para la base de datos sqlite3, insertar datos, removerlos y consultarlos,el artículo se llama Abstracción del motor de Base de Datos con el ORM Sqlalchemy y python.

Antes de comenzar a probar lo que se escribe en este artículo es necesario que realicen pruebas con el artículo mencionado anteriormente para que tengan la base de datos con sus datos listas para ser utilizadas en este artículo.

Ahora se explica como usar unas tablas con sus datos ya creada, creando una sesión para la base de datos.

Este artículo se basa en un tutorial en inglés de sqlalchemy o el tutorial paso a paso de sqlalchemy.

Lo primero que se hará es crear un archivo model.py que contendrá el modelo de la base de datos.

#Se importa el módulo datetime

import datetime

#Se importa schema y tupes de sqlalchemy

from sqlalchemy import schema, types



#Se instancia la clase MetaData.

metadata = schema.MetaData()



#Se crea la función now que devuelve la hora actual.

def now():

    return datetime.datetime.now()



#Se crea la instancia table con los campos de la tabla grupos

grupos_table = schema.Table('grupos',metadata,

        schema.Column('id',types.Integer,primary_key=True),

        schema.Column('grupo',types.String(300),nullable=False),

        schema.Column('descripcion',types.String(500),nullable=False),

)


#Se crea la instancia table con los campos de la tabla contactos

contactos_table = schema.Table('contactos',metadata,

        schema.Column('id',types.Integer,primary_key=True),

        schema.Column('nombre',types.String(100),nullable=False),

        schema.Column('telefono',types.String(11),nullable=False),

        schema.Column('grupo_id',types.Integer,nullable=False),

)



#Se crea la clase Contactos y Grupos que heredan de object y sólo tienen pass.

class Contactos(object): pass

class Grupos(object): pass



#Se mapea la Clase Contactos con la tabla contactos_table

orm.mapper(Contactos, contactos_table)

#Se mapea la Clase Grupos con la tabla grupos_table

orm.mapper(Grupos,grupos_table)




Ya con este código se logra el mapeo de las tablas existenes con sus campos.

Ahora se crea un archivo llamado prueba-db.py que va a realizar la sesión a la base de datos por medio del módulo model.py  donde se realizará unas consultas, inserciones y remociones de datos.



#!/usr/bin/env python

# -*- coding: utf-8 -*-



import model

from sqlalchemy import orm

from sqlalchemy import create_engine



#Crear un engine y crear todas las tablas necesarias

engine = create_engine('sqlite:///tutorial.db', echo=False)

model.metadata.bind = engine

model.metadata.create_all()



# Configurar la sesion



sm = orm.sessionmaker(bind=engine, autoflush=True, autocommit=False,

            expire_on_commit=True)

session = orm.scoped_session(sm)



#Se realiza una consulta a la tabla grupos

print "Consulta inicial de la tabla contactos"

consulta = session.query(model.Contactos).all()

for lista in consulta:

    print lista.nombre,lista.telefono

print "--------------------------------"





#Agregar un contacto

contacto = model.Contactos()

contacto.nombre = u"Luisa Gonzalez"

contacto.telefono = u"04155555555"

contacto.grupo_id = 2

session.add(contacto)

session.flush()

session.commit()





#Se realiza una consulta a la tabla grupos

print "Consulta la tabla contactos con el dato incorporado"

consulta = session.query(model.Contactos).all()

for lista in consulta:

    print lista.nombre,lista.telefono

print "--------------------------------"

    



#Borrar un contacto

session.delete(contacto)

session.flush()

session.commit()



#Se realiza una consulta a la tabla grupos

print "Consulta la tabla contactos luego de borrar el dato"

consulta = session.query(model.Contactos).all()

for lista in consulta:

    print lista.nombre,lista.telefono

print "--------------------------------"




El resultado de ejecutar el script pruebas-db.py se muestra a continuación:

Consulta inicial de la tabla contactos

Ernesto Crespo 04155673029

Pedro Perez 0295212223

Jhon Doe 04184488484

Jane Doe 04184488482

Pepito de los palotes 04184588484

--------------------------------

Consulta la tabla contactos con el dato incorporado

Ernesto Crespo 04155673029

Pedro Perez 0295212223

Jhon Doe 04184488484

Jane Doe 04184488482

Pepito de los palotes 04184588484

Luisa Gonzalez 04155555555

--------------------------------

Consulta la tabla contactos luego de borrar el dato

Ernesto Crespo 04155673029

Pedro Perez 0295212223

Jhon Doe 04184488484

Jane Doe 04184488482

Pepito de los palotes 04184588484

--------------------------------



De esta forma se puede realizar consultas, remociones e inserciones por medio de sqlalchemy con sesiones.

1 sept. 2013

Bajar vídeos de youtube desde Python con Pafy.

Pafy permite realizar busquedas de vídeos de youtube y descargarlos.

EL sitio de Pafy se encuentra en github, en ese sitio se puede bajar la librería en formato zip, tar.gz o visitar el repositorio git del proyecto.

Para instalar Pafy desde Linux se puede hacer con easy_install o pip:

pip install Pafy

Se ejecuta python:
ernesto@grievous:~$ python

Python 2.7.3 (default, Jan  2 2013, 13:56:14) 

[GCC 4.7.2] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> 

Se importa Pafy:
>>> from pafy import Pafy

Se crea la variable donde se encuentra el url del vídeo:
>>> url="http://www.youtube.com/watch?v=YOZjaqHioro"

Se crea la instancia del vídeo:
>>> video = Pafy(url)
Se obtiene el título del vídeo:
>>> video.title
u'Jimmy Fallon, Robin Thicke & The Roots Sing "Blurred Lines" (w/ Classroom Instruments)'

El rating y longitud del vídeo:

>>> video.rating
4.9188302785
>>> video.length
214

Se muestra los metadatos del vídeo:
>>> print video
Title: Jimmy Fallon, Robin Thicke & The Roots Sing "Blurred Lines" (w/ Classroom Instruments)
Author: latenight
ID: YOZjaqHioro
Duration: 00:03:34
Rating: 4.9188302785
Views: 10459846
Thumbnail: https://i1.ytimg.com/vi/YOZjaqHioro/default.jpg
Keywords: Jimmy Fallon, Late Night With Jimmy Fallon, Late Night, NBC, NBC TV, Television, Funny, Talk Show, comedic, humor, stand-up, snl, Fallon Stand-up, Fallon monologue, latenight, jokes, funny video, interview, variety, comedy sketches, talent, celebrities, music, musical performance, The Roots, video, clip, highlight, talking, youtube, jimmy fallon & robin thicke, robin thicke, blurred lines, classroom instruments, late night music room
Se muestra el título del vídeo, el autor, el ID del vídeo, la duración, el rating, la cantidad de veces que se ha visto, entre otra información.

Se muestra todos los formatos del vídeo y su resolución:
>>> streams = video.streams
>>> for s in streams: print s.resolution, s.extension
... 
1080x1920 webm
1080x1920 mp4
720x1280 webm
720x1280 mp4
480x854 webm
480x854 flv
360x640 webm
360x640 flv
360x640 mp4
240x400 flv
320x240 3gp
144x176 3gp

Se muestra todos los formatos, su resolución y el url para descargarlo:

>>> for s in streams: print s.resolution, s.extension, s.url
... 
1080x1920 webm http://r14---sn-ab5e6nll.c.youtube.com...
1080x1920 mp4 http://r14---sn-ab5e6nll.c.youtube.com...
720x1280 webm http://r14---sn-ab5e6nll.c.youtube.com...
720x1280 mp4 http://r14---sn-ab5e6nll.c.youtube.com...
480x854 webm http://r14---sn-ab5e6nll.c.youtube.com...
480x854 flv http://r14---sn-ab5e6nll.c.youtube.com...
360x640 webm http://r14---sn-ab5e6nll.c.youtube.com...
360x640 flv http://r14---sn-ab5e6nll.c.youtube.com...
360x640 mp4 http://r14---sn-ab5e6nll.c.youtube.com...
240x400 flv http://r14---sn-ab5e6nll.c.youtube.com...
320x240 3gp http://r14---sn-ab5e6nll.c.youtube.com...
144x176 3gp http://r14---sn-ab5e6nll.c.youtube.com...

Obtener la mejor resolución y su extensión:
>>> best = video.getbest()
>>> best.resolution, best.extension
('1080x1920', 'webm')

Mejor resolución para un formato en específico:
>>> best = video.getbest(preftype="mp4")
>>> best.resolution, best.extension
('1080x1920', 'mp4')
Obtener el url para descargar el vídeo:
>>> best.url
'http://r14---sn-ab5e6nll.c.youtube.com/videoplayback...'


Se descarga el vídeo con un nombre y en una ruta predefinida:
>>> myfilename = "/home/ernesto/videos/" + "JimmtFallon" + "." + best.extension
>>> best.download(progress=False, filepath=myfilename)
-Downloading 'Jimmy Fallon, Robin Thicke & The Roots Sing "Blurred Lines" (w/ Classroom Instruments).webm' [157,236,345 Bytes]
Done
Se sale de python:
>>> exit()
Se verifica que el archivo bajo:
ernesto@grievous:~/videos$ ls -l
total 153556
-rw-r--r-- 1 ernesto ernesto 157236345 sep  1 11:03 JimmtFallon.webm

Ahora puede ejecutar su reproductor de vídeo preferido para ver el vídeo.
En la siguiente figura se muestra la captura de pantalla del escritorio al momento de reproducir el vídeo con VLC:


Si desean ver el vídeo a continuación les dejo el enlace de youtube para verlo: