|
@@ -8,6 +8,7 @@
|
|
import cookielib
|
|
import cookielib
|
|
import ctypes
|
|
import ctypes
|
|
import datetime
|
|
import datetime
|
|
|
|
+import gzip
|
|
import htmlentitydefs
|
|
import htmlentitydefs
|
|
import httplib
|
|
import httplib
|
|
import locale
|
|
import locale
|
|
@@ -18,11 +19,13 @@ import os.path
|
|
import re
|
|
import re
|
|
import socket
|
|
import socket
|
|
import string
|
|
import string
|
|
|
|
+import StringIO
|
|
import subprocess
|
|
import subprocess
|
|
import sys
|
|
import sys
|
|
import time
|
|
import time
|
|
import urllib
|
|
import urllib
|
|
import urllib2
|
|
import urllib2
|
|
|
|
+import zlib
|
|
|
|
|
|
# parse_qs was moved from the cgi module to the urlparse module recently.
|
|
# parse_qs was moved from the cgi module to the urlparse module recently.
|
|
try:
|
|
try:
|
|
@@ -161,6 +164,56 @@ class ContentTooShortError(Exception):
|
|
self.downloaded = downloaded
|
|
self.downloaded = downloaded
|
|
self.expected = expected
|
|
self.expected = expected
|
|
|
|
|
|
|
|
+class YoutubeDLHandler(urllib2.HTTPHandler):
|
|
|
|
+ """Handler for HTTP requests and responses.
|
|
|
|
+
|
|
|
|
+ This class, when installed with an OpenerDirector, automatically adds
|
|
|
|
+ the standard headers to every HTTP request and handles gzipped and
|
|
|
|
+ deflated responses from web servers. If compression is to be avoided in
|
|
|
|
+ a particular request, the original request in the program code only has
|
|
|
|
+ to include the HTTP header "Youtubedl-No-Compression", which will be
|
|
|
|
+ removed before making the real request.
|
|
|
|
+
|
|
|
|
+ Part of this code was copied from:
|
|
|
|
+
|
|
|
|
+ http://techknack.net/python-urllib2-handlers/
|
|
|
|
+
|
|
|
|
+ Andrew Rowls, the author of that code, agreed to release it to the
|
|
|
|
+ public domain.
|
|
|
|
+ """
|
|
|
|
+
|
|
|
|
+ @staticmethod
|
|
|
|
+ def deflate(data):
|
|
|
|
+ try:
|
|
|
|
+ return zlib.decompress(data, -zlib.MAX_WBITS)
|
|
|
|
+ except zlib.error:
|
|
|
|
+ return zlib.decompress(data)
|
|
|
|
+
|
|
|
|
+ def http_request(self, req):
|
|
|
|
+ for h in std_headers:
|
|
|
|
+ if h in req.headers:
|
|
|
|
+ del req.headers[h]
|
|
|
|
+ req.add_header(h, std_headers[h])
|
|
|
|
+ if 'Youtubedl-no-compression' in req.headers:
|
|
|
|
+ if 'Accept-encoding' in req.headers:
|
|
|
|
+ del req.headers['Accept-encoding']
|
|
|
|
+ del req.headers['Youtubedl-no-compression']
|
|
|
|
+ return req
|
|
|
|
+
|
|
|
|
+ def http_response(self, req, resp):
|
|
|
|
+ old_resp = resp
|
|
|
|
+ # gzip
|
|
|
|
+ if resp.headers.get('Content-encoding', '') == 'gzip':
|
|
|
|
+ gz = gzip.GzipFile(fileobj=StringIO.StringIO(resp.read()), mode='r')
|
|
|
|
+ resp = urllib2.addinfourl(gz, old_resp.headers, old_resp.url, old_resp.code)
|
|
|
|
+ resp.msg = old_resp.msg
|
|
|
|
+ # deflate
|
|
|
|
+ if resp.headers.get('Content-encoding', '') == 'deflate':
|
|
|
|
+ gz = StringIO.StringIO(self.deflate(resp.read()))
|
|
|
|
+ resp = urllib2.addinfourl(gz, old_resp.headers, old_resp.url, old_resp.code)
|
|
|
|
+ resp.msg = old_resp.msg
|
|
|
|
+ return resp
|
|
|
|
+
|
|
class FileDownloader(object):
|
|
class FileDownloader(object):
|
|
"""File Downloader class.
|
|
"""File Downloader class.
|
|
|
|
|
|
@@ -559,8 +612,11 @@ class FileDownloader(object):
|
|
tmpfilename = self.temp_name(filename)
|
|
tmpfilename = self.temp_name(filename)
|
|
stream = None
|
|
stream = None
|
|
open_mode = 'wb'
|
|
open_mode = 'wb'
|
|
- basic_request = urllib2.Request(url, None, std_headers)
|
|
|
|
- request = urllib2.Request(url, None, std_headers)
|
|
|
|
|
|
+
|
|
|
|
+ # Do not include the Accept-Encoding header
|
|
|
|
+ headers = {'Youtubedl-no-compression': 'True'}
|
|
|
|
+ basic_request = urllib2.Request(url, None, headers)
|
|
|
|
+ request = urllib2.Request(url, None, headers)
|
|
|
|
|
|
# Establish possible resume length
|
|
# Establish possible resume length
|
|
if os.path.isfile(tmpfilename):
|
|
if os.path.isfile(tmpfilename):
|
|
@@ -822,7 +878,7 @@ class YoutubeIE(InfoExtractor):
|
|
return
|
|
return
|
|
|
|
|
|
# Set language
|
|
# Set language
|
|
- request = urllib2.Request(self._LANG_URL, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._LANG_URL)
|
|
try:
|
|
try:
|
|
self.report_lang()
|
|
self.report_lang()
|
|
urllib2.urlopen(request).read()
|
|
urllib2.urlopen(request).read()
|
|
@@ -842,7 +898,7 @@ class YoutubeIE(InfoExtractor):
|
|
'username': username,
|
|
'username': username,
|
|
'password': password,
|
|
'password': password,
|
|
}
|
|
}
|
|
- request = urllib2.Request(self._LOGIN_URL, urllib.urlencode(login_form), std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._LOGIN_URL, urllib.urlencode(login_form))
|
|
try:
|
|
try:
|
|
self.report_login()
|
|
self.report_login()
|
|
login_results = urllib2.urlopen(request).read()
|
|
login_results = urllib2.urlopen(request).read()
|
|
@@ -858,7 +914,7 @@ class YoutubeIE(InfoExtractor):
|
|
'next_url': '/',
|
|
'next_url': '/',
|
|
'action_confirm': 'Confirm',
|
|
'action_confirm': 'Confirm',
|
|
}
|
|
}
|
|
- request = urllib2.Request(self._AGE_URL, urllib.urlencode(age_form), std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._AGE_URL, urllib.urlencode(age_form))
|
|
try:
|
|
try:
|
|
self.report_age_confirmation()
|
|
self.report_age_confirmation()
|
|
age_results = urllib2.urlopen(request).read()
|
|
age_results = urllib2.urlopen(request).read()
|
|
@@ -876,7 +932,7 @@ class YoutubeIE(InfoExtractor):
|
|
|
|
|
|
# Get video webpage
|
|
# Get video webpage
|
|
self.report_video_webpage_download(video_id)
|
|
self.report_video_webpage_download(video_id)
|
|
- request = urllib2.Request('http://www.youtube.com/watch?v=%s&gl=US&hl=en&has_verified=1' % video_id, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request('http://www.youtube.com/watch?v=%s&gl=US&hl=en&has_verified=1' % video_id)
|
|
try:
|
|
try:
|
|
video_webpage = urllib2.urlopen(request).read()
|
|
video_webpage = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -895,7 +951,7 @@ class YoutubeIE(InfoExtractor):
|
|
for el_type in ['&el=embedded', '&el=detailpage', '&el=vevo', '']:
|
|
for el_type in ['&el=embedded', '&el=detailpage', '&el=vevo', '']:
|
|
video_info_url = ('http://www.youtube.com/get_video_info?&video_id=%s%s&ps=default&eurl=&gl=US&hl=en'
|
|
video_info_url = ('http://www.youtube.com/get_video_info?&video_id=%s%s&ps=default&eurl=&gl=US&hl=en'
|
|
% (video_id, el_type))
|
|
% (video_id, el_type))
|
|
- request = urllib2.Request(video_info_url, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(video_info_url)
|
|
try:
|
|
try:
|
|
video_info_webpage = urllib2.urlopen(request).read()
|
|
video_info_webpage = urllib2.urlopen(request).read()
|
|
video_info = parse_qs(video_info_webpage)
|
|
video_info = parse_qs(video_info_webpage)
|
|
@@ -1055,7 +1111,7 @@ class MetacafeIE(InfoExtractor):
|
|
|
|
|
|
def _real_initialize(self):
|
|
def _real_initialize(self):
|
|
# Retrieve disclaimer
|
|
# Retrieve disclaimer
|
|
- request = urllib2.Request(self._DISCLAIMER, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._DISCLAIMER)
|
|
try:
|
|
try:
|
|
self.report_disclaimer()
|
|
self.report_disclaimer()
|
|
disclaimer = urllib2.urlopen(request).read()
|
|
disclaimer = urllib2.urlopen(request).read()
|
|
@@ -1068,7 +1124,7 @@ class MetacafeIE(InfoExtractor):
|
|
'filters': '0',
|
|
'filters': '0',
|
|
'submit': "Continue - I'm over 18",
|
|
'submit': "Continue - I'm over 18",
|
|
}
|
|
}
|
|
- request = urllib2.Request(self._FILTER_POST, urllib.urlencode(disclaimer_form), std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._FILTER_POST, urllib.urlencode(disclaimer_form))
|
|
try:
|
|
try:
|
|
self.report_age_confirmation()
|
|
self.report_age_confirmation()
|
|
disclaimer = urllib2.urlopen(request).read()
|
|
disclaimer = urllib2.urlopen(request).read()
|
|
@@ -1771,7 +1827,7 @@ class YoutubeSearchIE(InfoExtractor):
|
|
while True:
|
|
while True:
|
|
self.report_download_page(query, pagenum)
|
|
self.report_download_page(query, pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
- request = urllib2.Request(result_url, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(result_url)
|
|
try:
|
|
try:
|
|
page = urllib2.urlopen(request).read()
|
|
page = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -1862,7 +1918,7 @@ class GoogleSearchIE(InfoExtractor):
|
|
while True:
|
|
while True:
|
|
self.report_download_page(query, pagenum)
|
|
self.report_download_page(query, pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
- request = urllib2.Request(result_url, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(result_url)
|
|
try:
|
|
try:
|
|
page = urllib2.urlopen(request).read()
|
|
page = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -1953,7 +2009,7 @@ class YahooSearchIE(InfoExtractor):
|
|
while True:
|
|
while True:
|
|
self.report_download_page(query, pagenum)
|
|
self.report_download_page(query, pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
result_url = self._TEMPLATE_URL % (urllib.quote_plus(query), pagenum)
|
|
- request = urllib2.Request(result_url, None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(result_url)
|
|
try:
|
|
try:
|
|
page = urllib2.urlopen(request).read()
|
|
page = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -2017,7 +2073,7 @@ class YoutubePlaylistIE(InfoExtractor):
|
|
|
|
|
|
while True:
|
|
while True:
|
|
self.report_download_page(playlist_id, pagenum)
|
|
self.report_download_page(playlist_id, pagenum)
|
|
- request = urllib2.Request(self._TEMPLATE_URL % (playlist_id, pagenum), None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._TEMPLATE_URL % (playlist_id, pagenum))
|
|
try:
|
|
try:
|
|
page = urllib2.urlopen(request).read()
|
|
page = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -2079,7 +2135,7 @@ class YoutubeUserIE(InfoExtractor):
|
|
pagenum = 1
|
|
pagenum = 1
|
|
|
|
|
|
self.report_download_page(username)
|
|
self.report_download_page(username)
|
|
- request = urllib2.Request(self._TEMPLATE_URL % (username), None, std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(self._TEMPLATE_URL % (username))
|
|
try:
|
|
try:
|
|
page = urllib2.urlopen(request).read()
|
|
page = urllib2.urlopen(request).read()
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
except (urllib2.URLError, httplib.HTTPException, socket.error), err:
|
|
@@ -2135,7 +2191,7 @@ class DepositFilesIE(InfoExtractor):
|
|
|
|
|
|
# Retrieve file webpage with 'Free download' button pressed
|
|
# Retrieve file webpage with 'Free download' button pressed
|
|
free_download_indication = { 'gateway_result' : '1' }
|
|
free_download_indication = { 'gateway_result' : '1' }
|
|
- request = urllib2.Request(url, urllib.urlencode(free_download_indication), std_headers)
|
|
|
|
|
|
+ request = urllib2.Request(url, urllib.urlencode(free_download_indication))
|
|
try:
|
|
try:
|
|
self.report_download_webpage(file_id)
|
|
self.report_download_webpage(file_id)
|
|
webpage = urllib2.urlopen(request).read()
|
|
webpage = urllib2.urlopen(request).read()
|
|
@@ -2354,8 +2410,7 @@ if __name__ == '__main__':
|
|
|
|
|
|
# General configuration
|
|
# General configuration
|
|
cookie_processor = urllib2.HTTPCookieProcessor(jar)
|
|
cookie_processor = urllib2.HTTPCookieProcessor(jar)
|
|
- urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()))
|
|
|
|
- urllib2.install_opener(urllib2.build_opener(cookie_processor))
|
|
|
|
|
|
+ urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler(), cookie_processor, YoutubeDLHandler()))
|
|
socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
|
|
socket.setdefaulttimeout(300) # 5 minutes should be enough (famous last words)
|
|
|
|
|
|
# Batch file verification
|
|
# Batch file verification
|