Merge pull request #26 from hbmartin/playlist-from-id
Browse files- pytube/contrib/playlist.py +18 -2
- tests/contrib/test_playlist.py +16 -4
pytube/contrib/playlist.py
CHANGED
@@ -8,7 +8,7 @@ from collections import OrderedDict
|
|
8 |
from typing import List, Optional, Iterable, Dict
|
9 |
from urllib.parse import parse_qs
|
10 |
|
11 |
-
from pytube import request, YouTube
|
12 |
from pytube.helpers import cache, deprecated
|
13 |
from pytube.mixins import install_proxy
|
14 |
|
@@ -50,7 +50,6 @@ class Playlist:
|
|
50 |
def parse_links(self) -> List[str]:
|
51 |
"""Parse the video links from the page source, extracts and
|
52 |
returns the /watch?v= part from video link href
|
53 |
-
It's an alternative for BeautifulSoup
|
54 |
"""
|
55 |
|
56 |
req = self.html
|
@@ -77,6 +76,23 @@ class Playlist:
|
|
77 |
|
78 |
return link_list
|
79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
80 |
@property # type: ignore
|
81 |
@cache
|
82 |
def video_urls(self) -> List[str]:
|
|
|
8 |
from typing import List, Optional, Iterable, Dict
|
9 |
from urllib.parse import parse_qs
|
10 |
|
11 |
+
from pytube import request, YouTube, extract
|
12 |
from pytube.helpers import cache, deprecated
|
13 |
from pytube.mixins import install_proxy
|
14 |
|
|
|
50 |
def parse_links(self) -> List[str]:
|
51 |
"""Parse the video links from the page source, extracts and
|
52 |
returns the /watch?v= part from video link href
|
|
|
53 |
"""
|
54 |
|
55 |
req = self.html
|
|
|
76 |
|
77 |
return link_list
|
78 |
|
79 |
+
def trimmed(self, video_id: str) -> List[str]:
|
80 |
+
"""Retrieve a list of YouTube video URLs trimmed at the given video ID
|
81 |
+
i.e. if the playlist has video IDs 1,2,3,4 calling trimmed(3) returns [1,2]
|
82 |
+
:type video_id: str
|
83 |
+
video ID to trim the returned list of playlist URLs at
|
84 |
+
:rtype: List[str]
|
85 |
+
:returns:
|
86 |
+
List of video URLs from the playlist trimmed at the given ID
|
87 |
+
"""
|
88 |
+
trimmed_urls = []
|
89 |
+
for url in self.video_urls:
|
90 |
+
if extract.video_id(url) == video_id:
|
91 |
+
break
|
92 |
+
else:
|
93 |
+
trimmed_urls.append(url)
|
94 |
+
return trimmed_urls
|
95 |
+
|
96 |
@property # type: ignore
|
97 |
@cache
|
98 |
def video_urls(self) -> List[str]:
|
tests/contrib/test_playlist.py
CHANGED
@@ -11,7 +11,7 @@ def test_title(request_get):
|
|
11 |
"<title>(149) Python Tutorial for Beginners "
|
12 |
"(For Absolute Beginners) - YouTube</title>"
|
13 |
)
|
14 |
-
url = "https://www.fakeurl.com/playlist?list=
|
15 |
pl = Playlist(url)
|
16 |
pl_title = pl.title()
|
17 |
assert pl_title == "(149) Python Tutorial for Beginners (For Absolute Beginners)"
|
@@ -20,7 +20,7 @@ def test_title(request_get):
|
|
20 |
@mock.patch("pytube.contrib.playlist.request.get")
|
21 |
def test_init_with_playlist_url(request_get):
|
22 |
request_get.return_value = ""
|
23 |
-
url = "https://www.youtube.com/playlist?list=
|
24 |
playlist = Playlist(url)
|
25 |
assert playlist.playlist_url == url
|
26 |
|
@@ -30,12 +30,12 @@ def test_init_with_watch_url(request_get):
|
|
30 |
request_get.return_value = ""
|
31 |
url = (
|
32 |
"https://www.youtube.com/watch?v=1KeYzjILqDo&"
|
33 |
-
"list=
|
34 |
)
|
35 |
playlist = Playlist(url)
|
36 |
assert (
|
37 |
playlist.playlist_url
|
38 |
-
== "https://www.youtube.com/playlist?list=
|
39 |
)
|
40 |
|
41 |
|
@@ -104,3 +104,15 @@ def test_proxy(install_proxy, request_get):
|
|
104 |
request_get.return_value = ""
|
105 |
Playlist(url, proxies={"http": "things"})
|
106 |
install_proxy.assert_called_with({"http": "things"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
"<title>(149) Python Tutorial for Beginners "
|
12 |
"(For Absolute Beginners) - YouTube</title>"
|
13 |
)
|
14 |
+
url = "https://www.fakeurl.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n"
|
15 |
pl = Playlist(url)
|
16 |
pl_title = pl.title()
|
17 |
assert pl_title == "(149) Python Tutorial for Beginners (For Absolute Beginners)"
|
|
|
20 |
@mock.patch("pytube.contrib.playlist.request.get")
|
21 |
def test_init_with_playlist_url(request_get):
|
22 |
request_get.return_value = ""
|
23 |
+
url = "https://www.youtube.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n"
|
24 |
playlist = Playlist(url)
|
25 |
assert playlist.playlist_url == url
|
26 |
|
|
|
30 |
request_get.return_value = ""
|
31 |
url = (
|
32 |
"https://www.youtube.com/watch?v=1KeYzjILqDo&"
|
33 |
+
"list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n&index=2&t=661s"
|
34 |
)
|
35 |
playlist = Playlist(url)
|
36 |
assert (
|
37 |
playlist.playlist_url
|
38 |
+
== "https://www.youtube.com/playlist?list=PLS1QulWo1RIaJECMeUT4LFwJ-ghgoSH6n"
|
39 |
)
|
40 |
|
41 |
|
|
|
104 |
request_get.return_value = ""
|
105 |
Playlist(url, proxies={"http": "things"})
|
106 |
install_proxy.assert_called_with({"http": "things"})
|
107 |
+
|
108 |
+
|
109 |
+
@mock.patch("pytube.contrib.playlist.request.get")
|
110 |
+
def test_trimmed(request_get, playlist_html):
|
111 |
+
url = "https://www.fakeurl.com/playlist?list=whatever"
|
112 |
+
request_get.return_value = playlist_html
|
113 |
+
playlist = Playlist(url)
|
114 |
+
playlist._find_load_more_url = MagicMock(return_value=None)
|
115 |
+
assert playlist.trimmed("1BYu65vLKdA") == [
|
116 |
+
"https://www.youtube.com/watch?v=ujTCoH21GlA",
|
117 |
+
"https://www.youtube.com/watch?v=45ryDIPHdGg",
|
118 |
+
]
|