- def _fetch_tracks(self, base_url, video_id, dl_note=None, dl_errnote=None):
- # retrieve all fragments of a list of tracks with fake AJAX calls
- track_urls = []
- current_page = 1
- while True:
- # fake a AJAX request to retrieve a list fragment
- page_url = base_url + "?page=%d&list=main&_ajax=1" % current_page
- req = compat_urllib_request.Request(page_url, headers={"X-Requested-With": "XMLHttpRequest"}, method="GET")
- resp = self._download_webpage(req, video_id, note=dl_note + " (page %d)" % current_page, errnote=dl_errnote)
-
- # extract all track URLs from fragment
- urls = re.findall(r'm-play-button m-url="(?P<url>[^"]+)"', resp)
- # clean up URLs
- urls = map(clean_html, urls)
- # create absolute URLs
- urls = map(lambda u: "https://www.mixcloud.com" + u, urls)
- track_urls.extend(urls)
-
- # advance to next fragment, if any
- if " m-next-page-url=" in resp:
- current_page += 1
- else:
- break
-
- return track_urls
-
- def _handle_track_urls(self, urls):
- return map(lambda u: self.url_result(u, "Mixcloud"), urls)
-
- def _get_user_description(self, page_content):
- return self._html_search_regex(
- r'<div class="description-text">.*?<p>(?P<description>.*?)</p></div></div></div>',
- page_content,
- "user description",
- group="description",
- fatal=False,
- default="")
-
- def _get_username(self, page_content):
- return self._og_search_title(page_content)
-
- def _real_extract(self, url):
- mobj = re.match(self._VALID_URL, url)
- user_id = mobj.group("user")
- list_type = mobj.group("type")
-
- # if only a profile URL was supplied, default to download all uploads
- if list_type is None:
- list_type = "uploads"
-
- video_id = "%s/%s" % (user_id, list_type)
-
- # download the user's profile to retrieve some metadata
- profile = self._download_webpage("https://www.mixcloud.com/%s/" % user_id,
- video_id,
- note="Downloading user profile",
- errnote="Unable to download user profile")
-
- username = self._get_username(profile)
- description = self._get_user_description(profile)
-
- # retrieve all page fragments of uploads, favorites or listens
- track_urls = self._fetch_tracks(
- "https://www.mixcloud.com/%s/%s/" % (user_id, list_type),
- video_id,
- dl_note="Downloading list of %s" % list_type,
- dl_errnote="Unable to download list of %s" % list_type)
-
- # let MixcloudIE handle each track URL
- entries = self._handle_track_urls(track_urls)
-
- return {
- '_type': 'playlist',
- 'entries': entries,
- 'title': "%s (%s)" % (username, list_type),
- 'id': video_id,
- "description": description
- }