[Spiegel] move into own file
[youtube-dl] / youtube_dl / InfoExtractors.py
1 import base64
2 import datetime
3 import itertools
4 import netrc
5 import os
6 import re
7 import socket
8 import time
9 import email.utils
10 import xml.etree.ElementTree
11 import random
12 import math
13 import operator
14 import hashlib
15 import binascii
16 import urllib
17
18 from .utils import *
19 from .extractor.common import InfoExtractor, SearchInfoExtractor
20
21 from .extractor.ard import ARDIE
22 from .extractor.arte import ArteTvIE
23 from .extractor.bliptv import BlipTVIE, BlipTVUserIE
24 from .extractor.comedycentral import ComedyCentralIE
25 from .extractor.collegehumor import CollegeHumorIE
26 from .extractor.dailymotion import DailymotionIE
27 from .extractor.depositfiles import DepositFilesIE
28 from .extractor.eighttracks import EightTracksIE
29 from .extractor.escapist import EscapistIE
30 from .extractor.facebook import FacebookIE
31 from .extractor.funnyordie import FunnyOrDieIE
32 from .extractor.gametrailers import GametrailersIE
33 from .extractor.generic import GenericIE
34 from .extractor.googleplus import GooglePlusIE
35 from .extractor.googlesearch import GoogleSearchIE
36 from .extractor.infoq import InfoQIE
37 from .extractor.justintv import JustinTVIE
38 from .extractor.keek import KeekIE
39 from .extractor.metacafe import MetacafeIE
40 from .extractor.mixcloud import MixcloudIE
41 from .extractor.mtv import MTVIE
42 from .extractor.myspass import MySpassIE
43 from .extractor.myvideo import MyVideoIE
44 from .extractor.nba import NBAIE
45 from .extractor.statigram import StatigramIE
46 from .extractor.photobucket import PhotobucketIE
47 from .extractor.pornotube import PornotubeIE
48 from .extractor.rbmaradio import RBMARadioIE
49 from .extractor.soundcloud import SoundcloudIE, SoundcloudSetIE
50 from .extractor.spiegel import SpiegelIE
51 from .extractor.stanfordoc import StanfordOpenClassroomIE
52 from .extractor.steam import SteamIE
53 from .extractor.ted import TEDIE
54 from .extractor.ustream import UstreamIE
55 from .extractor.vimeo import VimeoIE
56 from .extractor.worldstarhiphop import WorldStarHipHopIE
57 from .extractor.xnxx import XNXXIE
58 from .extractor.xvideos import XVideosIE
59 from .extractor.yahoo import YahooIE, YahooSearchIE
60 from .extractor.youjizz import YouJizzIE
61 from .extractor.youku import YoukuIE
62 from .extractor.youporn import YouPornIE
63 from .extractor.youtube import YoutubeIE, YoutubePlaylistIE, YoutubeSearchIE, YoutubeUserIE, YoutubeChannelIE
64 from .extractor.zdf import ZDFIE
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 class LiveLeakIE(InfoExtractor):
96
97     _VALID_URL = r'^(?:http?://)?(?:\w+\.)?liveleak\.com/view\?(?:.*?)i=(?P<video_id>[\w_]+)(?:.*)'
98     IE_NAME = u'liveleak'
99
100     def _real_extract(self, url):
101         mobj = re.match(self._VALID_URL, url)
102         if mobj is None:
103             raise ExtractorError(u'Invalid URL: %s' % url)
104
105         video_id = mobj.group('video_id')
106
107         webpage = self._download_webpage(url, video_id)
108
109         video_url = self._search_regex(r'file: "(.*?)",',
110             webpage, u'video URL')
111
112         video_title = self._html_search_regex(r'<meta property="og:title" content="(?P<title>.*?)"',
113             webpage, u'title').replace('LiveLeak.com -', '').strip()
114
115         video_description = self._html_search_regex(r'<meta property="og:description" content="(?P<desc>.*?)"',
116             webpage, u'description', fatal=False)
117
118         video_uploader = self._html_search_regex(r'By:.*?(\w+)</a>',
119             webpage, u'uploader', fatal=False)
120
121         info = {
122             'id':  video_id,
123             'url': video_url,
124             'ext': 'mp4',
125             'title': video_title,
126             'description': video_description,
127             'uploader': video_uploader
128         }
129
130         return [info]
131
132
133
134 class TumblrIE(InfoExtractor):
135     _VALID_URL = r'http://(?P<blog_name>.*?)\.tumblr\.com/((post)|(video))/(?P<id>\d*)/(.*?)'
136
137     def _real_extract(self, url):
138         m_url = re.match(self._VALID_URL, url)
139         video_id = m_url.group('id')
140         blog = m_url.group('blog_name')
141
142         url = 'http://%s.tumblr.com/post/%s/' % (blog, video_id)
143         webpage = self._download_webpage(url, video_id)
144
145         re_video = r'src=\\x22(?P<video_url>http://%s\.tumblr\.com/video_file/%s/(.*?))\\x22 type=\\x22video/(?P<ext>.*?)\\x22' % (blog, video_id)
146         video = re.search(re_video, webpage)
147         if video is None:
148            raise ExtractorError(u'Unable to extract video')
149         video_url = video.group('video_url')
150         ext = video.group('ext')
151
152         video_thumbnail = self._search_regex(r'posters(.*?)\[\\x22(?P<thumb>.*?)\\x22',
153             webpage, u'thumbnail', fatal=False)  # We pick the first poster
154         if video_thumbnail: video_thumbnail = video_thumbnail.replace('\\', '')
155
156         # The only place where you can get a title, it's not complete,
157         # but searching in other places doesn't work for all videos
158         video_title = self._html_search_regex(r'<title>(?P<title>.*?)</title>',
159             webpage, u'title', flags=re.DOTALL)
160
161         return [{'id': video_id,
162                  'url': video_url,
163                  'title': video_title,
164                  'thumbnail': video_thumbnail,
165                  'ext': ext
166                  }]
167
168 class BandcampIE(InfoExtractor):
169     _VALID_URL = r'http://.*?\.bandcamp\.com/track/(?P<title>.*)'
170
171     def _real_extract(self, url):
172         mobj = re.match(self._VALID_URL, url)
173         title = mobj.group('title')
174         webpage = self._download_webpage(url, title)
175         # We get the link to the free download page
176         m_download = re.search(r'freeDownloadPage: "(.*?)"', webpage)
177         if m_download is None:
178             raise ExtractorError(u'No free songs found')
179
180         download_link = m_download.group(1)
181         id = re.search(r'var TralbumData = {(.*?)id: (?P<id>\d*?)$', 
182                        webpage, re.MULTILINE|re.DOTALL).group('id')
183
184         download_webpage = self._download_webpage(download_link, id,
185                                                   'Downloading free downloads page')
186         # We get the dictionary of the track from some javascrip code
187         info = re.search(r'items: (.*?),$',
188                          download_webpage, re.MULTILINE).group(1)
189         info = json.loads(info)[0]
190         # We pick mp3-320 for now, until format selection can be easily implemented.
191         mp3_info = info[u'downloads'][u'mp3-320']
192         # If we try to use this url it says the link has expired
193         initial_url = mp3_info[u'url']
194         re_url = r'(?P<server>http://(.*?)\.bandcamp\.com)/download/track\?enc=mp3-320&fsig=(?P<fsig>.*?)&id=(?P<id>.*?)&ts=(?P<ts>.*)$'
195         m_url = re.match(re_url, initial_url)
196         #We build the url we will use to get the final track url
197         # This url is build in Bandcamp in the script download_bunde_*.js
198         request_url = '%s/statdownload/track?enc=mp3-320&fsig=%s&id=%s&ts=%s&.rand=665028774616&.vrs=1' % (m_url.group('server'), m_url.group('fsig'), id, m_url.group('ts'))
199         final_url_webpage = self._download_webpage(request_url, id, 'Requesting download url')
200         # If we could correctly generate the .rand field the url would be
201         #in the "download_url" key
202         final_url = re.search(r'"retry_url":"(.*?)"', final_url_webpage).group(1)
203
204         track_info = {'id':id,
205                       'title' : info[u'title'],
206                       'ext' :   'mp3',
207                       'url' :   final_url,
208                       'thumbnail' : info[u'thumb_url'],
209                       'uploader' :  info[u'artist']
210                       }
211
212         return [track_info]
213
214 class RedTubeIE(InfoExtractor):
215     """Information Extractor for redtube"""
216     _VALID_URL = r'(?:http://)?(?:www\.)?redtube\.com/(?P<id>[0-9]+)'
217
218     def _real_extract(self,url):
219         mobj = re.match(self._VALID_URL, url)
220         if mobj is None:
221             raise ExtractorError(u'Invalid URL: %s' % url)
222
223         video_id = mobj.group('id')
224         video_extension = 'mp4'        
225         webpage = self._download_webpage(url, video_id)
226
227         self.report_extraction(video_id)
228
229         video_url = self._html_search_regex(r'<source src="(.+?)" type="video/mp4">',
230             webpage, u'video URL')
231
232         video_title = self._html_search_regex('<h1 class="videoTitle slidePanelMovable">(.+?)</h1>',
233             webpage, u'title')
234
235         return [{
236             'id':       video_id,
237             'url':      video_url,
238             'ext':      video_extension,
239             'title':    video_title,
240         }]
241         
242 class InaIE(InfoExtractor):
243     """Information Extractor for Ina.fr"""
244     _VALID_URL = r'(?:http://)?(?:www\.)?ina\.fr/video/(?P<id>I[0-9]+)/.*'
245
246     def _real_extract(self,url):
247         mobj = re.match(self._VALID_URL, url)
248
249         video_id = mobj.group('id')
250         mrss_url='http://player.ina.fr/notices/%s.mrss' % video_id
251         video_extension = 'mp4'
252         webpage = self._download_webpage(mrss_url, video_id)
253
254         self.report_extraction(video_id)
255
256         video_url = self._html_search_regex(r'<media:player url="(?P<mp4url>http://mp4.ina.fr/[^"]+\.mp4)',
257             webpage, u'video URL')
258
259         video_title = self._search_regex(r'<title><!\[CDATA\[(?P<titre>.*?)]]></title>',
260             webpage, u'title')
261
262         return [{
263             'id':       video_id,
264             'url':      video_url,
265             'ext':      video_extension,
266             'title':    video_title,
267         }]
268
269 class HowcastIE(InfoExtractor):
270     """Information Extractor for Howcast.com"""
271     _VALID_URL = r'(?:https?://)?(?:www\.)?howcast\.com/videos/(?P<id>\d+)'
272
273     def _real_extract(self, url):
274         mobj = re.match(self._VALID_URL, url)
275
276         video_id = mobj.group('id')
277         webpage_url = 'http://www.howcast.com/videos/' + video_id
278         webpage = self._download_webpage(webpage_url, video_id)
279
280         self.report_extraction(video_id)
281
282         video_url = self._search_regex(r'\'?file\'?: "(http://mobile-media\.howcast\.com/[0-9]+\.mp4)',
283             webpage, u'video URL')
284
285         video_title = self._html_search_regex(r'<meta content=(?:"([^"]+)"|\'([^\']+)\') property=\'og:title\'',
286             webpage, u'title')
287
288         video_description = self._html_search_regex(r'<meta content=(?:"([^"]+)"|\'([^\']+)\') name=\'description\'',
289             webpage, u'description', fatal=False)
290
291         thumbnail = self._html_search_regex(r'<meta content=\'(.+?)\' property=\'og:image\'',
292             webpage, u'thumbnail', fatal=False)
293
294         return [{
295             'id':       video_id,
296             'url':      video_url,
297             'ext':      'mp4',
298             'title':    video_title,
299             'description': video_description,
300             'thumbnail': thumbnail,
301         }]
302
303 class VineIE(InfoExtractor):
304     """Information Extractor for Vine.co"""
305     _VALID_URL = r'(?:https?://)?(?:www\.)?vine\.co/v/(?P<id>\w+)'
306
307     def _real_extract(self, url):
308         mobj = re.match(self._VALID_URL, url)
309
310         video_id = mobj.group('id')
311         webpage_url = 'https://vine.co/v/' + video_id
312         webpage = self._download_webpage(webpage_url, video_id)
313
314         self.report_extraction(video_id)
315
316         video_url = self._html_search_regex(r'<meta property="twitter:player:stream" content="(.+?)"',
317             webpage, u'video URL')
318
319         video_title = self._html_search_regex(r'<meta property="og:title" content="(.+?)"',
320             webpage, u'title')
321
322         thumbnail = self._html_search_regex(r'<meta property="og:image" content="(.+?)(\?.*?)?"',
323             webpage, u'thumbnail', fatal=False)
324
325         uploader = self._html_search_regex(r'<div class="user">.*?<h2>(.+?)</h2>',
326             webpage, u'uploader', fatal=False, flags=re.DOTALL)
327
328         return [{
329             'id':        video_id,
330             'url':       video_url,
331             'ext':       'mp4',
332             'title':     video_title,
333             'thumbnail': thumbnail,
334             'uploader':  uploader,
335         }]
336
337 class FlickrIE(InfoExtractor):
338     """Information Extractor for Flickr videos"""
339     _VALID_URL = r'(?:https?://)?(?:www\.)?flickr\.com/photos/(?P<uploader_id>[\w\-_@]+)/(?P<id>\d+).*'
340
341     def _real_extract(self, url):
342         mobj = re.match(self._VALID_URL, url)
343
344         video_id = mobj.group('id')
345         video_uploader_id = mobj.group('uploader_id')
346         webpage_url = 'http://www.flickr.com/photos/' + video_uploader_id + '/' + video_id
347         webpage = self._download_webpage(webpage_url, video_id)
348
349         secret = self._search_regex(r"photo_secret: '(\w+)'", webpage, u'secret')
350
351         first_url = 'https://secure.flickr.com/apps/video/video_mtl_xml.gne?v=x&photo_id=' + video_id + '&secret=' + secret + '&bitrate=700&target=_self'
352         first_xml = self._download_webpage(first_url, video_id, 'Downloading first data webpage')
353
354         node_id = self._html_search_regex(r'<Item id="id">(\d+-\d+)</Item>',
355             first_xml, u'node_id')
356
357         second_url = 'https://secure.flickr.com/video_playlist.gne?node_id=' + node_id + '&tech=flash&mode=playlist&bitrate=700&secret=' + secret + '&rd=video.yahoo.com&noad=1'
358         second_xml = self._download_webpage(second_url, video_id, 'Downloading second data webpage')
359
360         self.report_extraction(video_id)
361
362         mobj = re.search(r'<STREAM APP="(.+?)" FULLPATH="(.+?)"', second_xml)
363         if mobj is None:
364             raise ExtractorError(u'Unable to extract video url')
365         video_url = mobj.group(1) + unescapeHTML(mobj.group(2))
366
367         video_title = self._html_search_regex(r'<meta property="og:title" content=(?:"([^"]+)"|\'([^\']+)\')',
368             webpage, u'video title')
369
370         video_description = self._html_search_regex(r'<meta property="og:description" content=(?:"([^"]+)"|\'([^\']+)\')',
371             webpage, u'description', fatal=False)
372
373         thumbnail = self._html_search_regex(r'<meta property="og:image" content=(?:"([^"]+)"|\'([^\']+)\')',
374             webpage, u'thumbnail', fatal=False)
375
376         return [{
377             'id':          video_id,
378             'url':         video_url,
379             'ext':         'mp4',
380             'title':       video_title,
381             'description': video_description,
382             'thumbnail':   thumbnail,
383             'uploader_id': video_uploader_id,
384         }]
385
386 class TeamcocoIE(InfoExtractor):
387     _VALID_URL = r'http://teamcoco\.com/video/(?P<url_title>.*)'
388
389     def _real_extract(self, url):
390         mobj = re.match(self._VALID_URL, url)
391         if mobj is None:
392             raise ExtractorError(u'Invalid URL: %s' % url)
393         url_title = mobj.group('url_title')
394         webpage = self._download_webpage(url, url_title)
395
396         video_id = self._html_search_regex(r'<article class="video" data-id="(\d+?)"',
397             webpage, u'video id')
398
399         self.report_extraction(video_id)
400
401         video_title = self._html_search_regex(r'<meta property="og:title" content="(.+?)"',
402             webpage, u'title')
403
404         thumbnail = self._html_search_regex(r'<meta property="og:image" content="(.+?)"',
405             webpage, u'thumbnail', fatal=False)
406
407         video_description = self._html_search_regex(r'<meta property="og:description" content="(.*?)"',
408             webpage, u'description', fatal=False)
409
410         data_url = 'http://teamcoco.com/cvp/2.0/%s.xml' % video_id
411         data = self._download_webpage(data_url, video_id, 'Downloading data webpage')
412
413         video_url = self._html_search_regex(r'<file type="high".*?>(.*?)</file>',
414             data, u'video URL')
415
416         return [{
417             'id':          video_id,
418             'url':         video_url,
419             'ext':         'mp4',
420             'title':       video_title,
421             'thumbnail':   thumbnail,
422             'description': video_description,
423         }]
424
425 class XHamsterIE(InfoExtractor):
426     """Information Extractor for xHamster"""
427     _VALID_URL = r'(?:http://)?(?:www.)?xhamster\.com/movies/(?P<id>[0-9]+)/.*\.html'
428
429     def _real_extract(self,url):
430         mobj = re.match(self._VALID_URL, url)
431
432         video_id = mobj.group('id')
433         mrss_url = 'http://xhamster.com/movies/%s/.html' % video_id
434         webpage = self._download_webpage(mrss_url, video_id)
435
436         mobj = re.search(r'\'srv\': \'(?P<server>[^\']*)\',\s*\'file\': \'(?P<file>[^\']+)\',', webpage)
437         if mobj is None:
438             raise ExtractorError(u'Unable to extract media URL')
439         if len(mobj.group('server')) == 0:
440             video_url = compat_urllib_parse.unquote(mobj.group('file'))
441         else:
442             video_url = mobj.group('server')+'/key='+mobj.group('file')
443         video_extension = video_url.split('.')[-1]
444
445         video_title = self._html_search_regex(r'<title>(?P<title>.+?) - xHamster\.com</title>',
446             webpage, u'title')
447
448         # Can't see the description anywhere in the UI
449         # video_description = self._html_search_regex(r'<span>Description: </span>(?P<description>[^<]+)',
450         #     webpage, u'description', fatal=False)
451         # if video_description: video_description = unescapeHTML(video_description)
452
453         mobj = re.search(r'hint=\'(?P<upload_date_Y>[0-9]{4})-(?P<upload_date_m>[0-9]{2})-(?P<upload_date_d>[0-9]{2}) [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]{3,4}\'', webpage)
454         if mobj:
455             video_upload_date = mobj.group('upload_date_Y')+mobj.group('upload_date_m')+mobj.group('upload_date_d')
456         else:
457             video_upload_date = None
458             self._downloader.report_warning(u'Unable to extract upload date')
459
460         video_uploader_id = self._html_search_regex(r'<a href=\'/user/[^>]+>(?P<uploader_id>[^<]+)',
461             webpage, u'uploader id', default=u'anonymous')
462
463         video_thumbnail = self._search_regex(r'\'image\':\'(?P<thumbnail>[^\']+)\'',
464             webpage, u'thumbnail', fatal=False)
465
466         return [{
467             'id':       video_id,
468             'url':      video_url,
469             'ext':      video_extension,
470             'title':    video_title,
471             # 'description': video_description,
472             'upload_date': video_upload_date,
473             'uploader_id': video_uploader_id,
474             'thumbnail': video_thumbnail
475         }]
476
477 class HypemIE(InfoExtractor):
478     """Information Extractor for hypem"""
479     _VALID_URL = r'(?:http://)?(?:www\.)?hypem\.com/track/([^/]+)/([^/]+)'
480
481     def _real_extract(self, url):
482         mobj = re.match(self._VALID_URL, url)
483         if mobj is None:
484             raise ExtractorError(u'Invalid URL: %s' % url)
485         track_id = mobj.group(1)
486
487         data = { 'ax': 1, 'ts': time.time() }
488         data_encoded = compat_urllib_parse.urlencode(data)
489         complete_url = url + "?" + data_encoded
490         request = compat_urllib_request.Request(complete_url)
491         response, urlh = self._download_webpage_handle(request, track_id, u'Downloading webpage with the url')
492         cookie = urlh.headers.get('Set-Cookie', '')
493
494         self.report_extraction(track_id)
495
496         html_tracks = self._html_search_regex(r'<script type="application/json" id="displayList-data">(.*?)</script>',
497             response, u'tracks', flags=re.MULTILINE|re.DOTALL).strip()
498         try:
499             track_list = json.loads(html_tracks)
500             track = track_list[u'tracks'][0]
501         except ValueError:
502             raise ExtractorError(u'Hypemachine contained invalid JSON.')
503
504         key = track[u"key"]
505         track_id = track[u"id"]
506         artist = track[u"artist"]
507         title = track[u"song"]
508
509         serve_url = "http://hypem.com/serve/source/%s/%s" % (compat_str(track_id), compat_str(key))
510         request = compat_urllib_request.Request(serve_url, "" , {'Content-Type': 'application/json'})
511         request.add_header('cookie', cookie)
512         song_data_json = self._download_webpage(request, track_id, u'Downloading metadata')
513         try:
514             song_data = json.loads(song_data_json)
515         except ValueError:
516             raise ExtractorError(u'Hypemachine contained invalid JSON.')
517         final_url = song_data[u"url"]
518
519         return [{
520             'id':       track_id,
521             'url':      final_url,
522             'ext':      "mp3",
523             'title':    title,
524             'artist':   artist,
525         }]
526
527 class Vbox7IE(InfoExtractor):
528     """Information Extractor for Vbox7"""
529     _VALID_URL = r'(?:http://)?(?:www\.)?vbox7\.com/play:([^/]+)'
530
531     def _real_extract(self,url):
532         mobj = re.match(self._VALID_URL, url)
533         if mobj is None:
534             raise ExtractorError(u'Invalid URL: %s' % url)
535         video_id = mobj.group(1)
536
537         redirect_page, urlh = self._download_webpage_handle(url, video_id)
538         new_location = self._search_regex(r'window\.location = \'(.*)\';', redirect_page, u'redirect location')
539         redirect_url = urlh.geturl() + new_location
540         webpage = self._download_webpage(redirect_url, video_id, u'Downloading redirect page')
541
542         title = self._html_search_regex(r'<title>(.*)</title>',
543             webpage, u'title').split('/')[0].strip()
544
545         ext = "flv"
546         info_url = "http://vbox7.com/play/magare.do"
547         data = compat_urllib_parse.urlencode({'as3':'1','vid':video_id})
548         info_request = compat_urllib_request.Request(info_url, data)
549         info_request.add_header('Content-Type', 'application/x-www-form-urlencoded')
550         info_response = self._download_webpage(info_request, video_id, u'Downloading info webpage')
551         if info_response is None:
552             raise ExtractorError(u'Unable to extract the media url')
553         (final_url, thumbnail_url) = map(lambda x: x.split('=')[1], info_response.split('&'))
554
555         return [{
556             'id':        video_id,
557             'url':       final_url,
558             'ext':       ext,
559             'title':     title,
560             'thumbnail': thumbnail_url,
561         }]
562
563
564 def gen_extractors():
565     """ Return a list of an instance of every supported extractor.
566     The order does matter; the first extractor matched is the one handling the URL.
567     """
568     return [
569         YoutubePlaylistIE(),
570         YoutubeChannelIE(),
571         YoutubeUserIE(),
572         YoutubeSearchIE(),
573         YoutubeIE(),
574         MetacafeIE(),
575         DailymotionIE(),
576         GoogleSearchIE(),
577         PhotobucketIE(),
578         YahooIE(),
579         YahooSearchIE(),
580         DepositFilesIE(),
581         FacebookIE(),
582         BlipTVIE(),
583         BlipTVUserIE(),
584         VimeoIE(),
585         MyVideoIE(),
586         ComedyCentralIE(),
587         EscapistIE(),
588         CollegeHumorIE(),
589         XVideosIE(),
590         SoundcloudSetIE(),
591         SoundcloudIE(),
592         InfoQIE(),
593         MixcloudIE(),
594         StanfordOpenClassroomIE(),
595         MTVIE(),
596         YoukuIE(),
597         XNXXIE(),
598         YouJizzIE(),
599         PornotubeIE(),
600         YouPornIE(),
601         GooglePlusIE(),
602         ArteTvIE(),
603         NBAIE(),
604         WorldStarHipHopIE(),
605         JustinTVIE(),
606         FunnyOrDieIE(),
607         SteamIE(),
608         UstreamIE(),
609         RBMARadioIE(),
610         EightTracksIE(),
611         KeekIE(),
612         TEDIE(),
613         MySpassIE(),
614         SpiegelIE(),
615         LiveLeakIE(),
616         ARDIE(),
617         ZDFIE(),
618         TumblrIE(),
619         BandcampIE(),
620         RedTubeIE(),
621         InaIE(),
622         HowcastIE(),
623         VineIE(),
624         FlickrIE(),
625         TeamcocoIE(),
626         XHamsterIE(),
627         HypemIE(),
628         Vbox7IE(),
629         GametrailersIE(),
630         StatigramIE(),
631         GenericIE()
632     ]
633
634 def get_info_extractor(ie_name):
635     """Returns the info extractor class with the given ie_name"""
636     return globals()[ie_name+'IE']