maitreyee19
commited on
Fix for -PyTube can't download or iterete over playlist it it contains a "subMenuItems" #915 (#918)
Browse files- pytube/contrib/playlist.py +14 -15
- tests/conftest.py +13 -0
- tests/contrib/test_playlist.py +17 -0
- tests/mocks/playlist_submenu.html.gz +0 -0
pytube/contrib/playlist.py
CHANGED
@@ -131,21 +131,20 @@ class Playlist(Sequence):
|
|
131 |
try:
|
132 |
# this is the json tree structure, if the json was extracted from
|
133 |
# html
|
134 |
-
|
135 |
-
"twoColumnBrowseResultsRenderer"
|
136 |
-
|
137 |
-
"contents"
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
]
|
149 |
videos = important_content["contents"]
|
150 |
except (KeyError, IndexError, TypeError):
|
151 |
try:
|
|
|
131 |
try:
|
132 |
# this is the json tree structure, if the json was extracted from
|
133 |
# html
|
134 |
+
section_contents = initial_data["contents"][
|
135 |
+
"twoColumnBrowseResultsRenderer"][
|
136 |
+
"tabs"][0]["tabRenderer"]["content"][
|
137 |
+
"sectionListRenderer"]["contents"]
|
138 |
+
try:
|
139 |
+
# Playlist without submenus
|
140 |
+
important_content = section_contents[
|
141 |
+
0]["itemSectionRenderer"][
|
142 |
+
"contents"][0]["playlistVideoListRenderer"]
|
143 |
+
except (KeyError, IndexError, TypeError):
|
144 |
+
# Playlist with submenus
|
145 |
+
important_content = section_contents[
|
146 |
+
1]["itemSectionRenderer"][
|
147 |
+
"contents"][0]["playlistVideoListRenderer"]
|
|
|
148 |
videos = important_content["contents"]
|
149 |
except (KeyError, IndexError, TypeError):
|
150 |
try:
|
tests/conftest.py
CHANGED
@@ -105,6 +105,19 @@ def playlist_long_html():
|
|
105 |
return f.read().decode("utf-8")
|
106 |
|
107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
@pytest.fixture
|
109 |
def stream_dict():
|
110 |
"""Youtube instance initialized with video id WXxV9g7lsFE."""
|
|
|
105 |
return f.read().decode("utf-8")
|
106 |
|
107 |
|
108 |
+
@pytest.fixture
|
109 |
+
def playlist_submenu_html():
|
110 |
+
"""Youtube playlist HTML loaded on 2020-01-24 from
|
111 |
+
https://www.youtube.com/playlist?list=PLZHQObOWTQDMsr9K-rj53DwVRMYO3t5Yr"""
|
112 |
+
file_path = os.path.join(
|
113 |
+
os.path.dirname(os.path.realpath(__file__)),
|
114 |
+
"mocks",
|
115 |
+
"playlist_submenu.html.gz",
|
116 |
+
)
|
117 |
+
with gzip.open(file_path, "rb") as f:
|
118 |
+
return f.read().decode("utf-8")
|
119 |
+
|
120 |
+
|
121 |
@pytest.fixture
|
122 |
def stream_dict():
|
123 |
"""Youtube instance initialized with video id WXxV9g7lsFE."""
|
tests/contrib/test_playlist.py
CHANGED
@@ -238,3 +238,20 @@ def test_trimmed_pagination_not_found(
|
|
238 |
playlist = Playlist(url) # noqa
|
239 |
# assert len(list(playlist.trimmed("wont-be-found"))) == 101 # noqa
|
240 |
assert True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
playlist = Playlist(url) # noqa
|
239 |
# assert len(list(playlist.trimmed("wont-be-found"))) == 101 # noqa
|
240 |
assert True
|
241 |
+
|
242 |
+
|
243 |
+
# test case for playlist with submenus
|
244 |
+
@mock.patch("pytube.contrib.playlist.request.get")
|
245 |
+
def test_playlist_submenu(
|
246 |
+
request_get, playlist_submenu_html):
|
247 |
+
url = "https://www.fakeurl.com/playlist?list=whatever"
|
248 |
+
request_get.side_effect = [
|
249 |
+
playlist_submenu_html,
|
250 |
+
'{"content_html":"<a '
|
251 |
+
'href=\\"/watch?v=BcWz41-4cDk&feature=plpp_video&ved'
|
252 |
+
'=CCYQxjQYACITCO33n5-pn-cCFUG3xAodLogN2yj6LA\\">}", '
|
253 |
+
'"load_more_widget_html":""}',
|
254 |
+
"{}",
|
255 |
+
]
|
256 |
+
playlist = Playlist(url)
|
257 |
+
assert len(playlist.video_urls) == 12
|
tests/mocks/playlist_submenu.html.gz
ADDED
Binary file (35.2 kB). View file
|
|