Last active
December 14, 2015 23:59
-
-
Save vr2262/5169756 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "youtube_api_demo" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This hosted notebook is current as of March 14. Run it yourself to bring it up to date!" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import gdata.youtube\n", | |
"import gdata.youtube.service\n", | |
"from datetime import timedelta" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"yt_service = gdata.youtube.service.YouTubeService()" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"It seems a feed gives you 25 results at a time no matter what." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_playlists = yt_service.Query('http://gdata.youtube.com/feeds/api/users/GameGrumps/playlists?v=2')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 3 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_playlists.__dict__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 4, | |
"text": [ | |
"{'_GDataFeed__generator': <atom.Generator at 0x1d4b090>,\n", | |
" '_GDataFeed__id': <atom.Id at 0x1cc1d90>,\n", | |
" 'author': [<atom.Author at 0x1d4b050>],\n", | |
" 'category': [<atom.Category at 0x1cdbb90>],\n", | |
" 'contributor': [],\n", | |
" 'entry': [<gdata.GDataEntry at 0x1d4b250>,\n", | |
" <gdata.GDataEntry at 0x1d4b290>,\n", | |
" <gdata.GDataEntry at 0x1d4b850>,\n", | |
" <gdata.GDataEntry at 0x1d4bed0>,\n", | |
" <gdata.GDataEntry at 0x1d4e550>,\n", | |
" <gdata.GDataEntry at 0x1d4eb90>,\n", | |
" <gdata.GDataEntry at 0x1d53210>,\n", | |
" <gdata.GDataEntry at 0x1d53850>,\n", | |
" <gdata.GDataEntry at 0x1d53e90>,\n", | |
" <gdata.GDataEntry at 0x1d56510>,\n", | |
" <gdata.GDataEntry at 0x1d56b50>,\n", | |
" <gdata.GDataEntry at 0x1d591d0>,\n", | |
" <gdata.GDataEntry at 0x1d59810>,\n", | |
" <gdata.GDataEntry at 0x1d59e50>,\n", | |
" <gdata.GDataEntry at 0x1d5c4d0>,\n", | |
" <gdata.GDataEntry at 0x1d5cb10>,\n", | |
" <gdata.GDataEntry at 0x1d60190>,\n", | |
" <gdata.GDataEntry at 0x1d607d0>,\n", | |
" <gdata.GDataEntry at 0x1d60e10>,\n", | |
" <gdata.GDataEntry at 0x1d654d0>,\n", | |
" <gdata.GDataEntry at 0x1d65b50>,\n", | |
" <gdata.GDataEntry at 0x1d681d0>,\n", | |
" <gdata.GDataEntry at 0x1d68810>,\n", | |
" <gdata.GDataEntry at 0x1d68e90>,\n", | |
" <gdata.GDataEntry at 0x1d6d510>],\n", | |
" 'extension_attributes': {},\n", | |
" 'extension_elements': [],\n", | |
" 'icon': None,\n", | |
" 'items_per_page': <gdata.ItemsPerPage at 0x1d4b210>,\n", | |
" 'link': [<atom.Link at 0x1cdbd10>,\n", | |
" <atom.Link at 0x1cdbd90>,\n", | |
" <atom.Link at 0x1cdbe10>,\n", | |
" <atom.Link at 0x1cdbe90>,\n", | |
" <atom.Link at 0x1cdbf10>,\n", | |
" <atom.Link at 0x1cdbf90>],\n", | |
" 'logo': <atom.Logo at 0x1cdbcd0>,\n", | |
" 'rights': None,\n", | |
" 'start_index': <gdata.StartIndex at 0x1d4b1d0>,\n", | |
" 'subtitle': None,\n", | |
" 'text': None,\n", | |
" 'title': <atom.Title at 0x1cdbc50>,\n", | |
" 'total_results': <gdata.TotalResults at 0x1d4b190>,\n", | |
" 'updated': <atom.Updated at 0x1cc1dd0>}" | |
] | |
} | |
], | |
"prompt_number": 4 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_playlists.entry[0].title.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 5, | |
"text": [ | |
"'The Great Circus Mystery Starring Mickey & Minnie'" | |
] | |
} | |
], | |
"prompt_number": 5 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_playlists.entry[0].content.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 6, | |
"text": [ | |
"\"Arin and Jon have a grand ol' time playing The Great Circus Mystery Starring Mickey & Minnie on the SNES!\"" | |
] | |
} | |
], | |
"prompt_number": 6 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"playlist_url = yt_service.GetYouTubePlaylistEntry(grump_playlists.entry[0].link[2].href)\n", | |
"playlist_videos = yt_service.GetYouTubePlaylistVideoFeed(playlist_url.feed_link[0].href)\n", | |
"for entry in playlist_videos.entry:\n", | |
" print entry.title.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"The Great Circus Mystery Starring Mickey & Minnie: Topsy-Turvy - PART 1 - Game Grumps\n", | |
"The Great Circus Mystery Starring Mickey & Minnie: Jungle Jangle - PART 2- Game Grumps\n" | |
] | |
} | |
], | |
"prompt_number": 7 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_playlists.link[5].__dict__\n", | |
"# Note 'rel': 'next'" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 8, | |
"text": [ | |
"{'extension_attributes': {},\n", | |
" 'extension_elements': [],\n", | |
" 'href': 'https://gdata.youtube.com/feeds/api/users/GameGrumps/playlists?start-index=26&max-results=25',\n", | |
" 'hreflang': None,\n", | |
" 'length': None,\n", | |
" 'rel': 'next',\n", | |
" 'text': None,\n", | |
" 'title': None,\n", | |
" 'type': 'application/atom+xml'}" | |
] | |
} | |
], | |
"prompt_number": 8 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"more_playlist = grump_playlists.link[5].href\n", | |
"yt_service.Query(more_playlist).entry[0].content.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 9, | |
"text": [ | |
"\"Arin and Jon play Demon's Souls and probably die a lot.\"" | |
] | |
} | |
], | |
"prompt_number": 9 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Note that you can only get up to 50 video results at a time. Seems `<link rel = 'next' ...>` can help." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads = yt_service.GetYouTubeVideoFeed(\n", | |
" 'http://gdata.youtube.com/feeds/api/users/GameGrumps/uploads?max-results=5&startindex=0&v=2')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 10 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads.__dict__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 11, | |
"text": [ | |
"{'_GDataFeed__generator': <atom.Generator at 0x1cdb110>,\n", | |
" '_GDataFeed__id': <atom.Id at 0x1ccb6d0>,\n", | |
" 'author': [<atom.Author at 0x1cdb0d0>],\n", | |
" 'category': [<atom.Category at 0x1d74990>],\n", | |
" 'contributor': [],\n", | |
" 'entry': [<gdata.youtube.YouTubeVideoEntry at 0x1cdb390>,\n", | |
" <gdata.youtube.YouTubeVideoEntry at 0x1cdb690>,\n", | |
" <gdata.youtube.YouTubeVideoEntry at 0x1d84610>,\n", | |
" <gdata.youtube.YouTubeVideoEntry at 0x1d6e0d0>,\n", | |
" <gdata.youtube.YouTubeVideoEntry at 0x1d6ead0>],\n", | |
" 'extension_attributes': {},\n", | |
" 'extension_elements': [],\n", | |
" 'icon': None,\n", | |
" 'items_per_page': <gdata.ItemsPerPage at 0x1cdb490>,\n", | |
" 'link': [<atom.Link at 0x1d74890>,\n", | |
" <atom.Link at 0x1d747d0>,\n", | |
" <atom.Link at 0x1d74790>,\n", | |
" <atom.Link at 0x1cdb890>,\n", | |
" <atom.Link at 0x1cdba50>,\n", | |
" <atom.Link at 0x1cdb190>],\n", | |
" 'logo': <atom.Logo at 0x1d748d0>,\n", | |
" 'rights': None,\n", | |
" 'start_index': <gdata.StartIndex at 0x1cdb450>,\n", | |
" 'subtitle': None,\n", | |
" 'text': None,\n", | |
" 'title': <atom.Title at 0x1d74910>,\n", | |
" 'total_results': <gdata.TotalResults at 0x1cdb350>,\n", | |
" 'updated': <atom.Updated at 0x1ccb690>}" | |
] | |
} | |
], | |
"prompt_number": 11 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads.entry[0].title.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 12, | |
"text": [ | |
"'The Great Circus Mystery Starring Mickey & Minnie: Ghastly Ghouls - PART 3 - Game Grumps'" | |
] | |
} | |
], | |
"prompt_number": 12 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"print grump_uploads.entry[0].content.text" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Their method of flight continues to distress and confound.\n", | |
"\n", | |
"Game Grumps are:\n", | |
"\n", | |
"Egoraptor: http://www.YouTube.com/Egoraptor\n", | |
"\n", | |
"JonTron: http://www.YouTube.com/Jontronshow\n", | |
"\n", | |
"\n", | |
"Game Grumps on Facebook: https://www.facebook.com/GameGrumps\n", | |
"\n", | |
"Game Grumps on Twitter: https://www.twitter.com/gamegrumps\n", | |
"\n", | |
"Game Grumps Store: http://www.sharkrobot.com/game-grumps\n" | |
] | |
} | |
], | |
"prompt_number": 13 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads.entry[0].media.duration.seconds" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 14, | |
"text": [ | |
"'608'" | |
] | |
} | |
], | |
"prompt_number": 14 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads.entry[0].rating.__dict__" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 15, | |
"text": [ | |
"{'average': '4.8586087',\n", | |
" 'extension_attributes': {'rel': 'http://schemas.google.com/g/2005#overall'},\n", | |
" 'extension_elements': [],\n", | |
" 'max': '5',\n", | |
" 'min': '1',\n", | |
" 'num_raters': '877',\n", | |
" 'text': None}" | |
] | |
} | |
], | |
"prompt_number": 15 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"grump_uploads.entry[0].statistics.view_count" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "pyout", | |
"prompt_number": 16, | |
"text": [ | |
"'303'" | |
] | |
} | |
], | |
"prompt_number": 16 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Let's find out how much time the Grumps have spent playing Sonic 2006." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"# Of course, first we have to find the Sonic 2006 playlist...\n", | |
"possible_sonic_playlist_chunk = grump_playlists\n", | |
"sonic_not_found = True\n", | |
"pages = 0\n", | |
"while sonic_not_found:\n", | |
" pages += 1\n", | |
" for index, entry in enumerate(possible_sonic_playlist_chunk.entry):\n", | |
" if 'sonic' in entry.title.text.lower():\n", | |
" sonic_not_found = False\n", | |
" break\n", | |
" else:\n", | |
" possible_sonic_playlist_chunk = yt_service.Query(possible_sonic_playlist_chunk.link[5].href)\n", | |
"sonic_playlist_url = yt_service.GetYouTubePlaylistEntry(possible_sonic_playlist_chunk.entry[index].link[2].href)\n", | |
"sonic_playlist = yt_service.GetYouTubePlaylistVideoFeed(sonic_playlist_url.feed_link[0].href)\n", | |
"print 'We found the {} playlist after {} pages of playlist results. '\\\n", | |
" 'It is playlist #{} on this page.'.format(entry.title.text, pages, index + 1)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"We found the Sonic '06 playlist after 2 pages of playlist results. It is playlist #3 on this page.\n" | |
] | |
} | |
], | |
"prompt_number": 17 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The Sonic 2006 playlist is also longer than 25 videos so we need to recycle some of our approach." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"total_duration = 0 # Measured in seconds.\n", | |
"number_of_episodes = 0\n", | |
"while sonic_playlist.link[4].rel == 'next':\n", | |
" for entry in sonic_playlist.entry:\n", | |
" number_of_episodes += 1\n", | |
" # Each Game Grumps episode has a 5 second intro\n", | |
" total_duration += float(entry.media.duration.seconds) - 5\n", | |
" sonic_playlist = yt_service.GetYouTubePlaylistVideoFeed(sonic_playlist.link[4].href)\n", | |
"print 'Game time (not taking speedups into account): ' + \\\n", | |
" str(timedelta(seconds=total_duration)) + ' (hours:minutes:seconds)'" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"Game time (not taking speedups into account): 4:37:15 (hours:minutes:seconds)\n" | |
] | |
} | |
], | |
"prompt_number": 18 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 18 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment