Taylor Fox Dahlin
commited on
Selection of bugfixes and improvements (#1090)
Browse files* Change Search client to WEB.
* Add documentation for oauth functionality.
* Return raw 'last_updated' string where it is not parseable.
- docs/user/quickstart.rst +10 -1
- pytube/__main__.py +8 -1
- pytube/contrib/playlist.py +16 -8
- pytube/contrib/search.py +1 -1
docs/user/quickstart.rst
CHANGED
@@ -41,7 +41,9 @@ when you create a YouTube object::
|
|
41 |
'http://youtube.com/watch?v=2lAe1cqCOXo',
|
42 |
on_progress_callback=progress_func,
|
43 |
on_complete_callback=complete_func,
|
44 |
-
proxies=my_proxies
|
|
|
|
|
45 |
)
|
46 |
|
47 |
When instantiating a YouTube object, these named arguments can be passed in to
|
@@ -57,5 +59,12 @@ downloaded, and is called with two arguments: the stream and the file path.
|
|
57 |
This could be used, for example, to perform post-download processing on a video
|
58 |
like trimming the length of it.
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
Once you have a YouTube object set up, you're ready to start looking at
|
61 |
different media streams for the video, which is discussed in the next section.
|
|
|
41 |
'http://youtube.com/watch?v=2lAe1cqCOXo',
|
42 |
on_progress_callback=progress_func,
|
43 |
on_complete_callback=complete_func,
|
44 |
+
proxies=my_proxies,
|
45 |
+
use_oauth=False,
|
46 |
+
allow_oauth_cache=True
|
47 |
)
|
48 |
|
49 |
When instantiating a YouTube object, these named arguments can be passed in to
|
|
|
59 |
This could be used, for example, to perform post-download processing on a video
|
60 |
like trimming the length of it.
|
61 |
|
62 |
+
The use_oauth and allow_oauth_cache flags allow you to authorize pytube to
|
63 |
+
interact with YouTube using your account, and can be used to bypass age
|
64 |
+
restrictions or access private videos and playlists. If allow_oauth_cache is
|
65 |
+
set to True, you should only be prompted to do so once, after which point
|
66 |
+
pytube will cache the tokens it needs to act on your behalf. Otherwise, you
|
67 |
+
will be prompted again for each action that requires you to be authenticated.
|
68 |
+
|
69 |
Once you have a YouTube object set up, you're ready to start looking at
|
70 |
different media streams for the video, which is discussed in the next section.
|
pytube/__main__.py
CHANGED
@@ -43,7 +43,14 @@ class YouTube:
|
|
43 |
:param func on_complete_callback:
|
44 |
(Optional) User defined callback function for stream download
|
45 |
complete events.
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
47 |
"""
|
48 |
self._js: Optional[str] = None # js fetched by js_url
|
49 |
self._js_url: Optional[str] = None # the url to the js, parsed from watch html
|
|
|
43 |
:param func on_complete_callback:
|
44 |
(Optional) User defined callback function for stream download
|
45 |
complete events.
|
46 |
+
:param dict proxies:
|
47 |
+
(Optional) A dict mapping protocol to proxy address which will be used by pytube.
|
48 |
+
:param bool use_oauth:
|
49 |
+
(Optional) Prompt the user to authenticate to YouTube.
|
50 |
+
If allow_oauth_cache is set to True, the user should only be prompted once.
|
51 |
+
:param bool allow_oauth_cache:
|
52 |
+
(Optional) Cache OAuth tokens locally on the machine. Defaults to True.
|
53 |
+
These tokens are only generated if use_oauth is set to True as well.
|
54 |
"""
|
55 |
self._js: Optional[str] = None # js fetched by js_url
|
56 |
self._js_url: Optional[str] = None # the url to the js, parsed from watch html
|
pytube/contrib/playlist.py
CHANGED
@@ -319,18 +319,26 @@ class Playlist(Sequence):
|
|
319 |
def last_updated(self) -> Optional[date]:
|
320 |
"""Extract the date that the playlist was last updated.
|
321 |
|
322 |
-
|
|
|
|
|
|
|
|
|
|
|
323 |
:rtype: datetime.date
|
324 |
"""
|
325 |
last_updated_text = self.sidebar_info[0]['playlistSidebarPrimaryInfoRenderer'][
|
326 |
'stats'][2]['runs'][1]['text']
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
|
|
|
|
|
|
334 |
|
335 |
@property
|
336 |
@cache
|
|
|
319 |
def last_updated(self) -> Optional[date]:
|
320 |
"""Extract the date that the playlist was last updated.
|
321 |
|
322 |
+
For some playlists, this will be a specific date, which is returned as a datetime
|
323 |
+
object. For other playlists, this is an estimate such as "1 week ago". Due to the
|
324 |
+
fact that this value is returned as a string, pytube does a best-effort parsing
|
325 |
+
where possible, and returns the raw string where it is not possible.
|
326 |
+
|
327 |
+
:return: Date of last playlist update where possible, else the string provided
|
328 |
:rtype: datetime.date
|
329 |
"""
|
330 |
last_updated_text = self.sidebar_info[0]['playlistSidebarPrimaryInfoRenderer'][
|
331 |
'stats'][2]['runs'][1]['text']
|
332 |
+
try:
|
333 |
+
date_components = last_updated_text.split()
|
334 |
+
month = date_components[0]
|
335 |
+
day = date_components[1].strip(',')
|
336 |
+
year = date_components[2]
|
337 |
+
return datetime.strptime(
|
338 |
+
f"{month} {day:0>2} {year}", "%b %d %Y"
|
339 |
+
).date()
|
340 |
+
except (IndexError, KeyError):
|
341 |
+
return last_updated_text
|
342 |
|
343 |
@property
|
344 |
@cache
|
pytube/contrib/search.py
CHANGED
@@ -18,7 +18,7 @@ class Search:
|
|
18 |
Search query provided by the user.
|
19 |
"""
|
20 |
self.query = query
|
21 |
-
self._innertube_client = InnerTube()
|
22 |
|
23 |
# The first search, without a continuation, is structured differently
|
24 |
# and contains completion suggestions, so we must store this separately
|
|
|
18 |
Search query provided by the user.
|
19 |
"""
|
20 |
self.query = query
|
21 |
+
self._innertube_client = InnerTube(client='WEB')
|
22 |
|
23 |
# The first search, without a continuation, is structured differently
|
24 |
# and contains completion suggestions, so we must store this separately
|