Jose Diaz-Gonzalez
commited on
Commit
·
7e36cb4
1
Parent(s):
f3b34c0
PEP8
Browse files- pytube/__init__.py +1 -0
- pytube/api.py +10 -8
- pytube/models.py +5 -2
- pytube/tinyjs.py +32 -12
- pytube/utils.py +3 -3
pytube/__init__.py
CHANGED
@@ -5,3 +5,4 @@ __license__ = 'MIT License'
|
|
5 |
__copyright__ = 'Copyright 2013 Nick Ficano'
|
6 |
|
7 |
from .api import YouTube
|
|
|
|
5 |
__copyright__ = 'Copyright 2013 Nick Ficano'
|
6 |
|
7 |
from .api import YouTube
|
8 |
+
YouTube
|
pytube/api.py
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
from __future__ import unicode_literals
|
4 |
|
5 |
from .exceptions import MultipleObjectsReturned, YouTubeError, CipherError
|
6 |
-
from .tinyjs import
|
7 |
from .models import Video
|
8 |
from .utils import safe_filename
|
9 |
try:
|
@@ -146,7 +146,7 @@ class YouTube(object):
|
|
146 |
return result[0]
|
147 |
else:
|
148 |
raise MultipleObjectsReturned(
|
149 |
-
|
150 |
|
151 |
def filter(self, extension=None, resolution=None):
|
152 |
"""Return a filtered list of videos given an extention and resolution
|
@@ -257,7 +257,7 @@ class YouTube(object):
|
|
257 |
is_vevo = True
|
258 |
|
259 |
stream_map = self._parse_stream_map(
|
260 |
-
|
261 |
|
262 |
self.title = data["args"]["title"]
|
263 |
js_url = "http:" + data["assets"]["js"]
|
@@ -275,16 +275,17 @@ class YouTube(object):
|
|
275 |
has_decrypted_signature = False
|
276 |
try:
|
277 |
signature = self._decrypt_signature(
|
278 |
-
|
279 |
url += '&signature=' + signature
|
280 |
has_decrypted_signature = True
|
281 |
except TypeError, e:
|
282 |
pass
|
283 |
|
284 |
if not has_decrypted_signature:
|
285 |
-
raise CipherError(
|
286 |
-
|
287 |
-
|
|
|
288 |
|
289 |
else:
|
290 |
signature = self._cipher(stream_map["s"][i], js_url)
|
@@ -315,7 +316,8 @@ class YouTube(object):
|
|
315 |
return "".join(a)
|
316 |
|
317 |
def _cipher(self, s, url):
|
318 |
-
"""Get the signature using the cipher
|
|
|
319 |
|
320 |
:params s: Signature
|
321 |
:params url: url of JavaScript file
|
|
|
3 |
from __future__ import unicode_literals
|
4 |
|
5 |
from .exceptions import MultipleObjectsReturned, YouTubeError, CipherError
|
6 |
+
from .tinyjs import JSVM
|
7 |
from .models import Video
|
8 |
from .utils import safe_filename
|
9 |
try:
|
|
|
146 |
return result[0]
|
147 |
else:
|
148 |
raise MultipleObjectsReturned(
|
149 |
+
"get() returned more than one object")
|
150 |
|
151 |
def filter(self, extension=None, resolution=None):
|
152 |
"""Return a filtered list of videos given an extention and resolution
|
|
|
257 |
is_vevo = True
|
258 |
|
259 |
stream_map = self._parse_stream_map(
|
260 |
+
data["args"]["url_encoded_fmt_stream_map"])
|
261 |
|
262 |
self.title = data["args"]["title"]
|
263 |
js_url = "http:" + data["assets"]["js"]
|
|
|
275 |
has_decrypted_signature = False
|
276 |
try:
|
277 |
signature = self._decrypt_signature(
|
278 |
+
stream_map['s'][0])
|
279 |
url += '&signature=' + signature
|
280 |
has_decrypted_signature = True
|
281 |
except TypeError, e:
|
282 |
pass
|
283 |
|
284 |
if not has_decrypted_signature:
|
285 |
+
raise CipherError(
|
286 |
+
"Couldn't cipher the signature. "
|
287 |
+
"Maybe YouTube has changed the cipher "
|
288 |
+
"algorithm. Notify this issue on GitHub")
|
289 |
|
290 |
else:
|
291 |
signature = self._cipher(stream_map["s"][i], js_url)
|
|
|
316 |
return "".join(a)
|
317 |
|
318 |
def _cipher(self, s, url):
|
319 |
+
"""Get the signature using the cipher
|
320 |
+
implemented in the JavaScript code
|
321 |
|
322 |
:params s: Signature
|
323 |
:params url: url of JavaScript file
|
pytube/models.py
CHANGED
@@ -104,8 +104,11 @@ class Video(object):
|
|
104 |
|
105 |
def __repr__(self):
|
106 |
"""A cleaner representation of the class instance."""
|
107 |
-
return "<Video: {0} (.{1}) - {2} - {3}>".format(
|
108 |
-
|
|
|
|
|
|
|
109 |
|
110 |
def __lt__(self, other):
|
111 |
if type(other) == Video:
|
|
|
104 |
|
105 |
def __repr__(self):
|
106 |
"""A cleaner representation of the class instance."""
|
107 |
+
return "<Video: {0} (.{1}) - {2} - {3}>".format(
|
108 |
+
self.video_codec,
|
109 |
+
self.extension,
|
110 |
+
self.resolution,
|
111 |
+
self.profile)
|
112 |
|
113 |
def __lt__(self, other):
|
114 |
if type(other) == Video:
|
pytube/tinyjs.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import re
|
2 |
|
|
|
3 |
class JSVM(object):
|
4 |
|
5 |
_memory = {}
|
@@ -9,13 +10,31 @@ class JSVM(object):
|
|
9 |
def __init__(self, code=""):
|
10 |
# TODO: parse automatically the 'swap' method
|
11 |
# function Bn(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c;return a};
|
12 |
-
def _swap(args):
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
self._js_methods = {
|
21 |
"split": _split,
|
@@ -38,17 +57,17 @@ class JSVM(object):
|
|
38 |
#print instruction
|
39 |
var, method = instruction.split("=")
|
40 |
m = regex.match(method)
|
41 |
-
if m
|
42 |
arguments = [method[1:-1]]
|
43 |
method = "$assign"
|
44 |
else:
|
45 |
m = m.groups()
|
46 |
#print m
|
47 |
arguments = []
|
48 |
-
pre_args = [m[0][:-1]] if m[0]
|
49 |
pre_args += m[2].split(",")
|
50 |
for a in pre_args:
|
51 |
-
if a
|
52 |
continue
|
53 |
# Replace variables with his value
|
54 |
arguments += [JSMethod(self._js_methods["$get"], a) if not a[0] == '"' and not a[0] == '' and not a.isdigit() else a]
|
@@ -68,6 +87,7 @@ class JSVM(object):
|
|
68 |
self._memory[ins[0]] = ins[1].run()
|
69 |
return self._memory
|
70 |
|
|
|
71 |
class JSMethod(object):
|
72 |
|
73 |
def __init__(self, method, args):
|
@@ -75,8 +95,8 @@ class JSMethod(object):
|
|
75 |
self._a = args
|
76 |
|
77 |
def run(self):
|
78 |
-
args = [
|
79 |
return self._m(args)
|
80 |
|
81 |
def __repr__(self):
|
82 |
-
return "%s(%s)" % (self._m.__name__, self._a)
|
|
|
1 |
import re
|
2 |
|
3 |
+
|
4 |
class JSVM(object):
|
5 |
|
6 |
_memory = {}
|
|
|
10 |
def __init__(self, code=""):
|
11 |
# TODO: parse automatically the 'swap' method
|
12 |
# function Bn(a,b){var c=a[0];a[0]=a[b%a.length];a[b]=c;return a};
|
13 |
+
def _swap(args):
|
14 |
+
a = list(args[0])
|
15 |
+
b = int(args[1])
|
16 |
+
c = a[0]
|
17 |
+
a[0] = a[b % len(a)]
|
18 |
+
a[b] = c
|
19 |
+
return "".join(a)
|
20 |
+
|
21 |
+
def _split(args):
|
22 |
+
return ""
|
23 |
+
|
24 |
+
def _slice(args):
|
25 |
+
return args[0][int(args[1]):]
|
26 |
+
|
27 |
+
def _reverse(args):
|
28 |
+
return args[0][::-1]
|
29 |
+
|
30 |
+
def _join(args):
|
31 |
+
return "".join(args[0])
|
32 |
+
|
33 |
+
def _assign(args):
|
34 |
+
return args[0]
|
35 |
+
|
36 |
+
def _get(args):
|
37 |
+
return self._memory[args[0]]
|
38 |
|
39 |
self._js_methods = {
|
40 |
"split": _split,
|
|
|
57 |
#print instruction
|
58 |
var, method = instruction.split("=")
|
59 |
m = regex.match(method)
|
60 |
+
if m is None:
|
61 |
arguments = [method[1:-1]]
|
62 |
method = "$assign"
|
63 |
else:
|
64 |
m = m.groups()
|
65 |
#print m
|
66 |
arguments = []
|
67 |
+
pre_args = [m[0][:-1]] if m[0] is not None else []
|
68 |
pre_args += m[2].split(",")
|
69 |
for a in pre_args:
|
70 |
+
if a is None or a == "":
|
71 |
continue
|
72 |
# Replace variables with his value
|
73 |
arguments += [JSMethod(self._js_methods["$get"], a) if not a[0] == '"' and not a[0] == '' and not a.isdigit() else a]
|
|
|
87 |
self._memory[ins[0]] = ins[1].run()
|
88 |
return self._memory
|
89 |
|
90 |
+
|
91 |
class JSMethod(object):
|
92 |
|
93 |
def __init__(self, method, args):
|
|
|
95 |
self._a = args
|
96 |
|
97 |
def run(self):
|
98 |
+
args = [a.run() if isinstance(a, JSMethod) else a for a in self._a]
|
99 |
return self._m(args)
|
100 |
|
101 |
def __repr__(self):
|
102 |
+
return "%s(%s)" % (self._m.__name__, self._a)
|
pytube/utils.py
CHANGED
@@ -79,7 +79,7 @@ def print_status(progress, file_size, start):
|
|
79 |
|
80 |
percentDone = int(progress) * 100. / file_size
|
81 |
done = int(50 * progress / int(file_size))
|
82 |
-
stdout.write("\r [%s%s][%3.2f%%] %s at %s/s\r " %
|
83 |
-
|
84 |
-
|
85 |
stdout.flush()
|
|
|
79 |
|
80 |
percentDone = int(progress) * 100. / file_size
|
81 |
done = int(50 * progress / int(file_size))
|
82 |
+
stdout.write("\r [%s%s][%3.2f%%] %s at %s/s\r " %
|
83 |
+
('=' * done, ' ' * (50 - done), percentDone, sizeof(file_size),
|
84 |
+
sizeof(progress // (clock() - start))))
|
85 |
stdout.flush()
|